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": [
"config:base"
],
"labels": [
"🚨 Dependency Update"
]
}

View File

@ -6,8 +6,11 @@ on:
jobs:
comment:
name: Comment on Issue
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, '🐞 Bug Report')
steps:
- name: Query recent commits
uses: TheBusyBiscuit/recently-closed-issues@1.1.0
@ -44,8 +47,8 @@ jobs:
* [ ] Your issue has already been reported before, it is a duplicate. Check the other issues first before posting!
* [ ] You posted an error without using pastebin. Please always post errors via pastebin otherwise they become nearly unreadable.
* [ ] You seem to be reporting multiple bugs at once. Please make a separate issue for each bug you encountered, so we can properly handle them individually.
* [ ] Your issue has already been fixed in a later version of Slimefun or CS-CoreLib, you should update.
* [ ] You are using an outdated and unsupported version of Slimefun / CS-CoreLib, again, you should update.
* [ ] Your issue has already been fixed in a later version of Slimefun, you should update.
* [ ] You are using an outdated and unsupported version of Slimefun, again, you should update.
* [ ] You are using an unofficially modified build of Slimefun. We only support official versions of Slimefun - for obvious reasons.
* [ ] You are using an unsupported version of Minecraft. We only provide support for the Minecraft versions Slimefun was developed for, older versions are not supported anymore.
* [ ] You are using a \"stable\" version of Slimefun (prefixed with \"RC - \"), your issue may have been fixed in a development build, so we only accept bug reports from those.

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 -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of contents**
# Table of contents
- [Release Candidate 21 (TBD)](#release-candidate-21-tbd)
- [Release Candidate 20 (30 Jan 2021)](#release-candidate-20-30-jan-2021)
- [Release Candidate 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021)
- [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020)
- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020)
@ -22,15 +21,36 @@
- [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019)
- [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019)
<!-- 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
* Added a new language: Bulgarian
* Added a new language: Hebrew
* (API) Added AsyncProfileLoadEvent
* Added Talisman of the Wise
* Added Book Binder
* Added Tier 3 Electric Ore Grinder
#### Changes
* Massive performance improvements to holograms/armorstands
@ -50,6 +70,13 @@
* Fixed Infused Hopper picking up items with a max pickup delay
* Fixed duplication issues related to holograms/armorstands
* Fixed #2754
* Fixed machines not respecting max size from inventories
* Fixed #2761
* Fixed #2460
* Fixed #2760
* Fixed #2771
* Fixed placeholders that did not get loaded yet not having a label
* Fixed #2679
## Release Candidate 19 (11 Jan 2021)

12
pom.xml
View File

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

View File

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

View File

@ -388,7 +388,7 @@ public class PlayerProfile {
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p));
Bukkit.getPluginManager().callEvent(event);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, event.getProfile());
callback.accept(event.getProfile());
});

View File

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

View File

@ -19,7 +19,6 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* Represents a {@link Category} that cannot be opened until the parent category/categories
@ -153,14 +152,13 @@ public class LockedCategory extends Category {
* @return Whether the {@link Player} has fully completed all parent categories, otherwise false
*/
public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) {
Validate.notNull(p, "The player cannot be null!");
Validate.notNull(profile, "The Profile cannot be null!");
for (Category category : parents) {
for (SlimefunItem item : category.getItems()) {
/*
* Should probably be replaced with Slimefun.hasUnlocked(...)
* However this will result in better performance because we don't
* request the PlayerProfile everytime
*/
if (Slimefun.isEnabled(p, item, false) && Slimefun.hasPermission(p, item, false) && !profile.hasUnlocked(item.getResearch())) {
// Check if the Player has researched every item (if the item is enabled)
if (!item.isDisabledIn(p.getWorld()) && item.hasResearch() && !profile.hasUnlocked(item.getResearch())) {
return false;
}
}

View File

@ -3,18 +3,30 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.hover.content.Text;
/**
* This is our class for the /sf versions subcommand.
*
* @author TheBusyBiscuit
* @author Walshy
*
*/
class VersionsCommand extends SubCommand {
VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
@ -24,39 +36,171 @@ class VersionsCommand extends SubCommand {
@Override
public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (sender.hasPermission("slimefun.command.versions") || sender instanceof ConsoleCommandSender) {
// After all these years... Spigot still displays as "CraftBukkit"
// so we will just fix this inconsistency for them :)
/*
* After all these years... Spigot still displays as "CraftBukkit".
* so we will just fix this inconsistency for them :)
*/
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
ComponentBuilder builder = new ComponentBuilder();
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion()));
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
// @formatter:off
builder.append("This Server uses the following setup of Slimefun:\n")
.color(ChatColor.GRAY)
.append(serverSoftware)
.color(ChatColor.GREEN)
.append(" " + Bukkit.getVersion() + '\n')
.color(ChatColor.DARK_GREEN)
.append("Slimefun ")
.color(ChatColor.GREEN)
.append(SlimefunPlugin.getVersion() + '\n')
.color(ChatColor.DARK_GREEN);
// @formatter:on
if (SlimefunPlugin.getMetricsService().getVersion() != null) {
sender.sendMessage(ChatColors.color("&aMetrics build: &2#" + SlimefunPlugin.getMetricsService().getVersion()));
// @formatter:off
builder.append("Metrics-Module ")
.color(ChatColor.GREEN)
.append("#" + SlimefunPlugin.getMetricsService().getVersion() + '\n')
.color(ChatColor.DARK_GREEN);
// @formatter:on
}
addJavaVersion(builder);
if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) {
sender.sendMessage(ChatColor.RED + "Backwards compatibility enabled!");
// @formatter:off
HoverEvent hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(
"Backwards compatibility has a negative impact on performance!\n" +
"We recommend you to disable this setting unless your server still " +
"has legacy Slimefun items (from before summer 2019) in circulation."
));
// @formatter:on
builder.append("\nBackwards compatibility enabled!\n").color(ChatColor.RED).event(hoverEvent);
}
sender.sendMessage("");
builder.append("\n").event((HoverEvent) null);
addPluginVersions(builder);
Collection<Plugin> addons = SlimefunPlugin.getInstalledAddons();
sender.sendMessage(ChatColors.color("&7Installed Addons: &8(" + addons.size() + ")"));
for (Plugin plugin : addons) {
String version = plugin.getDescription().getVersion();
if (Bukkit.getPluginManager().isPluginEnabled(plugin)) {
sender.sendMessage(ChatColor.GREEN + " " + plugin.getName() + ChatColor.DARK_GREEN + " v" + version);
} else {
sender.sendMessage(ChatColor.RED + " " + plugin.getName() + ChatColor.DARK_RED + " v" + version);
}
}
sender.spigot().sendMessage(builder.create());
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
}
private void addJavaVersion(@Nonnull ComponentBuilder builder) {
String javaVer = System.getProperty("java.version");
if (javaVer.startsWith("1.")) {
javaVer = javaVer.substring(2);
}
// If it's like 11.0.1.3 or 8.0_275
if (javaVer.indexOf('.') != -1) {
javaVer = javaVer.substring(0, javaVer.indexOf('.'));
}
int version = Integer.parseInt(javaVer);
if (version < 11) {
// @formatter:off
builder.append("Java " + version).color(ChatColor.RED)
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(
"Your Java version is out of date!\n!" +
"You should use Java 11 or higher.\n" +
"Paper will be dropping support for older versions with the release of Minecraft 1.17."
)))
.append("\n")
.event((HoverEvent) null);
// @formatter:on
} else {
builder.append("Java ").color(ChatColor.GREEN).append(version + "\n").color(ChatColor.DARK_GREEN);
}
}
private void addPluginVersions(@Nonnull ComponentBuilder builder) {
Collection<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
@Override
public NamespacedKey getKey() {
return new NamespacedKey(SlimefunPlugin.instance(), "guide_layout");
return new NamespacedKey(SlimefunPlugin.instance(), "guide_mode");
}
@Nonnull
@ -46,25 +46,24 @@ class GuideModeOption implements SlimefunGuideOption<SlimefunGuideMode> {
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) {
SlimefunGuideMode layout = current.get();
SlimefunGuideMode selectedMode = current.get();
ItemStack item = new ItemStack(Material.AIR);
if (layout == SlimefunGuideMode.SURVIVAL_MODE) {
if (selectedMode == SlimefunGuideMode.SURVIVAL_MODE) {
item.setType(Material.CHEST);
} else {
item.setType(Material.COMMAND_BLOCK);
}
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Design: " + ChatColor.YELLOW + ChatUtils.humanize(layout.name()));
meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Type: " + ChatColor.YELLOW + ChatUtils.humanize(selectedMode.name()));
List<String> lore = new ArrayList<>();
lore.add("");
lore.add((layout == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Chest");
lore.add((layout == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
lore.add((selectedMode == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Survival Mode");
lore.add((selectedMode == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
lore.add("");
lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change your layout");
lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change the type");
meta.setLore(lore);
item.setItemMeta(meta);

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.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
@ -71,46 +73,127 @@ public final class SlimefunGuideSettings {
@ParametersAreNonnullByDefault
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) {
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
LocalizationService locale = SlimefunPlugin.getLocalization();
// @formatter:off
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE),
"&e\u21E6 " + locale.getMessage(p, "guide.back.title"),
"",
"&7" + locale.getMessage(p, "guide.back.guide")
));
// @formatter:on
menu.addMenuClickHandler(0, (pl, slot, item, action) -> {
SlimefunGuide.openGuide(pl, guide);
return false;
});
GitHubService github = SlimefunPlugin.getGitHubService();
List<String> contributorsLore = new ArrayList<>();
contributorsLore.add("");
contributorsLore.addAll(SlimefunPlugin.getLocalization().getMessages(p, "guide.credits.description", msg -> msg.replace("%contributors%", String.valueOf(SlimefunPlugin.getGitHubService().getContributors().size()))));
contributorsLore.addAll(locale.getMessages(p, "guide.credits.description", msg -> msg.replace("%contributors%", String.valueOf(github.getContributors().size()))));
contributorsLore.add("");
contributorsLore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.credits.open"));
contributorsLore.add("&7\u21E8 &e" + locale.getMessage(p, "guide.credits.open"));
menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.credits"), contributorsLore.toArray(new String[0])), (pl, slot, action, item) -> {
// @formatter:off
menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"),
"&c" + locale.getMessage(p, "guide.title.credits"),
contributorsLore.toArray(new String[0])
));
// @formatter:on
menu.addMenuClickHandler(2, (pl, slot, action, item) -> {
ContributorsMenu.open(pl, 0);
return false;
});
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.versions"), "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft: &a" + Bukkit.getBukkitVersion(), "&fSlimefun: &a" + SlimefunPlugin.getVersion()), ChestMenuUtils.getEmptyClickHandler());
// @formatter:off
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK,
ChatColor.GREEN + locale.getMessage(p, "guide.title.versions"),
"&7&o" + locale.getMessage(p, "guide.tooltips.versions-notice"),
"",
"&fMinecraft: &a" + Bukkit.getBukkitVersion(),
"&fSlimefun: &a" + SlimefunPlugin.getVersion()),
ChestMenuUtils.getEmptyClickHandler()
);
// @formatter:on
// @formatter:off
menu.addItem(6, new CustomItem(Material.COMPARATOR,
"&e" + locale.getMessage(p, "guide.title.source"),
"", "&7Last Activity: &a" + NumberUtils.getElapsedTime(github.getLastUpdate()) + " ago",
"&7Forks: &e" + github.getForks(),
"&7Stars: &e" + github.getStars(),
"",
"&7&oSlimefun 4 is a community project,",
"&7&othe source code is available on GitHub",
"&7&oand if you want to keep this Plugin alive,",
"&7&othen please consider contributing to it",
"",
"&7\u21E8 &eClick to go to GitHub"
));
// @formatter:on
menu.addItem(6,
new CustomItem(Material.COMPARATOR, "&e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.source"), "", "&7Last Activity: &a" + NumberUtils.getElapsedTime(SlimefunPlugin.getGitHubService().getLastUpdate()) + " ago", "&7Forks: &e" + SlimefunPlugin.getGitHubService().getForks(), "&7Stars: &e" + SlimefunPlugin.getGitHubService().getStars(), "", "&7&oSlimefun 4 is a community project,", "&7&othe source code is available on GitHub", "&7&oand if you want to keep this Plugin alive,", "&7&othen please consider contributing to it", "", "&7\u21E8 &eClick to go to GitHub"));
menu.addMenuClickHandler(6, (pl, slot, item, action) -> {
pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4");
return false;
});
menu.addItem(8, new CustomItem(Material.KNOWLEDGE_BOOK, "&3" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.wiki"), "", "&7Do you need help with an Item or machine?", "&7You cannot figure out what to do?", "&7Check out our community-maintained Wiki", "&7and become one of our Editors!", "", "&7\u21E8 &eClick to go to the official Slimefun Wiki"), (pl, slot, item, action) -> {
// @formatter:off
menu.addItem(8, new CustomItem(Material.KNOWLEDGE_BOOK,
"&3" + locale.getMessage(p, "guide.title.wiki"),
"", "&7Do you need help with an Item or machine?",
"&7You cannot figure out what to do?",
"&7Check out our community-maintained Wiki",
"&7and become one of our Editors!",
"",
"&7\u21E8 &eClick to go to the official Slimefun Wiki"
));
// @formatter:on
menu.addMenuClickHandler(8, (pl, slot, item, action) -> {
pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki");
return false;
});
menu.addItem(47, new CustomItem(Material.BOOKSHELF, "&3" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.addons"), "", "&7Slimefun is huge. But its addons are what makes", "&7this plugin truly shine. Go check them out, some", "&7of them may be exactly what you were missing out on!", "", "&7Installed on this Server: &b" + SlimefunPlugin.getInstalledAddons().size(), "", "&7\u21E8 &eClick to see all available Addons for Slimefun4"), (pl, slot, item, action) -> {
// @formatter:off
menu.addItem(47, new CustomItem(Material.BOOKSHELF,
"&3" + locale.getMessage(p, "guide.title.addons"),
"",
"&7Slimefun is huge. But its addons are what makes",
"&7this plugin truly shine. Go check them out, some",
"&7of them may be exactly what you were missing out on!",
"",
"&7Installed on this Server: &b" + SlimefunPlugin.getInstalledAddons().size(),
"",
"&7\u21E8 &eClick to see all available addons for Slimefun4"
));
// @formatter:on
menu.addMenuClickHandler(47, (pl, slot, item, action) -> {
pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki/Addons");
return false;
});
if (SlimefunPlugin.getUpdater().getBranch().isOfficial()) {
menu.addItem(49, new CustomItem(Material.REDSTONE_TORCH, "&4" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.bugs"), "", "&7&oBug reports have to be made in English!", "", "&7Open Issues: &a" + SlimefunPlugin.getGitHubService().getOpenIssues(), "&7Pending Pull Requests: &a" + SlimefunPlugin.getGitHubService().getPendingPullRequests(), "", "&7\u21E8 &eClick to go to the Slimefun4 Bug Tracker"), (pl, slot, item, action) -> {
// @formatter:off
menu.addItem(49, new CustomItem(Material.REDSTONE_TORCH,
"&4" + locale.getMessage(p, "guide.title.bugs"),
"",
"&7&oBug reports have to be made in English!",
"",
"&7Open Issues: &a" + github.getOpenIssues(),
"&7Pending Pull Requests: &a" + github.getPendingPullRequests(),
"",
"&7\u21E8 &eClick to go to the Slimefun4 Bug Tracker"
));
// @formatter:on
menu.addMenuClickHandler(49, (pl, slot, item, action) -> {
pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/issues");
return false;
@ -119,7 +202,7 @@ public final class SlimefunGuideSettings {
menu.addItem(49, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
}
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> {
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + locale.getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> {
// Add something here
return false;
});
@ -158,7 +241,8 @@ public final class SlimefunGuideSettings {
for (SlimefunGuideOption<?> option : options) {
if (option instanceof FireworksOption) {
FireworksOption fireworks = (FireworksOption) option;
return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE)).orElse(true);
ItemStack guide = SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE);
return fireworks.getSelectedOption(p, guide).orElse(true);
}
}

View File

@ -31,7 +31,6 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -114,10 +113,11 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace
}
}
@Nonnull
protected MultiBlockInteractionHandler getInteractionHandler() {
return (p, mb, b) -> {
if (mb.equals(getMultiBlock())) {
if (!isDisabled() && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK) && Slimefun.hasUnlocked(p, this, true)) {
if (canUse(p, true) && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK)) {
onInteract(p, b);
}

View File

@ -115,14 +115,14 @@ abstract class AbstractItemNetwork extends Network {
if (menu != null) {
switch (request.getDirection()) {
case INSERT:
distributeInsertionRequest(inventories, request, menu, iterator, destinations);
break;
case WITHDRAW:
collectExtractionRequest(inventories, request, menu, iterator, providers);
break;
default:
break;
case INSERT:
distributeInsertionRequest(inventories, request, menu, iterator, destinations);
break;
case WITHDRAW:
collectExtractionRequest(inventories, request, menu, iterator, providers);
break;
default:
break;
}
}
}

View File

@ -92,19 +92,19 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
}
switch (id) {
case "CARGO_MANAGER":
return NetworkComponent.REGULATOR;
case "CARGO_NODE":
return NetworkComponent.CONNECTOR;
case "CARGO_NODE_INPUT":
case "CARGO_NODE_OUTPUT":
case "CARGO_NODE_OUTPUT_ADVANCED":
case "CT_IMPORT_BUS":
case "CT_EXPORT_BUS":
case "CHEST_TERMINAL":
return NetworkComponent.TERMINUS;
default:
return null;
case "CARGO_MANAGER":
return NetworkComponent.REGULATOR;
case "CARGO_NODE":
return NetworkComponent.CONNECTOR;
case "CARGO_NODE_INPUT":
case "CARGO_NODE_OUTPUT":
case "CARGO_NODE_OUTPUT_ADVANCED":
case "CT_IMPORT_BUS":
case "CT_EXPORT_BUS":
case "CHEST_TERMINAL":
return NetworkComponent.TERMINUS;
default:
return null;
}
}
@ -123,24 +123,24 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
if (to == NetworkComponent.TERMINUS) {
String id = BlockStorage.checkID(l);
switch (id) {
case "CARGO_NODE_INPUT":
inputNodes.add(l);
break;
case "CARGO_NODE_OUTPUT":
case "CARGO_NODE_OUTPUT_ADVANCED":
outputNodes.add(l);
break;
case "CHEST_TERMINAL":
terminals.add(l);
break;
case "CT_IMPORT_BUS":
imports.add(l);
break;
case "CT_EXPORT_BUS":
exports.add(l);
break;
default:
break;
case "CARGO_NODE_INPUT":
inputNodes.add(l);
break;
case "CARGO_NODE_OUTPUT":
case "CARGO_NODE_OUTPUT_ADVANCED":
outputNodes.add(l);
break;
case "CHEST_TERMINAL":
terminals.add(l);
break;
case "CT_IMPORT_BUS":
imports.add(l);
break;
case "CT_EXPORT_BUS":
exports.add(l);
break;
default:
break;
}
}
}

View File

@ -68,19 +68,19 @@ final class CargoUtils {
Material type = block.getType();
switch (type) {
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case DROPPER:
case HOPPER:
case BREWING_STAND:
case BARREL:
case BLAST_FURNACE:
case SMOKER:
return true;
default:
return SlimefunTag.SHULKER_BOXES.isTagged(type);
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case DROPPER:
case HOPPER:
case BREWING_STAND:
case BARREL:
case BLAST_FURNACE:
case SMOKER:
return true;
default:
return SlimefunTag.SHULKER_BOXES.isTagged(type);
}
}

View File

@ -75,14 +75,14 @@ public class EnergyNet extends Network implements HologramOwner {
return null;
} else {
switch (component.getEnergyComponentType()) {
case CONNECTOR:
case CAPACITOR:
return NetworkComponent.CONNECTOR;
case CONSUMER:
case GENERATOR:
return NetworkComponent.TERMINUS;
default:
return null;
case CONNECTOR:
case CAPACITOR:
return NetworkComponent.CONNECTOR;
case CONSUMER:
case GENERATOR:
return NetworkComponent.TERMINUS;
default:
return null;
}
}
}
@ -98,21 +98,21 @@ public class EnergyNet extends Network implements HologramOwner {
if (component != null) {
switch (component.getEnergyComponentType()) {
case CAPACITOR:
capacitors.put(l, component);
break;
case CONSUMER:
consumers.put(l, component);
break;
case GENERATOR:
if (component instanceof EnergyNetProvider) {
generators.put(l, (EnergyNetProvider) component);
} else if (component instanceof SlimefunItem) {
((SlimefunItem) component).warn("This Item is marked as a GENERATOR but does not implement the interface EnergyNetProvider!");
}
break;
default:
break;
case CAPACITOR:
capacitors.put(l, component);
break;
case CONSUMER:
consumers.put(l, component);
break;
case GENERATOR:
if (component instanceof EnergyNetProvider) {
generators.put(l, (EnergyNetProvider) component);
} else if (component instanceof SlimefunItem) {
((SlimefunItem) component).warn("This Item is marked as a GENERATOR but does not implement the interface EnergyNetProvider!");
}
break;
default:
break;
}
}
}

View File

@ -29,38 +29,51 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
*/
public class BackupService implements Runnable {
/**
* The maximum amount of backups to maintain
*/
private static final int MAX_BACKUPS = 20;
/**
* Our {@link DateTimeFormatter} for formatting file names.
*/
private final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm", Locale.ROOT);
/**
* The directory in which to create the backups
*/
private final File directory = new File("data-storage/Slimefun/block-backups");
@Override
public void run() {
List<File> backups = Arrays.asList(directory.listFiles());
// Make sure that the directory exists.
if (directory.exists()) {
List<File> backups = Arrays.asList(directory.listFiles());
if (backups.size() > MAX_BACKUPS) {
try {
purgeBackups(backups);
} catch (IOException e) {
SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e);
}
}
File file = new File(directory, format.format(LocalDateTime.now()) + ".zip");
if (!file.exists()) {
try {
if (file.createNewFile()) {
try (ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file))) {
createBackup(output);
}
SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
} else {
SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
if (backups.size() > MAX_BACKUPS) {
try {
purgeBackups(backups);
} catch (IOException e) {
SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e);
}
}
File file = new File(directory, format.format(LocalDateTime.now()) + ".zip");
if (!file.exists()) {
try {
if (file.createNewFile()) {
try (ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file))) {
createBackup(output);
}
SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
} else {
SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
}
} catch (IOException x) {
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
}
} catch (IOException x) {
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
}
}
}

View File

@ -138,29 +138,29 @@ public class BlockDataService implements Keyed {
}
switch (type) {
case PLAYER_HEAD:
case PLAYER_WALL_HEAD:
case CHEST:
case DISPENSER:
case BREWING_STAND:
case DROPPER:
case FURNACE:
case BLAST_FURNACE:
case HOPPER:
case LECTERN:
case JUKEBOX:
case ENDER_CHEST:
case ENCHANTING_TABLE:
case DAYLIGHT_DETECTOR:
case SMOKER:
case BARREL:
case SPAWNER:
case BEACON:
// All of the above Materials are Tile Entities
return true;
default:
// Otherwise we assume they're not Tile Entities
return false;
case PLAYER_HEAD:
case PLAYER_WALL_HEAD:
case CHEST:
case DISPENSER:
case BREWING_STAND:
case DROPPER:
case FURNACE:
case BLAST_FURNACE:
case HOPPER:
case LECTERN:
case JUKEBOX:
case ENDER_CHEST:
case ENCHANTING_TABLE:
case DAYLIGHT_DETECTOR:
case SMOKER:
case BARREL:
case SPAWNER:
case BEACON:
// All of the above Materials are Tile Entities
return true;
default:
// Otherwise we assume they're not Tile Entities
return false;
}
}

View File

@ -1,6 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.services;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@ -10,6 +11,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
@ -34,9 +38,19 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunG
*/
public class MinecraftRecipeService {
/**
* Our {@link Plugin} instance
*/
private final Plugin plugin;
/**
* The subscriber list for the {@link RecipeSnapshot}.
*/
private final List<Consumer<RecipeSnapshot>> subscriptions = new LinkedList<>();
/**
* Our {@link RecipeSnapshot} - The centerpiece of this class.
*/
private RecipeSnapshot snapshot;
/**
@ -115,6 +129,7 @@ public class MinecraftRecipeService {
*
* @param recipe
* The {@link Recipe} to get the shape from
*
* @return An Array of {@link RecipeChoice} representing the shape of this {@link Recipe}
*/
@Nonnull
@ -149,6 +164,7 @@ public class MinecraftRecipeService {
*
* @param item
* The {@link ItemStack} for which to get the recipes
*
* @return An array of {@link Recipe Recipes} to craft the given {@link ItemStack}
*/
@Nonnull
@ -160,4 +176,27 @@ public class MinecraftRecipeService {
}
}
/**
* This returns the corresponding {@link Keyed} {@link Recipe} for the given {@link NamespacedKey}.
* If no {@link Recipe} was found, null will be returned.
* This is a significantly faster method over {@link Bukkit#getRecipe(NamespacedKey)} since we
* operate on a cached {@link HashMap}
*
* @param key
* The {@link NamespacedKey}
*
* @return The corresponding {@link Recipe} or null
*/
@Nullable
public Recipe getRecipe(@Nonnull NamespacedKey key) {
Validate.notNull(key, "The NamespacedKey should not be null");
if (snapshot != null) {
// We operate on a cached HashMap which is much faster than Bukkit's method.
return snapshot.getRecipe(key);
} else {
return Bukkit.getRecipe(key);
}
}
}

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

View File

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

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_2 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_2", Material.FURNACE, "&cElectric Ore Grinder &7(&eII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(4), LoreBuilder.powerPerSecond(30));
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_3 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_3", Material.FURNACE, "&cElectric Ore Grinder &7(&eIII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(10), LoreBuilder.powerPerSecond(90));
public static final SlimefunItemStack ELECTRIC_INGOT_PULVERIZER = new SlimefunItemStack("ELECTRIC_INGOT_PULVERIZER", Material.FURNACE, "&cElectric Ingot Pulverizer", "", "&fPulverizes Ingots into Dust", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(14));
public static final SlimefunItemStack AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10));
public static final SlimefunItemStack AUTO_ENCHANTER = new SlimefunItemStack("AUTO_ENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Enchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18));
@ -840,7 +841,9 @@ public final class SlimefunItems {
public static final SlimefunItemStack ELECTRIC_INGOT_FACTORY_2 = new SlimefunItemStack("ELECTRIC_INGOT_FACTORY_2", Material.RED_TERRACOTTA, "&cElectric Ingot Factory &7(&eII&7)", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.speed(2), LoreBuilder.powerPerSecond(14));
public static final SlimefunItemStack ELECTRIC_INGOT_FACTORY_3 = new SlimefunItemStack("ELECTRIC_INGOT_FACTORY_3", Material.RED_TERRACOTTA, "&cElectric Ingot Factory &7(&eIII&7)", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(8), LoreBuilder.powerPerSecond(40));
@Deprecated
public static final SlimefunItemStack AUTOMATED_CRAFTING_CHAMBER = new SlimefunItemStack("AUTOMATED_CRAFTING_CHAMBER", Material.CRAFTING_TABLE, "&6Automated Crafting Chamber", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &710 J/Item");
public static final SlimefunItemStack FLUID_PUMP = new SlimefunItemStack("FLUID_PUMP", Material.BLUE_TERRACOTTA, "&9Fluid Pump", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &732 J/Block");
public static final SlimefunItemStack CHARGING_BENCH = new SlimefunItemStack("CHARGING_BENCH", Material.CRAFTING_TABLE, "&6Charging Bench", "", "&fCharges Items such as Jetpacks", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.powerBuffer(128), "&8\u21E8 &e\u26A1 &7Energy Loss: &c50%");

View File

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

View File

@ -266,7 +266,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
SlimefunItem sfitem = category.getItems().get(target);
if (Slimefun.isEnabled(p, sfitem, false)) {
if (!sfitem.isDisabledIn(p.getWorld())) {
displaySlimefunItem(menu, category, p, profile, sfitem, page, index);
index++;
}
@ -613,7 +613,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
}
String lore = Slimefun.hasPermission(p, slimefunItem, false) ? "&fNeeds to be unlocked elsewhere" : "&fNo Permission";
return Slimefun.hasUnlocked(p, slimefunItem, false) ? item : new CustomItem(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", lore);
return slimefunItem.canUse(p, false) ? item : new CustomItem(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", lore);
} else {
return item;
}

View File

@ -38,20 +38,20 @@ public class ButcherAndroid extends ProgrammableAndroid {
boolean attack = false;
switch (face) {
case NORTH:
attack = n.getLocation().getZ() < b.getZ();
break;
case EAST:
attack = n.getLocation().getX() > b.getX();
break;
case SOUTH:
attack = n.getLocation().getZ() > b.getZ();
break;
case WEST:
attack = n.getLocation().getX() < b.getX();
break;
default:
break;
case NORTH:
attack = n.getLocation().getZ() < b.getZ();
break;
case EAST:
attack = n.getLocation().getX() > b.getX();
break;
case SOUTH:
attack = n.getLocation().getZ() > b.getZ();
break;
case WEST:
attack = n.getLocation().getX() < b.getX();
break;
default:
break;
}
if (attack) {

View File

@ -64,22 +64,22 @@ public class FarmerAndroid extends ProgrammableAndroid {
Random random = ThreadLocalRandom.current();
switch (crop) {
case WHEAT:
return new ItemStack(Material.WHEAT, random.nextInt(2) + 1);
case POTATOES:
return new ItemStack(Material.POTATO, random.nextInt(3) + 1);
case CARROTS:
return new ItemStack(Material.CARROT, random.nextInt(3) + 1);
case BEETROOTS:
return new ItemStack(Material.BEETROOT, random.nextInt(3) + 1);
case COCOA:
return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1);
case NETHER_WART:
return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1);
case SWEET_BERRY_BUSH:
return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
default:
return null;
case WHEAT:
return new ItemStack(Material.WHEAT, random.nextInt(2) + 1);
case POTATOES:
return new ItemStack(Material.POTATO, random.nextInt(3) + 1);
case CARROTS:
return new ItemStack(Material.CARROT, random.nextInt(3) + 1);
case BEETROOTS:
return new ItemStack(Material.BEETROOT, random.nextInt(3) + 1);
case COCOA:
return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1);
case NETHER_WART:
return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1);
case SWEET_BERRY_BUSH:
return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
default:
return null;
}
}

View File

@ -194,14 +194,14 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
*/
public AndroidFuelSource getFuelSource() {
switch (getTier()) {
case 1:
return AndroidFuelSource.SOLID;
case 2:
return AndroidFuelSource.LIQUID;
case 3:
return AndroidFuelSource.NUCLEAR;
default:
throw new IllegalStateException("Cannot convert the following Android tier to a fuel type: " + getTier());
case 1:
return AndroidFuelSource.SOLID;
case 2:
return AndroidFuelSource.LIQUID;
case 3:
return AndroidFuelSource.NUCLEAR;
default:
throw new IllegalStateException("Cannot convert the following Android tier to a fuel type: " + getTier());
}
}
@ -564,38 +564,38 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
private void registerDefaultFuelTypes() {
switch (getFuelSource()) {
case SOLID:
registerFuelType(new MachineFuel(80, new ItemStack(Material.COAL_BLOCK)));
registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
registerFuelType(new MachineFuel(70, new ItemStack(Material.DRIED_KELP_BLOCK)));
case SOLID:
registerFuelType(new MachineFuel(80, new ItemStack(Material.COAL_BLOCK)));
registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
registerFuelType(new MachineFuel(70, new ItemStack(Material.DRIED_KELP_BLOCK)));
// Coal & Charcoal
registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL)));
registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
// Coal & Charcoal
registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL)));
registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
// Logs
for (Material mat : Tag.LOGS.getValues()) {
registerFuelType(new MachineFuel(2, new ItemStack(mat)));
}
// Logs
for (Material mat : Tag.LOGS.getValues()) {
registerFuelType(new MachineFuel(2, new ItemStack(mat)));
}
// Wooden Planks
for (Material mat : Tag.PLANKS.getValues()) {
registerFuelType(new MachineFuel(1, new ItemStack(mat)));
}
// Wooden Planks
for (Material mat : Tag.PLANKS.getValues()) {
registerFuelType(new MachineFuel(1, new ItemStack(mat)));
}
break;
case LIQUID:
registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
registerFuelType(new MachineFuel(200, SlimefunItems.OIL_BUCKET));
registerFuelType(new MachineFuel(500, SlimefunItems.FUEL_BUCKET));
break;
case NUCLEAR:
registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM));
registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
break;
default:
throw new IllegalStateException("Unhandled Fuel Source: " + getFuelSource());
break;
case LIQUID:
registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
registerFuelType(new MachineFuel(200, SlimefunItems.OIL_BUCKET));
registerFuelType(new MachineFuel(500, SlimefunItems.FUEL_BUCKET));
break;
case NUCLEAR:
registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM));
registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
break;
default:
throw new IllegalStateException("Unhandled Fuel Source: " + getFuelSource());
}
}
@ -685,26 +685,26 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
BlockFace face = rotationData == null ? BlockFace.NORTH : BlockFace.valueOf(rotationData);
switch (instruction) {
case START:
case WAIT:
// We are "waiting" here, so we only move a step forward
BlockStorage.addBlockInfo(b, "index", String.valueOf(index));
break;
case REPEAT:
// "repeat" just means, we reset our index
BlockStorage.addBlockInfo(b, "index", String.valueOf(0));
break;
case CHOP_TREE:
// We only move to the next step if we finished chopping wood
if (chopTree(b, inv, face)) {
case START:
case WAIT:
// We are "waiting" here, so we only move a step forward
BlockStorage.addBlockInfo(b, "index", String.valueOf(index));
}
break;
default:
// We set the index here in advance to fix moving android issues
BlockStorage.addBlockInfo(b, "index", String.valueOf(index));
instruction.execute(this, b, inv, face);
break;
break;
case REPEAT:
// "repeat" just means, we reset our index
BlockStorage.addBlockInfo(b, "index", String.valueOf(0));
break;
case CHOP_TREE:
// We only move to the next step if we finished chopping wood
if (chopTree(b, inv, face)) {
BlockStorage.addBlockInfo(b, "index", String.valueOf(index));
}
break;
default:
// We set the index here in advance to fix moving android issues
BlockStorage.addBlockInfo(b, "index", String.valueOf(index));
instruction.execute(this, b, inv, face);
break;
}
}
}

View File

@ -1,8 +1,11 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
@ -14,9 +17,10 @@ import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.Vein;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialConverter;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -59,6 +63,7 @@ public class WoodcutterAndroid extends ProgrammableAndroid {
return true;
}
@ParametersAreNonnullByDefault
private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) {
ItemStack drop = new ItemStack(log.getType());
@ -67,13 +72,95 @@ public class WoodcutterAndroid extends ProgrammableAndroid {
log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType());
if (log.getY() == android.getRelative(face).getY()) {
Optional<Material> sapling = MaterialConverter.getSaplingFromLog(log.getType());
sapling.ifPresent(log::setType);
replant(log);
} else {
log.setType(Material.AIR);
}
}
}
private void replant(@Nonnull Block block) {
Material logType = block.getType();
Material saplingType = null;
Predicate<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.UUID;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
@ -13,10 +16,10 @@ import org.bukkit.block.Block;
import org.bukkit.block.Dispenser;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
@ -47,15 +50,17 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class BlockPlacer extends SlimefunItem {
private final ItemSetting<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) {
super(category, item, recipeType, recipe);
addItemSetting(blacklist);
addItemSetting(unplaceableBlocks);
addItemHandler(onPlace(), onBlockDispense());
}
@Nonnull
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@ -69,6 +74,7 @@ public class BlockPlacer extends SlimefunItem {
};
}
@Nonnull
private BlockDispenseHandler onBlockDispense() {
return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) {
@ -79,7 +85,7 @@ public class BlockPlacer extends SlimefunItem {
Material material = e.getItem().getType();
if (SlimefunTag.SHULKER_BOXES.isTagged(material)) {
/**
/*
* Since vanilla Dispensers can already place Shulker boxes,
* we simply fallback to the vanilla behaviour.
*/
@ -89,7 +95,7 @@ public class BlockPlacer extends SlimefunItem {
e.setCancelled(true);
if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) {
/**
/*
* Some materials cannot be reliably placed, like beds,
* it would look kinda wonky, so we just ignore these altogether.
* The event has already been cancelled too, so they won't drop.
@ -97,7 +103,7 @@ public class BlockPlacer extends SlimefunItem {
return;
}
if (facedBlock.isEmpty() && !isBlacklisted(material) && dispenser.getInventory().getViewers().isEmpty()) {
if (facedBlock.isEmpty() && isAllowed(material) && dispenser.getInventory().getViewers().isEmpty()) {
SlimefunItem item = SlimefunItem.getByItem(e.getItem());
if (item != null) {
@ -123,11 +129,12 @@ public class BlockPlacer extends SlimefunItem {
*
* @return Whether this action is permitted or not
*/
@ParametersAreNonnullByDefault
private boolean hasPermission(Dispenser dispenser, Block target) {
String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner");
if (owner == null) {
/**
/*
* If no owner was set, then we will fallback to the previous behaviour:
* Allowing block placers to bypass protection, newly placed Block placers
* will respect protection plugins.
@ -135,20 +142,30 @@ public class BlockPlacer extends SlimefunItem {
return true;
}
// Get the corresponding OfflinePlayer
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner));
return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK);
}
private boolean isBlacklisted(Material type) {
for (String blockType : blacklist.getValue()) {
/**
* This checks if the given {@link Material} is allowed to be placed.
*
* @param type
* The {@link Material} to check
*
* @return Whether placing this {@link Material} is allowed
*/
private boolean isAllowed(@Nonnull Material type) {
for (String blockType : unplaceableBlocks.getValue()) {
if (type.toString().equals(blockType)) {
return true;
return false;
}
}
return false;
return true;
}
@ParametersAreNonnullByDefault
private void placeSlimefunBlock(SlimefunItem sfItem, ItemStack item, Block block, Dispenser dispenser) {
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, block);
Bukkit.getPluginManager().callEvent(e);
@ -156,68 +173,78 @@ public class BlockPlacer extends SlimefunItem {
if (!e.isCancelled()) {
boolean hasItemHandler = sfItem.callItemHandler(BlockPlaceHandler.class, handler -> {
if (handler.isBlockPlacerAllowed()) {
block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
schedulePlacement(block, dispenser.getInventory(), item, () -> {
block.setType(item.getType());
BlockStorage.store(block, sfItem.getId());
BlockStorage.store(block, sfItem.getId());
handler.onBlockPlacerPlace(e);
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
} else {
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
handler.onBlockPlacerPlace(e);
});
}
});
if (!hasItemHandler) {
block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
BlockStorage.store(block, sfItem.getId());
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
} else {
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
schedulePlacement(block, dispenser.getInventory(), item, () -> {
block.setType(item.getType());
BlockStorage.store(block, sfItem.getId());
});
}
}
}
@ParametersAreNonnullByDefault
private void placeBlock(ItemStack item, Block facedBlock, Dispenser dispenser) {
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, facedBlock);
Bukkit.getPluginManager().callEvent(e);
if (!e.isCancelled()) {
facedBlock.setType(item.getType());
schedulePlacement(facedBlock, dispenser.getInventory(), item, () -> {
facedBlock.setType(item.getType());
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (meta.hasDisplayName()) {
BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false);
if (meta.hasDisplayName()) {
BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false);
if ((blockState.getState() instanceof Nameable)) {
Nameable nameable = ((Nameable) blockState.getState());
nameable.setCustomName(meta.getDisplayName());
if ((blockState.getState() instanceof Nameable)) {
Nameable nameable = ((Nameable) blockState.getState());
nameable.setCustomName(meta.getDisplayName());
if (blockState.isSnapshot()) {
// Update block state after changing name
blockState.getState().update(true, false);
if (blockState.isSnapshot()) {
// Update block state after changing name
blockState.getState().update(true, false);
}
}
}
}
}
facedBlock.getWorld().playEffect(facedBlock.getLocation(), Effect.STEP_SOUND, item.getType());
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
} else {
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
});
}
}
@ParametersAreNonnullByDefault
private void schedulePlacement(Block b, Inventory inv, ItemStack item, Runnable runnable) {
// We need to delay this due to Dispenser-Inventory synchronization issues in Spigot.
SlimefunPlugin.runSync(() -> {
// Make sure the Block has not been occupied yet
if (b.isEmpty()) {
// Only remove 1 item.
ItemStack removedItem = item.clone();
removedItem.setAmount(1);
// Play particles
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, item.getType());
// Make sure the item was actually removed (fixes #2817)
try {
if (inv.removeItem(removedItem).isEmpty()) {
runnable.run();
}
} catch (Exception x) {
error("An Exception was thrown while a BlockPlacer was performing its action", x);
}
}
}, 2L);
}
}

View File

@ -110,14 +110,14 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
return (e, item, offhand) -> {
// Fixes #2217 - Prevent them from being used to shear entities
switch (e.getRightClicked().getType()) {
case MUSHROOM_COW:
case SHEEP:
case SNOWMAN:
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
e.setCancelled(true);
break;
default:
break;
case MUSHROOM_COW:
case SHEEP:
case SNOWMAN:
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
e.setCancelled(true);
break;
default:
break;
}
};
}

View File

@ -7,6 +7,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -57,10 +60,11 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
private final Map<String, ItemStack> craftingRecipes = new HashMap<>();
@ParametersAreNonnullByDefault
public AutomatedCraftingChamber(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
new BlockMenuPreset(getId(), "&6Automated Crafting Chamber") {
new BlockMenuPreset(getId(), "&4Deprecated item. Do not use.") {
@Override
public void init() {
@ -94,6 +98,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
@Override
public boolean canOpen(Block b, Player p) {
p.sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!");
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
}
@ -145,6 +150,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
e.getPlayer().sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!");
BlockStorage.addBlockInfo(e.getBlock(), "enabled", String.valueOf(false));
}
@ -308,4 +314,4 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
craftingRecipes.put(builder.toString(), RecipeType.getRecipeOutputList(machine, inputs));
}
}
}
}

View File

@ -23,10 +23,10 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
* Represents Book Binder, a machine that binds multiple enchantments books into one.
*
* @author ProfElements
*/
* Represents Book Binder, a machine that binds multiple enchantments books into one.
*
* @author ProfElements
*/
public class BookBinder extends AContainer {
private final ItemSetting<Boolean> bypassVanillaMaxLevel = new ItemSetting<>("bypass-vanilla-max-level", false);
@ -36,29 +36,29 @@ public class BookBinder extends AContainer {
@ParametersAreNonnullByDefault
public BookBinder(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(bypassVanillaMaxLevel, hasCustomMaxLevel, customMaxLevel);
addItemSetting(bypassVanillaMaxLevel, hasCustomMaxLevel, customMaxLevel);
}
@Override
protected MachineRecipe findNextRecipe(BlockMenu menu) {
for (int slot : getInputSlots()) {
ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
ItemStack item = menu.getItemInSlot(slot);
if (isCompatible(item) && isCompatible(target)) {
if (isCompatible(item) && isCompatible(target)) {
EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) item.getItemMeta();
EnchantmentStorageMeta targetMeta = (EnchantmentStorageMeta) target.getItemMeta();
Map<Enchantment, Integer> storedItemEnchantments = itemMeta.getStoredEnchants();
Map<Enchantment, Integer> storedTargetEnchantments = targetMeta.getStoredEnchants();
Map<Enchantment, Integer> enchantments = combineEnchantments(storedItemEnchantments, storedTargetEnchantments);
if (enchantments.size() > 0) {
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta();
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
enchantMeta.addStoredEnchant(entry.getKey(), entry.getValue(), bypassVanillaMaxLevel.getValue());
}
@ -69,7 +69,7 @@ public class BookBinder extends AContainer {
book.setItemMeta(enchantMeta);
MachineRecipe recipe = new MachineRecipe(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] {target, item}, new ItemStack[] {book});
MachineRecipe recipe = new MachineRecipe(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] { target, item }, new ItemStack[] { book });
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
return null;
@ -109,8 +109,8 @@ public class BookBinder extends AContainer {
private Map<Enchantment, Integer> combineEnchantments(Map<Enchantment, Integer> ech1, Map<Enchantment, Integer> ech2) {
Map<Enchantment, Integer> enchantments = new HashMap<>();
boolean conflicts = false;
enchantments.putAll(ech1);
for (Map.Entry<Enchantment, Integer> entry : ech2.entrySet()) {
for (Map.Entry<Enchantment, Integer> conflictsWith : enchantments.entrySet()) {
if (entry.getKey().conflictsWith(conflictsWith.getKey())) {
@ -122,12 +122,12 @@ public class BookBinder extends AContainer {
}
}
if (!conflicts) {
enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> {
int enchantMaxLevel = entry.getKey().getMaxLevel();
if (a == b) {
if (a.intValue() == b.intValue()) {
if (enchantMaxLevel <= a) {
return enchantMaxLevel;
}
@ -136,7 +136,6 @@ public class BookBinder extends AContainer {
} else {
return a + 1;
}
} else {
int highestLevel = Math.max(a, b);
@ -149,13 +148,13 @@ public class BookBinder extends AContainer {
} else {
return highestLevel;
}
}
});
}
}
return enchantments;
}
});
}
}
return enchantments;
}
}

View File

@ -1,16 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotHopperable;
@ -22,13 +11,23 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenu
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
/**
* The {@link ElectricSmeltery} is an electric version of the standard {@link Smeltery}.
@ -112,12 +111,10 @@ public class ElectricSmeltery extends AContainer implements NotHopperable {
processing.remove(b);
return true;
});
this.registerDefaultRecipes();
}
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount();
return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
}
@Override

View File

@ -1,15 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
@ -22,6 +12,15 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class HeatedPressureChamber extends AContainer {
@ -73,12 +72,10 @@ public class HeatedPressureChamber extends AContainer {
}
}
};
this.registerDefaultRecipes();
}
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount();
return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
}
@Override

View File

@ -128,24 +128,24 @@ public abstract class Reactor extends AbstractEnergyProvider implements Hologram
ReactorMode mode = getReactorMode(b.getLocation());
switch (mode) {
case GENERATOR:
menu.replaceExistingItem(4, new CustomItem(SlimefunItems.NUCLEAR_REACTOR, "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7\u21E8 Click to change the Focus to &eProduction"));
menu.addMenuClickHandler(4, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, MODE, ReactorMode.PRODUCTION.toString());
updateInventory(menu, b);
return false;
});
break;
case PRODUCTION:
menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7\u21E8 Click to change the Focus to &ePower Generation"));
menu.addMenuClickHandler(4, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, MODE, ReactorMode.GENERATOR.toString());
updateInventory(menu, b);
return false;
});
break;
default:
break;
case GENERATOR:
menu.replaceExistingItem(4, new CustomItem(SlimefunItems.NUCLEAR_REACTOR, "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7\u21E8 Click to change the Focus to &eProduction"));
menu.addMenuClickHandler(4, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, MODE, ReactorMode.PRODUCTION.toString());
updateInventory(menu, b);
return false;
});
break;
case PRODUCTION:
menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7\u21E8 Click to change the Focus to &ePower Generation"));
menu.addMenuClickHandler(4, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, MODE, ReactorMode.GENERATOR.toString());
updateInventory(menu, b);
return false;
});
break;
default:
break;
}
BlockMenu port = getAccessPort(b.getLocation());

View File

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

View File

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

View File

@ -1,5 +1,18 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -7,20 +20,6 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link MagicianTalisman} is a special kind of {@link Talisman} which awards a {@link Player}
* with an extra {@link Enchantment} when they enchant their {@link ItemStack}.
@ -30,12 +29,16 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class MagicianTalisman extends Talisman {
private final ItemSetting<Boolean> allowEnchantmentBooks = new ItemSetting<>("allow-enchantment-books", false);
private final Set<TalismanEnchantment> enchantments = new HashSet<>();
@ParametersAreNonnullByDefault
public MagicianTalisman(SlimefunItemStack item, ItemStack[] recipe) {
super(item, recipe, false, false, "magician", 80);
addItemSetting(allowEnchantmentBooks);
for (Enchantment enchantment : Enchantment.values()) {
try {
for (int i = 1; i <= enchantment.getMaxLevel(); i++) {
@ -70,7 +73,7 @@ public class MagicianTalisman extends Talisman {
// @formatter:off
List<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(TalismanEnchantment::getValue)
.collect(Collectors.toList());
@ -90,4 +93,13 @@ public class MagicianTalisman extends Talisman {
return true;
}
/**
* This method checks whether enchantment books
* can be given an extra {@link Enchantment} or not.
*
* @return Whether enchantment books can receive an extra {@link Enchantment}
*/
public boolean isEnchantmentBookAllowed() {
return allowEnchantmentBooks.getValue();
}
}

View File

@ -9,6 +9,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
@ -33,7 +34,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Talisman extends SlimefunItem {
@ -113,10 +113,6 @@ public class Talisman extends SlimefunItem {
return effects;
}
protected String getMessageSuffix() {
return suffix;
}
protected boolean isEventCancelled() {
return cancel;
}
@ -147,36 +143,44 @@ public class Talisman extends SlimefunItem {
}
}
private static boolean hasMessage(@Nonnull Talisman talisman) {
return talisman.getMessageSuffix() != null;
@ParametersAreNonnullByDefault
public static boolean trigger(Event e, SlimefunItemStack stack) {
return trigger(e, stack.getItem(), true);
}
@ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItemStack stack) {
return checkFor(e, stack.getItem());
public static boolean trigger(Event e, SlimefunItemStack stack, boolean sendMessage) {
return trigger(e, stack.getItem(), sendMessage);
}
@ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItem item) {
public static boolean trigger(Event e, SlimefunItem item) {
return trigger(e, item, true);
}
@ParametersAreNonnullByDefault
public static boolean trigger(Event e, SlimefunItem item, boolean sendMessage) {
if (!(item instanceof Talisman)) {
return false;
}
Talisman talisman = (Talisman) item;
if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) {
return false;
}
Player p = getPlayerByEventType(e);
if (p == null || !pass(p, talisman)) {
if (p == null || !talisman.canEffectsBeApplied(p)) {
return false;
}
ItemStack talismanItem = talisman.getItem();
if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) {
activateTalisman(e, p, p.getInventory(), talisman, talismanItem);
if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getInventory(), talisman, talismanItem, sendMessage);
return true;
} else {
return false;
@ -185,8 +189,8 @@ public class Talisman extends SlimefunItem {
ItemStack enderTalisman = talisman.getEnderVariant();
if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman);
if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage);
return true;
} else {
return false;
@ -198,11 +202,30 @@ public class Talisman extends SlimefunItem {
}
@ParametersAreNonnullByDefault
private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem) {
private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem, boolean sendMessage) {
consumeItem(inv, talisman, talismanItem);
applyTalismanEffects(p, talisman);
cancelEvent(e, talisman);
sendMessage(p, talisman);
if (sendMessage) {
talisman.sendMessage(p);
}
}
@ParametersAreNonnullByDefault
private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) {
if (talisman.isConsumable()) {
ItemStack[] contents = inv.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack item = contents[i];
if (SlimefunUtils.isItemSimilar(item, talismanItem, true, false)) {
ItemUtils.consumeItem(item, false);
return;
}
}
}
}
@ParametersAreNonnullByDefault
@ -219,29 +242,63 @@ public class Talisman extends SlimefunItem {
}
}
@ParametersAreNonnullByDefault
private static void sendMessage(Player p, Talisman talisman) {
if (hasMessage(talisman)) {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.talisman." + talisman.getMessageSuffix(), true);
}
/**
* This returns whether the {@link Talisman} is silent.
* A silent {@link Talisman} will not send a message to a {@link Player}
* when activated.
*
* @return Whether this {@link Talisman} is silent
*/
public boolean isSilent() {
return getMessageSuffix() == null;
}
@ParametersAreNonnullByDefault
private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) {
if (talisman.isConsumable()) {
ItemStack[] contents = inv.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack item = contents[i];
@Nullable
protected final String getMessageSuffix() {
return suffix;
}
if (SlimefunUtils.isItemSimilar(item, talismanItem, true, false)) {
ItemUtils.consumeItem(item, false);
return;
/**
* This method sends the given {@link Player} the message of this {@link Talisman}.
* Dependent on the selected config setting, the message will be sent via the actionbar
* or in the chat window.
*
* @param p
* The {@link Player} who shall receive the message
*/
public void sendMessage(@Nonnull Player p) {
Validate.notNull(p, "The Player must not be null.");
// Check if this Talisman has a message
if (!isSilent()) {
try {
String messageKey = "messages.talisman." + getMessageSuffix();
if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) {
// Use the actionbar
SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false);
} else {
// Send the message via chat
SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true);
}
} catch (Exception x) {
error("An Exception was thrown while trying to send a Talisman message", x);
}
}
}
private static Player getPlayerByEventType(Event e) {
private boolean canEffectsBeApplied(@Nonnull Player p) {
for (PotionEffect effect : getEffects()) {
if (effect != null && p.hasPotionEffect(effect.getType())) {
return false;
}
}
return true;
}
@Nullable
private static Player getPlayerByEventType(@Nonnull Event e) {
if (e instanceof EntityDeathEvent) {
return ((EntityDeathEvent) e).getEntity().getKiller();
} else if (e instanceof BlockBreakEvent) {
@ -259,14 +316,4 @@ public class Talisman extends SlimefunItem {
return null;
}
private static boolean pass(Player p, SlimefunItem talisman) {
for (PotionEffect effect : ((Talisman) talisman).getEffects()) {
if (effect != null && p.hasPotionEffect(effect.getType())) {
return false;
}
}
return true;
}
}

View File

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

View File

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

View File

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

View File

@ -4,6 +4,7 @@ import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -27,6 +28,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class GrindStone extends MultiBlockMachine {
@ParametersAreNonnullByDefault
public GrindStone(Category category, SlimefunItemStack item) {
super(category, item, new ItemStack[] { null, null, null, null, new ItemStack(Material.OAK_FENCE), null, null, new CustomItem(Material.DISPENSER, "Dispenser (Facing up)"), null }, BlockFace.SELF);
}
@ -71,6 +73,9 @@ public class GrindStone extends MultiBlockMachine {
recipes.add(new ItemStack(Material.PRISMARINE));
recipes.add(new ItemStack(Material.PRISMARINE_SHARD, 4));
recipes.add(new ItemStack(Material.NETHER_WART_BLOCK));
recipes.add(new ItemStack(Material.NETHER_WART, 9));
}
@Override

View File

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

View File

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

View File

@ -120,21 +120,21 @@ public class IndustrialMiner extends MultiBlockMachine {
Random random = ThreadLocalRandom.current();
switch (ore) {
case COAL_ORE:
return new ItemStack(Material.COAL);
case DIAMOND_ORE:
return new ItemStack(Material.DIAMOND);
case EMERALD_ORE:
return new ItemStack(Material.EMERALD);
case NETHER_QUARTZ_ORE:
return new ItemStack(Material.QUARTZ);
case REDSTONE_ORE:
return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2));
case LAPIS_ORE:
return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4));
default:
// This includes Iron and Gold ore (and Ancient Debris)
return new ItemStack(ore);
case COAL_ORE:
return new ItemStack(Material.COAL);
case DIAMOND_ORE:
return new ItemStack(Material.DIAMOND);
case EMERALD_ORE:
return new ItemStack(Material.EMERALD);
case NETHER_QUARTZ_ORE:
return new ItemStack(Material.QUARTZ);
case REDSTONE_ORE:
return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2));
case LAPIS_ORE:
return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4));
default:
// This includes Iron and Gold ore (and Ancient Debris)
return new ItemStack(ore);
}
}

View File

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

View File

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

View File

@ -56,39 +56,39 @@ public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
Random random = ThreadLocalRandom.current();
switch (e.getEntityType()) {
case ZOMBIE:
if (random.nextInt(100) < chanceZombie.getValue()) {
e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD));
}
break;
case SKELETON:
if (random.nextInt(100) < chanceSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.SKELETON_SKULL));
}
break;
case CREEPER:
if (random.nextInt(100) < chanceCreeper.getValue()) {
e.getDrops().add(new ItemStack(Material.CREEPER_HEAD));
}
break;
case WITHER_SKELETON:
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
}
break;
case PLAYER:
if (random.nextInt(100) < chancePlayer.getValue()) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
case ZOMBIE:
if (random.nextInt(100) < chanceZombie.getValue()) {
e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD));
}
break;
case SKELETON:
if (random.nextInt(100) < chanceSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.SKELETON_SKULL));
}
break;
case CREEPER:
if (random.nextInt(100) < chanceCreeper.getValue()) {
e.getDrops().add(new ItemStack(Material.CREEPER_HEAD));
}
break;
case WITHER_SKELETON:
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
}
break;
case PLAYER:
if (random.nextInt(100) < chancePlayer.getValue()) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
ItemMeta meta = skull.getItemMeta();
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
skull.setItemMeta(meta);
ItemMeta meta = skull.getItemMeta();
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
skull.setItemMeta(meta);
e.getDrops().add(skull);
}
break;
default:
break;
e.getDrops().add(skull);
}
break;
default:
break;
}
};
}

View File

@ -41,7 +41,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for providing the core mechanics of the {@link AncientAltar}
@ -105,12 +104,13 @@ public class AncientAltarListener implements Listener {
}
String id = slimefunBlock.get().getId();
Player p = e.getPlayer();
if (id.equals(pedestalItem.getId())) {
e.cancel();
usePedestal(b, e.getPlayer());
usePedestal(b, p);
} else if (id.equals(altarItem.getId())) {
if (!Slimefun.hasUnlocked(e.getPlayer(), altarItem, true) || altarsInUse.contains(b.getLocation())) {
if (!altarItem.canUse(p, true) || altarsInUse.contains(b.getLocation())) {
e.cancel();
return;
}
@ -119,7 +119,7 @@ public class AncientAltarListener implements Listener {
altarsInUse.add(b.getLocation());
e.cancel();
useAltar(b, e.getPlayer());
useAltar(b, p);
}
}
@ -212,8 +212,9 @@ public class AncientAltarListener implements Listener {
}
Optional<ItemStack> result = getRecipeOutput(catalyst, input);
if (result.isPresent()) {
if (Slimefun.hasUnlocked(p, result.get(), true)) {
if (SlimefunUtils.canPlayerUseItem(p, result.get(), true)) {
List<ItemStack> consumed = new ArrayList<>();
consumed.add(catalyst);
@ -248,7 +249,7 @@ public class AncientAltarListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent e) {
if (altarItem == null || altarItem.isDisabled()) {
return;

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

View File

@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.BeeWings;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.BeeWingsTask;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for the slow falling effect given to the {@link Player}
@ -44,7 +43,7 @@ public class BeeWingsListener implements Listener {
Player player = (Player) e.getEntity();
ItemStack chestplate = player.getInventory().getChestplate();
if (wings.isItem(chestplate) && Slimefun.hasUnlocked(player, chestplate, true)) {
if (wings.isItem(chestplate) && wings.canUse(player, true)) {
new BeeWingsTask(player).scheduleRepeating(3, 1);
}
}

View File

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

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.items.backpacks.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} listens for a {@link FoodLevelChangeEvent} or an {@link EntityDamageEvent} for starvation
@ -74,7 +73,7 @@ public class CoolerListener implements Listener {
for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) {
if (Slimefun.hasUnlocked(p, cooler, true)) {
if (cooler.canUse(p, true)) {
takeJuiceFromCooler(p, item);
} else {
return;

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.SlimefunArmorPiece;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link Listener} for the {@link ElytraCap}.
@ -57,7 +56,7 @@ public class ElytraImpactListener implements Listener {
if (helmet.isPresent()) {
SlimefunItem item = helmet.get();
if (Slimefun.hasUnlocked(p, item, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) {
if (item.canUse(p, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) {
e.setDamage(0);
p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1);

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.Jetpack;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedMagnet;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.InfusedMagnetTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.JetBootsTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.JetpackTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.InfusedMagnetTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.ParachuteTask;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for listening to the {@link PlayerToggleSneakEvent}
@ -59,7 +58,7 @@ public class GadgetsListener implements Listener {
if (SlimefunUtils.containsSimilarItem(p.getInventory(), SlimefunItems.INFUSED_MAGNET, true)) {
InfusedMagnet magnet = (InfusedMagnet) SlimefunItems.INFUSED_MAGNET.getItem();
if (Slimefun.hasUnlocked(p, magnet, true)) {
if (magnet.canUse(p, true)) {
new InfusedMagnetTask(p, magnet.getRadius()).scheduleRepeating(0, 8);
}
}
@ -67,7 +66,7 @@ public class GadgetsListener implements Listener {
}
private void handleChestplate(@Nonnull Player p, @Nullable SlimefunItem chestplate) {
if (chestplate == null || !Slimefun.hasUnlocked(p, chestplate, true)) {
if (chestplate == null || !chestplate.canUse(p, true)) {
return;
}
@ -83,7 +82,7 @@ public class GadgetsListener implements Listener {
}
private void handleBoots(@Nonnull Player p, @Nullable SlimefunItem boots) {
if (boots instanceof JetBoots && Slimefun.hasUnlocked(p, boots, true)) {
if (boots instanceof JetBoots && boots.canUse(p, true)) {
double speed = ((JetBoots) boots).getSpeed();
if (speed > 0.2) {

View File

@ -62,8 +62,13 @@ public class MultiBlockListener implements Listener {
e.setCancelled(true);
MultiBlock mb = multiblocks.getLast();
mb.getSlimefunItem().callItemHandler(MultiBlockInteractionHandler.class, handler -> handler.onInteract(p, mb, b));
Bukkit.getPluginManager().callEvent(new MultiBlockInteractEvent(p, mb, b, e.getBlockFace()));
MultiBlockInteractEvent event = new MultiBlockInteractEvent(p, mb, b, e.getBlockFace());
Bukkit.getPluginManager().callEvent(event);
// Fixes #2809
if (!event.isCancelled()) {
mb.getSlimefunItem().callItemHandler(MultiBlockInteractionHandler.class, handler -> handler.onInteract(p, mb, b));
}
}
}

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

View File

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

View File

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

View File

@ -61,24 +61,24 @@ public class TalismanListener implements Listener {
public void onDamageGet(EntityDamageEvent e) {
if (e.getEntity() instanceof Player) {
if (e.getCause() == DamageCause.LAVA) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA);
Talisman.trigger(e, SlimefunItems.TALISMAN_LAVA);
}
if (e.getCause() == DamageCause.DROWNING) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER);
Talisman.trigger(e, SlimefunItems.TALISMAN_WATER);
}
if (e.getCause() == DamageCause.FALL) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL);
Talisman.trigger(e, SlimefunItems.TALISMAN_ANGEL);
}
if (e.getCause() == DamageCause.FIRE) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE);
Talisman.trigger(e, SlimefunItems.TALISMAN_FIRE);
}
if (e.getCause() == DamageCause.ENTITY_ATTACK) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR);
Talisman.trigger(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.trigger(e, SlimefunItems.TALISMAN_WARRIOR);
}
if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) {
@ -91,7 +91,7 @@ public class TalismanListener implements Listener {
if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) {
Projectile projectile = (Projectile) e.getDamager();
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
if (Talisman.trigger(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
Player p = (Player) e.getEntity();
returnProjectile(p, projectile);
}
@ -143,7 +143,7 @@ public class TalismanListener implements Listener {
// We are also excluding entities which can pickup items, this is not perfect
// but it at least prevents dupes by tossing items to zombies
if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) {
if (!entity.getCanPickupItems() && Talisman.trigger(e, SlimefunItems.TALISMAN_HUNTER)) {
Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops());
for (ItemStack drop : extraDrops) {
@ -192,7 +192,7 @@ public class TalismanListener implements Listener {
@EventHandler
public void onItemBreak(PlayerItemBreakEvent e) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) {
if (Talisman.trigger(e, SlimefunItems.TALISMAN_ANVIL)) {
PlayerInventory inv = e.getPlayer().getInventory();
int slot = inv.getHeldItemSlot();
@ -225,7 +225,7 @@ public class TalismanListener implements Listener {
@EventHandler
public void onSprint(PlayerToggleSprintEvent e) {
if (e.isSprinting()) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_TRAVELLER);
Talisman.trigger(e, SlimefunItems.TALISMAN_TRAVELLER);
}
}
@ -235,31 +235,39 @@ public class TalismanListener implements Listener {
Map<Enchantment, Integer> enchantments = e.getEnchantsToAdd();
// Magician Talisman
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MAGICIAN)) {
MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem();
TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet());
MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem();
TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet());
if (enchantment != null) {
if (enchantment != null && Talisman.trigger(e, SlimefunItems.TALISMAN_MAGICIAN)) {
/*
* Fix #2679
* By default, the Bukkit API doesn't allow us to give enchantment books extra enchantments.
*/
if (talisman.isEnchantmentBookAllowed() && e.getItem().getType() == Material.BOOK) {
e.getItem().addUnsafeEnchantment(enchantment.getEnchantment(), enchantment.getLevel());
} else {
enchantments.put(enchantment.getEnchantment(), enchantment.getLevel());
}
}
// Wizard Talisman
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) {
for (Enchantment enchantment : enchantments.keySet()) {
if (random.nextInt(100) < 40) {
e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1);
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.trigger(e, SlimefunItems.TALISMAN_WIZARD)) {
// Randomly lower some enchantments
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
if (entry.getValue() > 1 && random.nextInt(100) < 40) {
enchantments.put(entry.getKey(), entry.getValue() - 1);
}
}
// Give an extra Fortune boost (Lvl 3 - 5)
enchantments.put(Enchantment.LOOT_BONUS_BLOCKS, random.nextInt(3) + 3);
}
}
@EventHandler(ignoreCancelled = true)
public void onExperienceReceive(PlayerExpChangeEvent e) {
if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) {
// Check if the experience change was positive.
if (e.getAmount() > 0 && Talisman.trigger(e, SlimefunItems.TALISMAN_WISE)) {
// Double-XP
e.setAmount(e.getAmount() * 2);
}
@ -267,21 +275,27 @@ public class TalismanListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onBlockDropItems(BlockDropItemEvent e) {
// We only want to double ores
Material type = e.getBlockState().getType();
if (type.name().endsWith("_ORE")) {
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
// We are going to ignore Silk Touch here
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
Material type = e.getBlockState().getType();
// We only want to double ores
if (SlimefunTag.MINER_TALISMAN_TRIGGERS.isTagged(type)) {
Collection<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));
// Keep track of whether we actually doubled the drops or not
boolean doubledDrops = false;
// Loop through all dropped items
for (Item drop : drops) {
ItemStack droppedItem = drop.getItemStack();
// We do not want to dupe blocks
if (!droppedItem.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount());
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount));
@ -289,8 +303,14 @@ public class TalismanListener implements Listener {
}
}
// Fixes #2077
if (doubledDrops) {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.miner", true);
Talisman talisman = SlimefunItems.TALISMAN_MINER.getItem(Talisman.class);
// Fixes #2818
if (talisman != null) {
talisman.sendMessage(e.getPlayer());
}
}
}
}
@ -300,7 +320,7 @@ public class TalismanListener implements Listener {
@EventHandler
public void onBlockBreak(BlockBreakEvent e) {
if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN);
Talisman.trigger(e, SlimefunItems.TALISMAN_CAVEMAN);
}
}

View File

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

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.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link Listener} responsible for a {@link Player} interacting with an {@link Entity}.
@ -48,7 +47,7 @@ public class EntityInteractionListener implements Listener {
SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
if (sfItem != null) {
if (Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) {
if (sfItem.canUse(e.getPlayer(), true)) {
sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
} else if (sfItem.getState() != ItemState.VANILLA_FALLBACK) {
/*

View File

@ -18,7 +18,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for handling any custom mob drops.
@ -55,7 +54,7 @@ public class MobDropListener implements Listener {
if (item.getType() != Material.AIR) {
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null && Slimefun.hasUnlocked(p, sfItem, true)) {
if (sfItem != null && sfItem.canUse(p, true)) {
sfItem.callItemHandler(EntityKillHandler.class, handler -> handler.onKill(e, e.getEntity(), p, item));
}
}
@ -63,21 +62,21 @@ public class MobDropListener implements Listener {
}
private boolean canDrop(@Nonnull Player p, @Nonnull ItemStack item) {
SlimefunItem sfi = SlimefunItem.getByItem(item);
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfi == null) {
if (sfItem == null) {
return true;
} else if (Slimefun.hasUnlocked(p, sfi, true)) {
if (sfi instanceof RandomMobDrop) {
} else if (sfItem.canUse(p, true)) {
if (sfItem instanceof RandomMobDrop) {
int random = ThreadLocalRandom.current().nextInt(100);
if (((RandomMobDrop) sfi).getMobDropChance() <= random) {
if (((RandomMobDrop) sfItem).getMobDropChance() <= random) {
return false;
}
}
if (sfi instanceof BasicCircuitBoard) {
return ((BasicCircuitBoard) sfi).isDroppedFromGolems();
if (sfItem instanceof BasicCircuitBoard) {
return ((BasicCircuitBoard) sfItem).isDroppedFromGolems();
}
return true;

View File

@ -32,56 +32,56 @@ class OilResource extends SlimefunResource {
}
switch (biome) {
case SNOWY_BEACH:
case STONE_SHORE:
case BEACH:
return 6;
case SNOWY_BEACH:
case STONE_SHORE:
case BEACH:
return 6;
case DESERT:
case DESERT_HILLS:
case DESERT_LAKES:
return 45;
case DESERT:
case DESERT_HILLS:
case DESERT_LAKES:
return 45;
case MOUNTAINS:
case GRAVELLY_MOUNTAINS:
case MOUNTAIN_EDGE:
case RIVER:
return 17;
case MOUNTAINS:
case GRAVELLY_MOUNTAINS:
case MOUNTAIN_EDGE:
case RIVER:
return 17;
case SNOWY_MOUNTAINS:
case SNOWY_TUNDRA:
case ICE_SPIKES:
case FROZEN_OCEAN:
case FROZEN_RIVER:
return 14;
case SNOWY_MOUNTAINS:
case SNOWY_TUNDRA:
case ICE_SPIKES:
case FROZEN_OCEAN:
case FROZEN_RIVER:
return 14;
case BADLANDS:
case BADLANDS_PLATEAU:
case WOODED_BADLANDS_PLATEAU:
case ERODED_BADLANDS:
case MODIFIED_BADLANDS_PLATEAU:
case MODIFIED_WOODED_BADLANDS_PLATEAU:
case MUSHROOM_FIELDS:
case MUSHROOM_FIELD_SHORE:
return 24;
case BADLANDS:
case BADLANDS_PLATEAU:
case WOODED_BADLANDS_PLATEAU:
case ERODED_BADLANDS:
case MODIFIED_BADLANDS_PLATEAU:
case MODIFIED_WOODED_BADLANDS_PLATEAU:
case MUSHROOM_FIELDS:
case MUSHROOM_FIELD_SHORE:
return 24;
case DEEP_OCEAN:
case OCEAN:
case COLD_OCEAN:
case DEEP_COLD_OCEAN:
case DEEP_FROZEN_OCEAN:
case DEEP_LUKEWARM_OCEAN:
case DEEP_WARM_OCEAN:
case LUKEWARM_OCEAN:
case WARM_OCEAN:
return 62;
case DEEP_OCEAN:
case OCEAN:
case COLD_OCEAN:
case DEEP_COLD_OCEAN:
case DEEP_FROZEN_OCEAN:
case DEEP_LUKEWARM_OCEAN:
case DEEP_WARM_OCEAN:
case LUKEWARM_OCEAN:
case WARM_OCEAN:
return 62;
case SWAMP:
case SWAMP_HILLS:
return 20;
case SWAMP:
case SWAMP_HILLS:
return 20;
default:
return 10;
default:
return 10;
}
}

View File

@ -26,33 +26,33 @@ class SaltResource extends SlimefunResource {
}
switch (biome) {
case SNOWY_BEACH:
case STONE_SHORE:
case BEACH:
case DESERT_LAKES:
case RIVER:
case ICE_SPIKES:
case FROZEN_RIVER:
return 40;
case SNOWY_BEACH:
case STONE_SHORE:
case BEACH:
case DESERT_LAKES:
case RIVER:
case ICE_SPIKES:
case FROZEN_RIVER:
return 40;
case DEEP_OCEAN:
case OCEAN:
case COLD_OCEAN:
case DEEP_COLD_OCEAN:
case DEEP_FROZEN_OCEAN:
case DEEP_LUKEWARM_OCEAN:
case DEEP_WARM_OCEAN:
case FROZEN_OCEAN:
case LUKEWARM_OCEAN:
case WARM_OCEAN:
return 60;
case DEEP_OCEAN:
case OCEAN:
case COLD_OCEAN:
case DEEP_COLD_OCEAN:
case DEEP_FROZEN_OCEAN:
case DEEP_LUKEWARM_OCEAN:
case DEEP_WARM_OCEAN:
case FROZEN_OCEAN:
case LUKEWARM_OCEAN:
case WARM_OCEAN:
return 60;
case SWAMP:
case SWAMP_HILLS:
return 20;
case SWAMP:
case SWAMP_HILLS:
return 20;
default:
return 6;
default:
return 6;
}
}

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_nodes", 206, "Cargo Setup", 30, SlimefunItems.CARGO_INPUT_NODE, SlimefunItems.CARGO_OUTPUT_NODE);
register("electric_ingot_machines", 207, "Electric Ingot Fabrication", 18, SlimefunItems.ELECTRIC_GOLD_PAN, SlimefunItems.ELECTRIC_DUST_WASHER, SlimefunItems.ELECTRIC_INGOT_FACTORY);
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2);
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2, SlimefunItems.ELECTRIC_ORE_GRINDER_3);
register("automated_crafting_chamber", 210, "Automated Crafting", 20, SlimefunItems.AUTOMATED_CRAFTING_CHAMBER);
register("better_food_fabricator", 211, "Upgraded Food Fabrication", 28, SlimefunItems.FOOD_FABRICATOR_2, SlimefunItems.FOOD_COMPOSTER_2);
register("reactor_access_port", 212, "Reactor Interaction", 18, SlimefunItems.REACTOR_ACCESS_PORT);

View File

@ -1666,6 +1666,13 @@ public final class SlimefunItemSetup {
.setProcessingSpeed(4)
.register(plugin);
new ElectricOreGrinder(categories.electricity, SlimefunItems.ELECTRIC_ORE_GRINDER_3, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.REINFORCED_PLATE, SlimefunItems.HEATING_COIL, SlimefunItems.REINFORCED_PLATE, null, SlimefunItems.ELECTRIC_ORE_GRINDER_2, null, SlimefunItems.REINFORCED_PLATE, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.REINFORCED_PLATE})
.setCapacity(1024)
.setEnergyConsumption(45)
.setProcessingSpeed(10)
.register(plugin);
new HeatedPressureChamber(categories.electricity, SlimefunItems.HEATED_PRESSURE_CHAMBER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.LEAD_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, new ItemStack(Material.GLASS), SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, SlimefunItems.HEATING_COIL, SlimefunItems.LEAD_INGOT})
.setCapacity(128)

View File

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

View File

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

View File

@ -47,6 +47,28 @@ public enum ColoredMaterial {
Material.BLACK_WOOL
}),
/**
* This {@link List} contains all carpet colors ordered by their appearance ingame.
*/
CARPET(new Material[] {
Material.WHITE_CARPET,
Material.ORANGE_CARPET,
Material.MAGENTA_CARPET,
Material.LIGHT_BLUE_CARPET,
Material.YELLOW_CARPET,
Material.LIME_CARPET,
Material.PINK_CARPET,
Material.GRAY_CARPET,
Material.LIGHT_GRAY_CARPET,
Material.CYAN_CARPET,
Material.PURPLE_CARPET,
Material.BLUE_CARPET,
Material.BROWN_CARPET,
Material.GREEN_CARPET,
Material.RED_CARPET,
Material.BLACK_CARPET
}),
/**
* This {@link List} contains all stained glass colors ordered by their appearance ingame.
*/

View File

@ -15,6 +15,7 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -358,4 +359,31 @@ public final class SlimefunUtils {
SlimefunPlugin.runSync(new CapacitorTextureUpdateTask(l, charge, capacity));
}
/**
* This checks whether the {@link Player} is able to use the given {@link ItemStack}.
* It will always return <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.items.blocks.BlockPlacer;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel;
@ -120,6 +121,12 @@ public enum SlimefunTag implements Tag<Material> {
*/
DIRT_VARIANTS,
/**
* All soil blocks for a fungus to grow on.
* This includes all dirt variants, nylium and soul soil.
*/
FUNGUS_SOIL,
/**
* All variants of concrete powder.
* Can you believe there is no tag for this already?
@ -184,6 +191,11 @@ public enum SlimefunTag implements Tag<Material> {
*/
INDUSTRIAL_MINER_ORES,
/**
* All materials (ores) which can be doubled using a Miner {@link Talisman}.
*/
MINER_TALISMAN_TRIGGERS,
/**
* All materials (crops) which the {@link CropGrowthAccelerator} will recognize.
*/
@ -210,8 +222,16 @@ public enum SlimefunTag implements Tag<Material> {
*/
CAVEMAN_TALISMAN_TRIGGERS;
/**
* Lookup table for tag names.
*/
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 {
for (SlimefunTag tag : valuesCache) {

View File

@ -59,49 +59,49 @@ public class CustomItemSerializer {
builder.append(flag.toString() + "=");
switch (flag) {
case AMOUNT: {
builder.append(item.getAmount());
break;
}
case DATA: {
builder.append((int) item.getData().getData());
break;
}
case DURABILITY: {
builder.append((int) item.getDurability());
break;
}
case ENCHANTMENTS:
for (Enchantment enchantment : Enchantment.values()) {
if (item.getEnchantments().containsKey(enchantment)) {
builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment));
} else {
builder.append(enchantment.getName() + ":0");
case AMOUNT: {
builder.append(item.getAmount());
break;
}
case DATA: {
builder.append((int) item.getData().getData());
break;
}
case DURABILITY: {
builder.append((int) item.getDurability());
break;
}
case ENCHANTMENTS:
for (Enchantment enchantment : Enchantment.values()) {
if (item.getEnchantments().containsKey(enchantment)) {
builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment));
} else {
builder.append(enchantment.getName() + ":0");
}
}
break;
case ITEMMETA_DISPLAY_NAME: {
if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&"));
} else {
builder.append("NONE");
}
break;
}
break;
case ITEMMETA_DISPLAY_NAME: {
if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&"));
} else {
builder.append("NONE");
case ITEMMETA_LORE: {
if (item.hasItemMeta() && item.getItemMeta().hasLore()) {
builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&"));
} else {
builder.append("NONE");
}
break;
}
break;
}
case ITEMMETA_LORE: {
if (item.hasItemMeta() && item.getItemMeta().hasLore()) {
builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&"));
} else {
builder.append("NONE");
case MATERIAL: {
builder.append(item.getType().toString());
break;
}
break;
}
case MATERIAL: {
builder.append(item.getType().toString());
break;
}
default:
break;
default:
break;
}
i++;

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.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* Represents a category, which structure multiple {@link SlimefunItem} in the {@link SlimefunGuide}.
@ -258,7 +257,7 @@ public class Category implements Keyed {
*/
public boolean isHidden(@Nonnull Player p) {
for (SlimefunItem slimefunItem : getItems()) {
if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) {
if (!slimefunItem.isHidden() && !slimefunItem.isDisabledIn(p.getWorld())) {
return false;
}
}

View File

@ -16,9 +16,11 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.Permission;
import io.github.thebusybiscuit.cscorelib2.collections.OptionalMap;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
@ -32,6 +34,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.UnregisteredItemExcepti
import io.github.thebusybiscuit.slimefun4.api.exceptions.WrongItemStackException;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotConfigurable;
import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable;
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive;
@ -377,6 +380,26 @@ public class SlimefunItem implements Placeable {
return state != ItemState.ENABLED;
}
/**
* This method returns whether this {@link SlimefunItem} is disabled
* for that specific {@link World}.
* Note that if the item is disabled globally, this method will still return false.
*
* @param world
* The {@link World} to check
*
* @return Whether this {@link SlimefunItem} is disabled in that world (or in general).
*/
public boolean isDisabledIn(@Nonnull World world) {
if (state == ItemState.UNREGISTERED) {
error("isDisabled(World) cannot be called before registering the item", new UnregisteredItemException(this));
return false;
}
// Check if the Item is disabled globally or in this specific world
return isDisabled() || !SlimefunPlugin.getWorldSettingsService().isEnabled(world, this);
}
/**
* This method returns the {@link SlimefunAddon} that registered this
* {@link SlimefunItem}. If this Item is from Slimefun itself, the current
@ -996,7 +1019,6 @@ public class SlimefunItem implements Placeable {
*/
public void error(@Nonnull String message, @Nonnull Throwable throwable) {
Validate.notNull(addon, "Cannot send an error for an unregistered item!");
addon.getLogger().log(Level.SEVERE, "Item \"{0}\" from {1} v{2} has caused an Error!", new Object[] { id, addon.getName(), addon.getPluginVersion() });
if (addon.getBugTrackerURL() != null) {
@ -1012,6 +1034,90 @@ public class SlimefunItem implements Placeable {
}
}
/**
* This method checks if the given {@link Player} is able to use this {@link SlimefunItem}.
* A {@link Player} can use it if the following conditions apply:
*
* <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
public final boolean equals(Object obj) {
if (obj instanceof SlimefunItem) {

View File

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

View File

@ -60,7 +60,7 @@ public interface InventoryBlock {
@Override
public boolean canOpen(Block b, Player p) {
return p.hasPermission("slimefun.inventory.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES) && Slimefun.hasUnlocked(p, item, false));
return p.hasPermission("slimefun.inventory.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK) && Slimefun.hasUnlocked(p, item, false));
}
};
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,25 +1,26 @@
---
slimefun:
armor: Brnění
basic_machines: Základní stroje
birthday: TheBusyBiscuitovy narozeniny (26. Říjen)
cargo: Cargo systém
christmas: Vánoce (Prosinec)
easter: Velikonoce (Duben)
electricity: Energie a elektrika
ender_talismans: Ender Talismany (Tier II)
food: Jídlo
gps: GPS stroje
halloween: Halloween (31. Října)
items: Užitečné itemy
magical_armor: Magická zbroj
magical_gadgets: Magické pomůcky
magical_items: Magické itemy
resources: Materiály
talismans: Talismany (Tier I)
tech_misc: Technické komponenty
technical_gadgets: Technické pomůcky
tools: Nástroje
weapons: Zbraně
misc: Smíšené položky
valentines_day: Svatého Valentýna (14. Února)
tools: Nástroje
items: Užitečné předměty
food: Jídlo
basic_machines: Základní stroje
electricity: Energie a elektrika
gps: GPS stroje
armor: Brnění
magical_items: Magické předměty
magical_gadgets: Magické pomůcky
misc: Smíšené předměty
technical_gadgets: Technické pomůcky
resources: Materiály
cargo: Cargo systém
tech_misc: Technické komponenty
magical_armor: Magická zbroj
talismans: Talismany (Tier I)
ender_talismans: Enderitové talismany (Tier II)
christmas: Vánoce (prosinec)
valentines_day: Svatého Valentýna (14. února)
easter: Velikonoce (duben)
birthday: TheBusyBiscuitovy narozeniny (26. říjen)
halloween: Halloween (31. října)
androids: Programovatelné androidy

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,18 @@
---
commands:
help: הצגת מסך עזרה
teleporter: ראה נקודות ציון של שחקנים אחרים
search: חפש במדריך את המונח הנתון
cheat: מאפשר לזמן פריטים ברמאות
give: נותן למישהו פירטי סליים פאן
guide: תן לעצמך מדריך סליים פאן
teleporter: ראה נקודות ציון של שחקנים אחרים
versions: הצגת תוספים מותקנים
search: חפש במדריך את המונח הנתון
open_guide: פתח את המדריך בלי להשתמש בספר
stats: מציג כמה נתונים סטטיסטיים על שחקן
research:
description: 'בטל נעילה /מחקרים עבור שחקן זה '
reset: "&c איפס את הידע של %שחקן% זה"
reset-target: "&cהידע שלך אופס "
backpack:
description: אחזר עותק של גיבוי קיים
invalid-id: " המספר המזהה חייב להיות מספר לא שלילי!&4"
@ -21,46 +28,15 @@ commands:
please-wait: "&e !אנא המתן שנייה ... התוצאות מגיעות"
verbose-player: "&4 האיתות המילולי אינו יכול להיות בשימוש על ידי שחקן!"
unknown-flag: "&4איתות לא ידוע: &c%flag%"
versions: הצגת תוספים מותקנים
open_guide: פתח את המדריך בלי להשתמש בספר
stats: מציג כמה נתונים סטטיסטיים על שחקן
research:
description: 'בטל נעילה /מחקרים עבור שחקן זה '
reset: "&c איפס את הידע של %שחקן% זה"
reset-target: "&cהידע שלך אופס "
guide:
title:
main: סליים פאן מדריך
credits: סליים פאן4 תורמים
wiki: סליים פאן4 ויקי
addons: 'תוספות לסליים פאן '
versions: גרסאות מותקנות
settings: 'הגדרות & מידע '
languages: בחר את השפה המועדפת עליך
bugs: דיווחי שגיאות
source: קוד מקור
back:
guide: חזור למדריך סליים פאן
title: חזור
settings: חזור ללוח ההגדרות
tooltips:
wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי
recipes:
climbing-pick: משטחים שאפשר לטפס עליהם
machine: מתכונים שנעשו במכונה זו
miner: משאבים שתוכלו להשיג אצל כורה זה
generator: סוגי דלק זמינים
gold-pan: משאבים שתוכלו להשיג
open-category: לחץ לפתיחה
versions-notice: אלה חשובים מאוד כשמדווחים על באגים!
work-in-progress: תכונה זו עדיין לא הושלמה במלואה!
search:
message: מה תרצה לחפש?
name: "&7חפש...."
tooltip: "&b לחץ לחפש פריט"
inventory: "%item% מחפש עבור: "
cheat:
no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!"
languages:
change: לחץ כדי לבחור שפה חדשה
description:
- "&7כעת יש לך אפשרות לשנות"
- "&7השפה שבה סליים פאן"
- "&7יוצג בפניך. פריטים"
- "&7לא ניתן לתרגם לעת עתה."
updated: "&a :השפה שלך הוגדרה בהצלחה ל &b%lang%"
translations:
name: "&aIs משהו חסר?"
@ -68,13 +44,23 @@ guide:
select: 'לחץ כדי לבחור שפה זאת '
select-default: לחץ לבחירת שפת ברירת המחדל
selected-language: 'נבחר כעת:'
credits:
open: לחץ כדי לראות את התורמים שלנו
change: לחץ כדי לבחור שפה חדשה
description:
- "&7 סליים פאן הוא פרויקט קוד פתוח "
- "&7ומתוחזק על ידי קהילה גדולה של אנשים."
- "&7על &e%contributors% &7אנשים עבדו"
- "&7.סליים פאן לאורך כל השנים האלה "
- "&7כעת יש לך אפשרות לשנות"
- "&7השפה שבה סליים פאן"
- "&7יוצג בפניך. פריטים"
- "&7לא ניתן לתרגם לעת עתה."
title:
main: סליים פאן מדריך
settings: 'הגדרות & מידע '
languages: בחר את השפה המועדפת עליך
credits: סליים פאן4 תורמים
wiki: סליים פאן4 ויקי
addons: 'תוספות לסליים פאן '
bugs: דיווחי שגיאות
source: קוד מקור
versions: גרסאות מותקנות
credits:
commit: להתחייב
commits: מתחייב
roles:
@ -83,32 +69,60 @@ guide:
resourcepack: "&c אמן חבילת משאבים"
translator: "&9מתרגם"
profile-link: "לחץ כדי לבקר את הפרופיל שלהם \nב -GitHub"
search:
message: &b מה תרצה לחפש?
name: "&7חפש...."
tooltip: "&b לחץ לחפש פריט"
inventory: "%item% מחפש עבור: "
cheat:
no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!"
open: לחץ כדי לראות את התורמים שלנו
description:
- "&7 סליים פאן הוא פרויקט קוד פתוח "
- "&7ומתוחזק על ידי קהילה גדולה של אנשים."
- "&7על &e%contributors% &7אנשים עבדו"
- "&7.סליים פאן לאורך כל השנים האלה "
pages:
previous: עמוד קודם
next: עמוד הבא
tooltips:
open-category: לחץ לפתיחה
versions-notice: אלה חשובים מאוד כשמדווחים על באגים!
wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי
recipes:
machine: מתכונים שנעשו במכונה זו
miner: משאבים שתוכלו להשיג אצל כורה זה
generator: סוגי דלק זמינים
gold-pan: משאבים שתוכלו להשיג
climbing-pick: משטחים שאפשר לטפס עליהם
back:
title: חזור
guide: חזור למדריך סליים פאן
settings: חזור ללוח ההגדרות
locked: נעול
locked-category:
- כדי לבטל את הנעילה של קטגוריה זו
- 'צריך לפתוח את כל הפריטים מה '
- הקטגוריות הבאות
work-in-progress: תכונה זו עדיין לא הושלמה במלואה!
messages:
not-researched: "&4אין לך מספיק ידע להבין זאת "
not-enough-xp: "&4אין לך מספיק נקודות ניסיון\nכדי לפתוח את זה "
unlocked: "&b אתה פתחת %research% "
only-players: "&4 פקודה זו מיועדת רק לשחקנים"
unknown-player: "&4 :שחקן לא מוכר &c%player%"
no-permission: "&4 אין לך את ההרשאה הנדרשת לעשות זאת"
usage: "&4 שימוש: &c %שימוש%"
not-online: "&4 %שחקן%cis לא ברשת!"
given-item: '&b ניתן לך סכום &a %amount% &7"%item%7'
give-item: "&b %ניתן לך %amount% &a %item%"
give-research: '&b נתת %player% את המח"%research%&7"'
hungry: "&cאתה רעב מדיי כדי לעשות את זה!"
disabled-in-world: "&4 פריט זה הושבת בעולם זה"
disabled-item: "&4 פריט זה הושבת איך בכלל השגת את זה ?"
no-tome-yourself: "&c אינך יכול להשתמש ב- 4 כרך של מידע צמך...."
multimeter: "&bStored Energy: &3%stored% &b/ &3%capacity%"
talisman:
angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה"
fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
caveman: "&a&oהקמע שלך נתן לך מהירות"
anvil: "&a&o הקמע שלך הציל את הכלי שלך מלהישבר"
miner: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
hunter: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
lava: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
water: "&a&oהקמע שלך הציל אותך מלטבוע "
angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה"
fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
magician: "&a%o הקמע שלך העניק לך כישוף נוסף"
traveller: "&a&o הקמע שלך נתן לך דחיפת מהירות"
warrior: "&a&oהקמע שלך שיפר את כוחך לזמן מה"
@ -116,54 +130,8 @@ messages:
whirlwind: "&a&o הקמע שלך שיקף את הטיל"
wizard: "&a&o הקמע שלך העניק לך רמת הון טובה יותר אבל אולי גם הוריד כמה רמות הקסם
אחרות"
fortune-cookie:
- "&7 עזור לי, אני כלוא במפעל לעוגיות "
- "&7אתה תמות מחר על ידי.... קריפר "
- "&7 בשלב מסוים בחיים שלך משהו רע יקרה!!!"
- "&7בשבוע הבא תבחין שזה לא העולם האמיתי, אתה נמצא במשחק מחשב"
- "עוגיה זו תהיה טעימה תוך כמה שניות &7"
- '&7 המילה האחרונה שתשמע תהיה "להשמיד !!!"'
- "&7מה שלא תעשה אל תחבק קריפר ניסיתי. זה מרגיש טוב,אבל לא שווה את זה"
- "&7התשובה היא 42"
- "&7 וולשי ביום ירחיקו את הצרות."
- "&7 לעולם אל תחפור ישר למטה!"
- "&7זו רק שריטה!"
- "&7תמיד תסתכל על הצד הטוב שבחיים"
- "&7זה היה למעשה ביסקוויט ולא עוגיה"
- "&7שלטי הניאון דולקים"
piglin-barter: &4 אתה לא יכול לסחור עם חזירונים באמצעות חפצי סליים פאן
enchantment-rune:
fail: "&cאת לא יכול להחליף עם חזירונים חפצים של סליים פאן."
no-enchantment: "&cלא נמצא שום קסם ישים לפריט הזה."
success: "&aהחלת בהצלחה קסם אקראי החל על פריט זה."
tape-measure:
no-anchor: "&c אתה צריך להגדיר עוגן לפני שתוכל להתחיל למדוד!"
wrong-world: "!&cנראה שהעוגן שלך נמצא בעולם אחר"
distance: "&7המדידה נלקחה &eDistance: %distance%."
anchor-set: "&aהעוגן הוגדר בהצלחה:&e %anchor%"
multi-tool:
mode-change: "&b%device% &9: המצב השתנה ל: %mode%"
not-shears: "&c מולטי טול לא יכול לשמש כמזמרה!"
climbing-pick:
dual-wielding: "&4אתה צריך להחזיק מכושי טיפוס בשתי !הידיים כדי להשתמש בהם"
wrong-material: "&cאתה לא יכול לטפס על המשטח הזה. עיין במדריך סליים פאן למידע
נוסף!"
bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה"
not-researched: "&4אין לך מספיק ידע להבין זאת "
unlocked: "&b אתה פתחת %research% "
only-players: "&4 פקודה זו מיועדת רק לשחקנים"
unknown-player: "&4 :שחקן לא מוכר &c%player%"
no-permission: "&4 אין לך את ההרשאה הנדרשת לעשות זאת"
usage: "&4 שימוש: &c %שימוש%"
not-online: "&4 %שחקן%cis לא ברשת!"
given-item: "&b ניתן לך סכום &a %amount% &7\"%item%7"
give-item: '&b %ניתן לך %amount% &a %item%'
give-research: "&b נתת %player% את המח\"%research%&7\""
hungry: "&cאתה רעב מדיי כדי לעשות את זה!"
disabled-in-world: "&4 פריט זה הושבת בעולם זה"
disabled-item: "&4 פריט זה הושבת איך בכלל השגת את זה ?"
no-tome-yourself: "&c אינך יכול להשתמש ב- 4 כרך של מידע צמך...."
multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%'
caveman: "&a&oהקמע שלך נתן לך מהירות"
wise: "&a&oהקמע שלך הכפיל את ירידת נקודות הניסיון שלך"
soulbound-rune:
fail: "&c אתה יכול לקשור פריט אחד בלבד לנשמתך בכל פעם."
success: "&a אתה קושרת פריט זה בהצלחה לנשמתך! אתה תשמור עליו כשתמות."
@ -182,87 +150,43 @@ messages:
ברזל!"
link-prompt: "&e לחץ כאן:"
diet-cookie: "&eאתה מתחיל להרגיש מרחף...."
fortune-cookie:
- "&7 עזור לי, אני כלוא במפעל לעוגיות "
- "&7אתה תמות מחר על ידי.... קריפר "
- "&7 בשלב מסוים בחיים שלך משהו רע יקרה!!!"
- "&7בשבוע הבא תבחין שזה לא העולם האמיתי, אתה נמצא במשחק מחשב"
- עוגיה זו תהיה טעימה תוך כמה שניות &7
- '&7 המילה האחרונה שתשמע תהיה "להשמיד !!!"'
- "&7מה שלא תעשה אל תחבק קריפר ניסיתי. זה מרגיש טוב,אבל לא שווה את זה"
- "&7התשובה היא 42"
- "&7 וולשי ביום ירחיקו את הצרות."
- "&7 לעולם אל תחפור ישר למטה!"
- "&7זו רק שריטה!"
- "&7תמיד תסתכל על הצד הטוב שבחיים"
- "&7זה היה למעשה ביסקוויט ולא עוגיה"
- "&7שלטי הניאון דולקים"
piglin-barter: אתה לא יכול לסחור עם חזירונים באמצעות חפצי סליים פאן
enchantment-rune:
fail: "&cאת לא יכול להחליף עם חזירונים חפצים של סליים פאן."
no-enchantment: "&cלא נמצא שום קסם ישים לפריט הזה."
success: "&aהחלת בהצלחה קסם אקראי החל על פריט זה."
tape-measure:
no-anchor: "&c אתה צריך להגדיר עוגן לפני שתוכל להתחיל למדוד!"
wrong-world: "!&cנראה שהעוגן שלך נמצא בעולם אחר"
distance: "&7המדידה נלקחה &eDistance: %distance%."
anchor-set: "&aהעוגן הוגדר בהצלחה:&e %anchor%"
multi-tool:
mode-change: "&b%device% &9: המצב השתנה ל: %mode%"
not-shears: "&c מולטי טול לא יכול לשמש כמזמרה!"
climbing-pick:
dual-wielding: "&4אתה צריך להחזיק מכושי טיפוס בשתי !הידיים כדי להשתמש בהם"
wrong-material: "&cאתה לא יכול לטפס על המשטח הזה. עיין במדריך סליים פאן למידע
נוסף!"
invalid-item: "&4%item% &cאינו פריט בר תוקף!"
invalid-amount: "&4%amount% &cאינו כמות ברת תוקף : המספר חייב להיות גדול מאפס!"
invalid-research: "&4%research% &cאינו מחקר בר תוקף!"
anvil:
not-working: "&4אתה לא יכול להשתמש בפרטי סליים פאן בתוך סדן"
mcmmo-salvaging: "&4אתה לא יכול להציל (לתקן) חפצי סליים פאן"
workbench:
not-enhanced: "&4 אתה לא יכול להשתמש בפרטי סליים פאן על שולחן עבודה רגיל"
gps:
geo:
scan-required: |-
&4-סורק גאולוגי נדרש!
&c סרוק את הנתח הזה באמצעות סורק !גאולוגי-קודם
waypoint:
duplicate: "&4כבר יצרת נקודת ציון בשם: &f%waypoint%"
new: "&eהקלד שם לנקודת הדרך החדשה שלך בצ'אט. (קודי צבע נתמכים!)"
added: "&a נוסף בהצלחה נקודת דרך חדשה"
max: "&4 הגעת לכמות הנקודות הדרך המרבית"
deathpoint: |-
&4נקודת מוות
&7%date%
insufficient-complexity:
- "&4אין מספיק מורכבות ברשת ה GPS: &c%complexity%"
- "&4a) אין לך הגדרות רשת GPS עדיין"
- "&4b) הגדרות ה GPS שלך לא מספיק מורכבות"
languages:
zh-CN: "(מנדרינית(סין"
tl: טגלית
default: שרת ברירת מחדל
en: אנגלית
de: 'גרמנית '
fr: צרפתית
it: איטלקית
es: ספרדית
pl: פולנית
sv: שוודית
nl: הולנדית
cs: צ'כית
hu: הונגרית
lv: לטבית
ru: רוסית
sk: סלובקית
zh-TW: "(סינית (טייוואן"
vi: וייטנאמי
id: אינדונזית
el: יווני
he: עברית
ar: ערבית
af: אפריקנית
da: דנית
fi: פינית
uk: אוקראינית
ms: מלאית
'no': נורווגית
ja: יפנית
fa: פרסית
th: תאילנדי
ro: רומנית
pt: "(פורטוגזית (פורטוגל"
pt-BR: "(פורטוגזית (ברזיל"
bg: בולגרית
ko: קוריאנית
tr: טורקי
hr: קרואטית
mk: מקדונית
sr: סרבית
be: בלארוסית
bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה"
machines:
GPS_CONTROL_PANEL:
title: לוח בקרה - ג'י פי אס
transmitters: סקירה משדר
waypoints: סקירת נקודות דרך
INDUSTRIAL_MINER:
no-fuel: &c לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל.
piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!"
piston-space: "&cלשתי הבוכנות צריך להיות בלוק מעליהן!"
destroyed: "&cנראה שכורה התעשייתי שלך הושמד."
already-running: "&cהכורה התעשייתית הזה עדיין פועל."
full-chest: "&cהתיבה של הכורה התעשייתי שלך מלאה!"
no-permission: נראה שאין לך אישור להפעיל כאן כורה תעשייתי!&4
finished: "&eהכורה התעשייתי שלך סיים את !%ores% ore(s)!עבודתו! הוא חצב"
pattern-not-found: "&e סליחה לא יכולתי \n .לזהות את המתכון \nאנא הכנס את \nהפריטים
בדפוס הנכון לתוך המתקן "
unknown-material: "&e סליחה, לא יכולתי לזהות את הפריט במתקן שלי. אנא הכנס משהו שאני
@ -273,7 +197,8 @@ machines:
in-use: "&c המלאי של בלוק זה נפתח כרגע על ידי שחקן אחר."
ignition-chamber-no-flint: "&c תא הצתה חסר צור ופלדה."
ANCIENT_ALTAR:
not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals% /\n8( "
not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals%
/\n8( "
unknown-catalyst: "&4 זרז לא ידוע! &c השתמש במתכון הנכון במקום זאת!"
unknown-recipe: "&4 מתכון לא ידוע! &cהשתמש במתכון הנכון במקום!"
ANCIENT_PEDESTAL:
@ -301,17 +226,50 @@ machines:
time: זמן משוער
CARGO_NODES:
must-be-placed: "&4חייב להיות מונח על תיבה או מכונה!"
brewing_stand:
not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!"
villagers:
no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!"
cartography_table:
not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!"
cauldron:
no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן"
GPS_CONTROL_PANEL:
title: לוח בקרה - ג'י פי אס
transmitters: סקירה משדר
waypoints: סקירת נקודות דרך
INDUSTRIAL_MINER:
no-fuel: לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל.
piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!"
piston-space: "&cלשתי הבוכנות צריך להיות בלוק מעליהן!"
destroyed: "&cנראה שכורה התעשייתי שלך הושמד."
already-running: "&cהכורה התעשייתית הזה עדיין פועל."
full-chest: "&cהתיבה של הכורה התעשייתי שלך מלאה!"
no-permission: נראה שאין לך אישור להפעיל כאן כורה תעשייתי!&4
finished: "&eהכורה התעשייתי שלך סיים את !%ores% ore(s)!עבודתו! הוא חצב"
anvil:
not-working: "&4אתה לא יכול להשתמש בפרטי סליים פאן בתוך סדן"
mcmmo-salvaging: "&4אתה לא יכול להציל (לתקן) חפצי סליים פאן"
backpack:
already-open: "&cסליחה התרמיל הזה פתוח במקום אחר "
no-stack: "&cאתה לא יכול לערום תרמילים"
workbench:
not-enhanced: "&4 אתה לא יכול להשתמש בפרטי סליים פאן על שולחן עבודה רגיל"
gps:
deathpoint: |-
&4נקודת מוות
&7%date%
waypoint:
new: "&eהקלד שם לנקודת הדרך החדשה שלך בצ'אט. (קודי צבע נתמכים!)"
added: "&a נוסף בהצלחה נקודת דרך חדשה"
max: "&4 הגעת לכמות הנקודות הדרך המרבית"
duplicate: "&4כבר יצרת נקודת ציון בשם: &f%waypoint%"
insufficient-complexity:
- "&4אין מספיק מורכבות ברשת ה GPS: &c%complexity%"
- "&4a) אין לך הגדרות רשת GPS עדיין"
- "&4b) הגדרות ה GPS שלך לא מספיק מורכבות"
geo:
scan-required: |-
&4-סורק גאולוגי נדרש!
&c סרוק את הנתח הזה באמצעות סורק !גאולוגי-קודם
inventory:
no-access: "&4אין לך גישה לבלוק הזה"
android:
started: "&7 האנדרואיד שלך ממשיך את תסריט"
stopped: "&7 האנדרואיד שלך \nעצר את התסריט "
scripts:
too-long: "&c!התסריט ארוך מכדי לערוך"
already-uploaded: "&4 התסריט הזה כבר הועלה."
instructions:
START: "&2 התחל תסריט"
@ -350,10 +308,56 @@ android:
own: "&4אתה לא יכול לדרג את התסריט שלך עצמך!"
already: "&4אתה כבר השארת דירוג לתסריט זה!"
editor: עורך תסריט
started: "&7 האנדרואיד שלך ממשיך את תסריט"
stopped: "&7 האנדרואיד שלך \nעצר את התסריט "
backpack:
already-open: "&cסליחה התרמיל הזה פתוח במקום אחר "
no-stack: "&cאתה לא יכול לערום תרמילים"
inventory:
no-access: "&4אין לך גישה לבלוק הזה"
too-long: "&c!התסריט ארוך מכדי לערוך"
languages:
default: שרת ברירת מחדל
en: אנגלית
de: 'גרמנית '
fr: צרפתית
it: איטלקית
es: ספרדית
pl: פולנית
sv: שוודית
nl: הולנדית
cs: צ'כית
hu: הונגרית
lv: לטבית
ru: רוסית
sk: סלובקית
zh-TW: "(מנדרינית (טייוואן"
vi: וייטנאמי
id: אינדונזית
zh-CN: "(מנדרינית(סין"
el: יווני
he: עברית
ar: ערבית
af: אפריקנית
da: דנית
fi: פינית
uk: אוקראינית
ms: מלאית
'no': נורווגית
ja: יפנית
fa: פרסית
th: תאילנדי
ro: רומנית
pt: "(פורטוגזית (פורטוגל"
pt-BR: "(פורטוגזית (ברזיל"
bg: בולגרית
ko: קוריאנית
tr: טורקי
hr: קרואטית
mk: מקדונית
sr: סרבית
be: בלארוסית
tl: טגלית
brewing_stand:
not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!"
villagers:
no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!"
cartography_table:
not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!"
cauldron:
no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן"
placeholderapi:
profile-loading: בטעינה...

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

View File

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

View File

@ -4,7 +4,6 @@ commands:
cheat: Geeft je toestemming om gratis spullen in het spel te brengen
give: Geef iemand een aantal Slimefun spullen
guide: Geef jezelf een Slimefun Handboek
timings: Laat informatie over de server's prestaties zien
teleporter: Bekijk de opgeslagen locaties van andere spelers
versions: Laat een lijst met alle geïnstalleerde uitbreidingen zien
search: Doorzoek de Slimefun handleiding voor een bepaald trefwoord
@ -15,6 +14,18 @@ commands:
description: Ontgrendel of herstart Slimefun kennissen van een speler
reset: "&cJe hebt %player%'s Slimefun kennis herstart"
reset-target: "&cJe Slimefun kennis is herstart"
backpack:
description: Krijg een kopie van een al bestaande rugzak
invalid-id: "&4Het id moet een positieve nummer zijn!"
player-never-joined: "&4Er is geen speler met die naam gevonden!"
backpack-does-not-exist: "& 4De opgegeven rugzak bestaat niet!"
restored-backpack-given: "&aJouw rugzak is hersteld en is toegevoegd aan jouw
inventaris."
charge:
description: Laad het item wat je vasthoud op
charge-success: Item is opgeladen!
not-rechargeable: Dit item kan niet opgeladen worden!
timings: Laat informatie over de server's prestaties zien
guide:
search:
message: "&bOp welk woord zou je willen zoeken?"
@ -22,8 +33,8 @@ guide:
tooltip: "&bKlik om naar een item te zoeken"
inventory: 'Zoeken naar: %item%'
lore:
- "&bOp welk woord zou je willen zoeken?"
- "&7Type je zoekterm in het gespreksvenster"
'1': "&7Type je zoekterm in het gespreksvenster"
'0': "&bOp welk woord zou je willen zoeken?"
cheat:
no-multiblocks: "&4Je kan geen Slimefun machines in het spel brengen, je moet
ze bouwen zoals aangegeven."
@ -34,7 +45,13 @@ guide:
lore: Klik om een eigen vertaling toe the voegen
select: Klik om deze taal te selecteren
select-default: Klik om de standaard taal te selecteren
selected-language: 'Momenteel geselecteerd:'
selected-language: " Op dit moment geselecteerd:"
change: Klik om een nieuwe taal te kiezen
description:
'0': "&7Je hebt nu de mogelijkheid om de taal"
'1': "&7van Slimefun te veranderen"
'2': "&7aan jou wordt vertoond. Items"
'3': "&7kunnen momenteel niet vertaald worden."
title:
main: Slimefun Handboek
settings: Instellingen & Informatie
@ -44,6 +61,7 @@ guide:
addons: Uitbreidingen voor Slimefun4
bugs: Fouten rapporteren
source: Source Code
versions: Geïnstalleerde versies
credits:
commit: Bijdrage
commits: Bijdragen
@ -53,6 +71,12 @@ guide:
resourcepack: "&cGrafische bundel Ontwikkelaar"
translator: "&9Vertaler"
profile-link: Klik om hun profielen op Github te bezoeken
open: Klik om onze bijdragers te zien
description:
'0': "&7Slimefun is een open-source project"
'1': "&7en wordt in stand gehouden door een grote gemeenschap van mensen."
'2': "&7Meer dan &e%contributors% &7mensen hebben hieraan"
'3': "&7al deze jaren gewerkt."
pages:
previous: Vorige bladzijde
next: Volgende bladzijde
@ -65,15 +89,17 @@ guide:
miner: Grondstoffen die je met deze Miner kunt verkrijgen
generator: Beschikbare soorten brandstof
gold-pan: Grondstoffen die je kunt verkrijgen
climbing-pick: Oppervlakken die je kunt beklimmen
back:
title: Terug
guide: Ga terug naar de Slimefun Handleiding
settings: Ga terug naar Instellingen
locked: VERGRENDELD
locked-category:
- Om deze categorie te ontgrendelen zul je
- alle items moeten ontgrendelen van de
- volgende categorieën
'0': Om deze categorie te ontgrendelen zul je
'1': alle items moeten ontgrendelen van de
'2': volgende categorieën
work-in-progress: Dit is nog niet helemaal klaar!
messages:
not-researched: "&4Je hebt niet genoeg Slimefun kennis om dit te begrijpen"
not-enough-xp: "&4Je hebt niet genoeg XP om dit te ontgrendelen"
@ -83,12 +109,8 @@ messages:
no-permission: "&4Je hebt geen toestemming om deze actie uit te voeren"
usage: "&4Gebruik, zoals: &c%usage%"
not-online: "&4%player% &cis niet online!"
invalid-item: "&4%item% &cis geen geldig voorwerp!"
invalid-amount: "&4%amount% &cis geen geldige hoeveelheid: het moet meer zijn
dan 0!"
given-item: '&bJe hebt &a%amount% keer &7"%item%&7" ontvangen'
give-item: '&bJe hebt %player% &a%amount% keer &7"%item%&7" gegeven'
invalid-research: "&4%research% &cis geen geldig Slimefun onderzoek"
give-research: '&bJe hebt %player% de kennis over &7"%research%&7" gegeven'
hungry: "&cJe hebt teveel honger om zoiets te doen!"
disabled-in-world: "&4&lDit voorwerp is uitgeschakeld in deze wereld"
@ -110,6 +132,8 @@ messages:
whirlwind: "&a&oJe Talisman heeft het projectiel weerkaatst"
wizard: "&a&oJe Talisman heeft je een hoger level van geluk gegeven, maar heeft
misschien ook de levels van andere betoveringen verlaagd"
caveman: "&a&oJe talisman gaf je haast"
wise: "&a&oJe Talisman heeft je verkregen experience punten verdubbeld"
soulbound-rune:
fail: "&cJe kan maar één voorwerp met je ziel verbinden op elk moment"
success: "&aJe hebt dit voorwerp succesvol met je ziel verbonden! Het blijft bij
@ -129,19 +153,46 @@ messages:
link-prompt: "&eKlik mij:"
diet-cookie: "&eJe begint je zo ligt als een veertje te voelen..."
fortune-cookie:
- "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!"
- "&7Je overlijdt morgen... door een creeper..."
- "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha"
- "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld is,
maar een simulatie"
- "&7Dit koekje gaat over een paar seconden heerlijk smaken"
- '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld alleen
maar vals!"'
- "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd,
maar het is het echt niet waard"
- "&742. Het antwoord op alles is 42"
- "&7A Walshy, één dag houdt alle problemen weg"
- "&7Graaf nooit recht naar beneden!"
'0': "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!"
'1': "&7Je overlijdt morgen... door een creeper..."
'2': "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha"
'3': "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld
is, maar een simulatie"
'4': "&7Dit koekje gaat over een paar seconden heerlijk smaken"
'5': '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld
alleen maar vals!"'
'6': "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd,
maar het is het echt niet waard"
'7': "&742. Het antwoord op alles is 42"
'8': "&7A Walshy, één dag houdt alle problemen weg"
'9': "&7Graaf nooit recht naar beneden!"
'10': "&7Het is slechts een vleeswonde!"
'11': "&7Kijk altijd naar de blije kant van je leven!"
'12': "&7Deze was eigenlijk een biscuitje en geen koekje"
'13': "&7Neon borden zijn LIT!"
piglin-barter: "&4Je kunt geen Slimefun spullen met piglins ruilen"
enchantment-rune:
fail: "&cJe kunt dit item niet betoveren."
no-enchantment: "&cKon geen mogelijke betoveringen vinden voor dit item."
success: "&aJe hebt succesvol een random betovering toegevoegd op dit item."
tape-measure:
no-anchor: "&cJe hebt nog een anker nodig voordat je kunt meten!"
wrong-world: "&cJe anker lijkt in een andere wereld te zitten!"
distance: "&7Afstand gemeten. &eAfstand: %distance%"
anchor-set: "&aHet is gelukt om het anker in te stellen:&e %anchor%"
multi-tool:
mode-change: "&b%device% mode veranderd naar: &9%mode%"
not-shears: "&cEen Mutli Tool kan niet gebruikt worden als een schaar!"
climbing-pick:
dual-wielding: "&4Je moet een klim-pickaxe in bijde handen hebben om hem te gebruiken!"
wrong-material: "&cJe kunt dit oppervlak niet beklimmen. Check je Slimefun Guide
voor meer info!"
invalid-item: "&4%item% &cis geen geldig voorwerp!"
invalid-amount: "&4%amount% &cis geen geldige hoeveelheid: het moet meer zijn dan
0!"
invalid-research: "&4%research% &cis geen geldig Slimefun onderzoek"
bee-suit-slow-fall: "&eJe Bee Wings zullen je helpen om weer veilig op de grond
te komen"
mode-change: "&b%device% mode is veranderd naar: &9%mode%"
machines:
pattern-not-found: "&eSorry, ik heb het recept niet herkend. Plaats astublieft de
@ -187,8 +238,20 @@ machines:
title: GPS - Configuratiescherm
transmitters: Transmitter-overzicht
waypoints: Waypoint-overzicht
INDUSTRIAL_MINER:
no-fuel: "& cUw Industrial Miner heeft geen brandstof meer! Doe de brandstof in
de kist erboven."
piston-facing: "&cJe Industrial Miner moet de duwmachines naar boven hebben!"
piston-space: "&cDe twee duwmachines moeten een leeg blok boven hem hebben!"
destroyed: "&cJouw Industrial Miner lijkt vernietigt te zijn!"
already-running: "&cDeze Industrial Miner draait al!"
full-chest: "&cDe kist van je Industrial Miner is vol!"
no-permission: "&4Het lijkt er op dat je geen permissie hebt om een Industrial
Miner hier te laten werken!"
finished: "&eJe Industrial Miner is klaar! Het heeft in totaal %ores% grondstof(fen)! "
anvil:
not-working: "&4Je kan geen Slimefun voorwerpen gebruiken in een aambeeld!"
mcmmo-salvaging: "&4Je kunt geen Slimefun items afbreken!"
backpack:
already-open: "&cSorry, deze rugzak is al ergens anders geopend!"
no-stack: "&cJe kan geen rugzakken stapelen"
@ -201,10 +264,11 @@ gps:
&r(Kleurcodes zijn ondersteund)"
added: "&aEen nieuw locatiepunt is succesvol toegevoegd"
max: "&4Je hebt het maximum aantal locatiepunten bereikt"
duplicate: "&4Je hebt al een waypoint genaamd: &f%waypoint%"
insufficient-complexity:
- "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%"
- "&4a) Je hebt nog geen GPS netwerk opgezet"
- "&4b) Je GPS netwerk is niet complex genoeg"
'0': "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%"
'1': "&4a) Je hebt nog geen GPS netwerk opgezet"
'2': "&4b) Je GPS netwerk is niet complex genoeg"
geo:
scan-required: "&4Een GEO-Scan is nodig! &cScan deze chunk eerst met behulp van
een GEO-Scanner!"
@ -243,15 +307,15 @@ android:
INTERFACE_ITEMS: "&9Geef inventaris aan de geconfronteerde interface"
INTERFACE_FUEL: "&cOntvang brandstof van de geconfronteerde interface"
enter-name:
-
- "&eType astublieft de gewenste naam in voor het script"
'1': "&eType astublieft de gewenste naam in voor het script"
uploaded:
- "&bBezig met uploaden..."
- "&aHet script is succesvol geupload!"
'0': "&bBezig met uploaden..."
'1': "&aHet script is succesvol geupload!"
rating:
own: "&4Je kan je eigen script geen waardering geven!"
already: "&4Je hebt aan een waardering achtergelaten voor dit script!"
editor: Scripteditor
too-long: "&cDe code is te lang om te kunnen editen!"
languages:
default: Server-Standaard
en: Engels
@ -284,10 +348,25 @@ languages:
fa: Perzisch
th: Thais
ro: Roemeens
pt: Portugees (Portugal)
pt: Portugees (Portugal)
pt-BR: Portugees (Brazilië)
bg: Bulgaars
ko: Koreaans
tr: Turks
hr: Kroatisch
mk: Macedonisch
sr: Servisch
be: Wit-Russisch/Russisch
tl: Tagalog
brewing_stand:
not-working: "&4Je kunt geen Slimefun spullen in een brouwstandaard doen!"
villagers:
no-trading: "&4Je kunt geen Slimefun spullen met villagers ruilen!"
cartography_table:
not-working: "&4Je kunt Slimefun items niet in een cartografie tafel gebruiken!"
cauldron:
no-discoloring: "&4Je kunt de kleur van Slimefun Bescherming niet er af halen"
placeholderapi:
profile-loading: Aan het laden...
miner:
no-ores: "&eSorry, ik kon geen ertsen vinden dichtbij!"

View File

@ -26,8 +26,8 @@ commands:
not-rechargeable: Vật phẩm này không thể sạc được!
timings:
description: Độ trễ của slimefun và addon của nó
verbose-player: "&4Cờ dài này không thể sử dụng bới Người chơi!"
please-wait: "&eVui lòng đợi một chút... Kết quả chuẩn bị đến!"
verbose-player: "&4Cờ dài này không thể sử dụng bới Người chơi!"
unknown-flag: "&4Không rõ cờ: &c%flag%"
guide:
search:
@ -138,6 +138,7 @@ messages:
wizard: "&a&oBùa hộ mệnh của bạn đã cho bạn một Cấp độ may mắn tốt hơn nhưng cũng
có thể hạ thấp một số Cấp độ phù phép khác"
caveman: "&a&oBùa ma thuật của bạn cho bạn hiệu ứng Đào nhanh"
wise: "&a&oBùa ma thuật đã nhân đôi số kinh nghiệm của bạn"
soulbound-rune:
fail: "&cBạn chỉ có thể liên kết một vật phẩm với linh hồn của bạn trong cùng
một thời điểm."
@ -375,3 +376,5 @@ cauldron:
no-discoloring: "&4Bạn không thể đổi màu giáp của Slimefun"
miner:
no-ores: "&eXin lỗi, tôi không thể tìm bất kì Khoáng sản nào xung quanh!"
placeholderapi:
profile-loading: Đang tải...

View File

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

View File

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

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

Some files were not shown because too many files have changed in this diff Show More