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

Merge branch 'master' into refactoring/block-energy

This commit is contained in:
TheBusyBiscuit 2020-08-20 16:55:35 +02:00 committed by GitHub
commit 88be3e79ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
124 changed files with 5097 additions and 3585 deletions

View File

@ -17,13 +17,13 @@ Rules for all types of posts:
Rules for posting an Issue on GitHub:
1. This Issue Section is ONLY for Slimefun-related Issues, Issues about other Plugins or Slimefun Addons should not be posted here.
2. Please consult our [Troubleshooting Guide](#troubleshooting-guide) before posting.
2. Please consult our [Troubleshooting Guide](https://github.com/TheBusyBiscuit/Slimefun4/wiki/How-to-report-bugs) before posting.
3. Check other Issues before posting to make sure you are not posting a duplicate.
4. Do not put any Tags inside your title like [IMPORTANT], [URGENT] or [SUGGESTION]. Try to be professional by making your title as short as possible, we will assign it the required labels if necessary.
5. Do not post your Issue more than once, this is considered spam and does not benefit our community in any way. Do not repost your Issue if it was closed either.
4. Please do not put any Tags inside your title like [IMPORTANT], [URGENT] or [SUGGESTION]. Try to be professional by making your title as short as possible, we will assign it the required labels if necessary.
5. Do not post your Issue more than once, this is considered spam and does not benefit our community in any way. Do not repost your Issue if it was closed either, just leave a comment stating that the issue has still persisted and give more context on it.
6. Give us all available information right away, it may be a bit of time-wasting for us to keep asking for more Info. And this includes any Information to reproduce your Issue step-by-step.
7. Check whether there are newer versions available than the ones you are using, it might be that your Issue has been fixed already.
8. All text logs must be posted via a link to http://pastebin.com or similiar websites.
8. All text logs must be posted via a link to https://pastebin.com/ or similiar websites, long logs are very hard to read and get weirdly formatted when you post them on here. Using a proper pasting site allows us to keep things clean and easy to read.
Your Issue will be CLOSED WITHOUT WARNING if we think you violated these Rules.
@ -35,26 +35,3 @@ Guidelines for making a Pull Request on GitHub:
2. Try to make your values configurable in the config.yml / Items.yml or any additional file. This may not be necessary at every instance but it does give the end-users a way to customize their experience.
3. If your Pull Request is made in response to an Issue opened on GitHub, comment on that Issue and reference your Pull Request to show that you are proposing a fix for it.
4. Name your commits appropriately. Standards like "Add files via upload" or "Update Readme.md" are lame. Make sure that the commit message stands for it's changes. (e.g. "Fixed Furnaces duplicating Items")
## Troubleshooting Guide
### Step 1: Check whether you have installed Slimefun correctly
Slimefun requires [CS-CoreLib](http://dev.bukkit.org/bukkit-plugins/cs-corelib) to run.
If it has not been installed automatically for you, then please download & install it manually.
### Step 2: Check whether you are running on the latest Versions
Both, [Slimefun](http://dev.bukkit.org/bukkit-plugins/slimefun/files) and [CS-CoreLib](http://dev.bukkit.org/bukkit-plugins/cs-corelib/files) are updated from time to time.
You should be sure that you run the latest Versions (at the time you post your Issue) of both Plugins.
### Step 3: Does it have to do with Items called 'CS-CoreLib's Head'?
Well in that case, you have been the victim of corruption, unless you have an Error/Crash Report that we can work with, there is literally nothing we can do about it.
Corrupting Files/Data can happen from time to time and getting completely rid of it would require a ton of work and even then it is still not completely impossible to occur.
### Step 4: Do you get an Error, do you have an Error Report?
Check your /plugins/Slimefun/error-reports/ directory and if it contains any Files, then please upload those to http://pastebin.com
and provide us with a link.
When providing us Errors from your Server Log MAKE SURE THEY ARE ERRORS.
It has happened more often than you may think that people send us messages.
Try to read the suspected 'Error' before uploading it to http://pastebin.com
If it says "Please install CS-CoreLib", then you may want to rethink whether you want to ask us what it means...

View File

@ -6,7 +6,10 @@ on:
jobs:
comment:
name: Invalid Issues
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'Bug Report') == false
steps:
- name: Close Issue

View File

@ -9,6 +9,7 @@ on:
jobs:
report:
name: Discord Webhook
runs-on: ubuntu-latest
if: github.repository == 'TheBusyBiscuit/Slimefun4'

View File

@ -6,7 +6,10 @@ on:
jobs:
comment:
name: Mark Issue as duplicate
runs-on: ubuntu-latest
if: contains(github.event.comment.body, 'Duplicate of ')
steps:
- name: Add label to the Issue

View File

@ -17,6 +17,7 @@ on:
jobs:
build:
name: Maven build
runs-on: ubuntu-latest
steps:

26
.github/workflows/url-checker.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: URL Validator
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
name: URL Checker
runs-on: ubuntu-latest
steps:
- name: URL-checker
uses: SuperKogito/URLs-checker@0.2.1
with:
git_path: https://github.com/TheBusyBiscuit/Slimefun4
file_types: .md,.java,.yml
print_all: False
retry_count: 2
## These URLs will always be correct, even if their services may be offline right now
white_listed_patterns: http://textures.minecraft.net/texture/,https://pastebin.com/,https://www.spigotmc.org/threads/spigot-bungeecord-1-16-1.447405/#post-3852349

View File

@ -11,8 +11,9 @@ on:
- '**.yml'
jobs:
build:
linter:
name: YAML Linter
runs-on: ubuntu-latest
steps:

View File

@ -29,6 +29,10 @@
* (API) Added support for adding custom Piglin Barter drops
* (API) Added BlockPlacerPlaceEvent
* (API) Added ToolUseHandler
* Added "Sand -> Sandstone" recipe to the Electric Press
* Added "Red Sand -> Red Sandstone" recipe to the Electric Press
* Industrial Miners can now also mine Gilded Blackstone
* Added a config option to disable Players from burning when exposed to radiation
#### Changes
* Performance improvement for Programmable Android rotations
@ -37,6 +41,9 @@
* Performance improvements for idling Enhanced Furnaces when using Paper
* Performance improvements for Rainbow Blocks
* Crafting a Rag now yields two items
* Small performance improvements for Slimefun guides
* Small performance improvements for Cargo networks
* Small performance improvements for Miner Androids
#### Fixes
* Fixed Programmable Androids rotating in the wrong direction
@ -52,6 +59,17 @@
* Fixed #2181
* Fixed #2180
* Fixed #2122
* Fixed #2168
* Fixed #2203
* Fixed #2205
* Fixed #2209
* Fixed #2217
* Fixed Miner Talisman sending messages when drops were not even doubled
* Fixed #2077
* Fixed #2207
* Fixed ChestTerminal timings showing up as cargo nodes
* Fixed timings reports never arriving sometimes
* Fixed #2138
## Release Candidate 15 (01 Aug 2020)

View File

@ -192,5 +192,5 @@ This information includes (but is not limited to)
* date of the last commit to this repository
</details>
Additionally the plugin connects to https://mojang.com/ to retrieve the Minecraft skins of our contributors (if possible).<br>
Additionally the plugin connects to [textures.minecraft.net](https://www.minecraft.net/en-us) to retrieve the Minecraft skins of our contributors (if possible).<br>
Note that Slimefun is not associated with `Mojang Studios` or Minecraft.

22
pom.xml
View File

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.thebusybiscuit</groupId>
<groupId>com.github.thebusybiscuit</groupId>
<artifactId>Slimefun</artifactId>
<!-- Our default version will be UNOFFICIAL, this will prevent auto updates -->
@ -22,7 +22,7 @@
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Spigot properties -->
<spigot.version>1.16.1</spigot.version>
<spigot.version>1.16.2</spigot.version>
<spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
<!-- Default settings for sonarcloud.io -->
@ -47,6 +47,16 @@
</licenses>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
@ -57,7 +67,7 @@
</repository>
<repository>
<id>paper-repo</id>
<url>https://repo.destroystokyo.com/repository/maven-public/</url>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>worldedit-repo</id>
@ -303,14 +313,14 @@
</dependency>
<dependency>
<groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit</artifactId>
<version>v1.15-d952559324-1</version>
<artifactId>MockBukkit-v1.15</artifactId>
<version>0.3.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.4.6</version>
<version>3.5.2</version>
<scope>test</scope>
</dependency>

View File

@ -84,7 +84,7 @@ public class ErrorReport {
addon.getLogger().log(Level.WARNING, "");
addon.getLogger().log(Level.WARNING, "An Error occurred! It has been saved as: ");
addon.getLogger().log(Level.WARNING, "/plugins/Slimefun/error-reports/{0}", file.getName());
addon.getLogger().log(Level.WARNING, "Please put this file on https://pastebin.com and report this to the developer(s).");
addon.getLogger().log(Level.WARNING, "Please put this file on https://pastebin.com/ and report this to the developer(s).");
if (addon.getBugTrackerURL() != null) {
addon.getLogger().log(Level.WARNING, "Bug Tracker: {0}", addon.getBugTrackerURL());

View File

@ -283,6 +283,14 @@ public class GPSNetwork {
if (!event.isCancelled()) {
String id = ChatColor.stripColor(ChatColors.color(event.getName())).toUpperCase(Locale.ROOT).replace(' ', '_');
for (Waypoint wp : profile.getWaypoints()) {
if (wp.getId().equals(id)) {
SlimefunPlugin.getLocalization().sendMessage(p, "gps.waypoint.duplicate", true, msg -> msg.replace("%waypoint%", event.getName()));
return;
}
}
profile.addWaypoint(new Waypoint(profile, id, event.getLocation(), event.getName()));
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1F, 1F);

View File

@ -99,4 +99,9 @@ public final class HashedArmorpiece {
return item;
}
@Override
public String toString() {
return "HashedArmorpiece {hash=" + hash + ",item=" + item.map(SlimefunItem::getID).orElse(null) + '}';
}
}

View File

@ -225,6 +225,11 @@ public abstract class Network {
});
}
/**
* This returns the {@link Location} of the regulator block for this {@link Network}
*
* @return The {@link Location} of our regulator
*/
public Location getRegulator() {
return regulator;
}

View File

@ -32,8 +32,8 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint;
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -455,11 +455,13 @@ public final class PlayerProfile {
int armorCount = 0;
NamespacedKey setId = null;
for (HashedArmorpiece armorpiece : armor) {
Optional<SlimefunArmorPiece> armorPiece = armorpiece.getItem();
if (!armorPiece.isPresent()) {
return false;
setId = null;
continue;
}
if (armorPiece.get() instanceof ProtectiveArmor) {

View File

@ -19,7 +19,8 @@ class GuideCommand extends SubCommand {
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.guide")) {
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST));
SlimefunGuideLayout design = SlimefunGuide.getDefaultLayout();
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(design).clone());
}
else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -1,16 +1,10 @@
package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
@ -36,31 +30,7 @@ public final class SlimefunGuide {
private SlimefunGuide() {}
public static ItemStack getItem(SlimefunGuideLayout design) {
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
List<String> lore = new LinkedList<>();
lore.addAll(Arrays.asList("", ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"), ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits")));
switch (design) {
case BOOK:
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Book GUI)"));
break;
case CHEAT_SHEET:
meta.setDisplayName(ChatColors.color("&cSlimefun Guide &4(Cheat Sheet)"));
lore.add(0, ChatColors.color("&4&lOnly openable by Admins"));
lore.add(0, "");
break;
case CHEST:
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Chest GUI)"));
break;
default:
return null;
}
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
return item;
return SlimefunPlugin.getRegistry().getGuideLayout(design).getItem();
}
public static void openCheatMenu(Player p) {
@ -132,4 +102,13 @@ public final class SlimefunGuide {
public static boolean isGuideItem(ItemStack item) {
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEST), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.BOOK), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEAT_SHEET), true);
}
public static SlimefunGuideLayout getDefaultLayout() {
if (SlimefunPlugin.getCfg().getBoolean("guide.default-view-book")) {
return SlimefunGuideLayout.BOOK;
}
else {
return SlimefunGuideLayout.CHEST;
}
}
}

View File

@ -21,6 +21,12 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
/**
* This menu shows a list of every {@link Contributor} to this project.
*
* @author TheBusyBiscuit
*
*/
final class ContributorsMenu {
private ContributorsMenu() {}

View File

@ -102,7 +102,7 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
@Override
public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.values()) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true)) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true, false)) {
return Optional.of(layout);
}
}

View File

@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.guide.options;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.ChatColor;
@ -16,6 +18,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -37,7 +40,16 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
Language language = SlimefunPlugin.getLocalization().getLanguage(p);
String languageName = language.isDefault() ? (SlimefunPlugin.getLocalization().getMessage(p, "languages.default") + ChatColor.DARK_GRAY + " (" + language.getName(p) + ")") : SlimefunPlugin.getLocalization().getMessage(p, "languages." + language.getId());
return Optional.of(new CustomItem(language.getItem(), "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.selected-language") + " &a" + languageName, "", "&7You now have the option to change", "&7the language in which Slimefun", "&7will send you messages.", "&7Note that this only translates", "&7some messages, not items.", "&7&oThis feature is still being worked on", "", "&7\u21E8 &eClick to change your language"));
List<String> lore = new ArrayList<>();
lore.add("");
lore.add("&e&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress"));
lore.add("");
lore.addAll(SlimefunPlugin.getLocalization().getMessages(p, "guide.languages.description", msg -> msg.replace("%contributors%", String.valueOf(SlimefunPlugin.getGitHubService().getContributors().size()))));
lore.add("");
lore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.change"));
ItemStack item = new CustomItem(language.getItem(), "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.selected-language") + " &a" + languageName, lore.toArray(new String[0]));
return Optional.of(item);
}
else {
return Optional.empty();
@ -78,7 +90,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
});
}
else if (i == 7) {
menu.addItem(7, new CustomItem(SlimefunUtils.getCustomHead("3edd20be93520949e6ce789dc4f43efaeb28c717ee6bfcbbe02780142f716"), SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.name"), "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.lore")), (pl, slot, item, action) -> {
menu.addItem(7, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.ADD_NEW_LANGUAGE.getTexture()), SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.name"), "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.lore")), (pl, slot, item, action) -> {
ChatUtils.sendURL(pl, "https://github.com/TheBusyBiscuit/Slimefun4/wiki/Translating-Slimefun");
pl.closeInventory();
return false;
@ -105,7 +117,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
int slot = 10;
for (Language language : SlimefunPlugin.getLocalization().getLanguages()) {
menu.addItem(slot, new CustomItem(language.getItem(), ChatColor.GREEN + language.getName(p), "&b" + SlimefunPlugin.getLocalization().getProgress(language) + '%', "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.select")), (pl, i, item, action) -> {
menu.addItem(slot, new CustomItem(language.getItem(), ChatColor.GREEN + language.getName(p), "&b" + language.getTranslationProgress() + '%', "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.select")), (pl, i, item, action) -> {
SlimefunPlugin.instance().getServer().getPluginManager().callEvent(new PlayerLanguageChangeEvent(pl, SlimefunPlugin.getLocalization().getLanguage(pl), language));
setSelectedOption(pl, guide, language.getId());

View File

@ -19,6 +19,11 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
*/
public interface SlimefunGuideOption<T> extends Keyed {
/**
* This returns the {@link SlimefunAddon} which added this {@link SlimefunGuideOption}.
*
* @return The registering {@link SlimefunAddon}
*/
SlimefunAddon getAddon();
Optional<ItemStack> getDisplayItem(Player p, ItemStack guide);

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
@ -73,14 +74,21 @@ public final class SlimefunGuideSettings {
return false;
});
menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.credits"), "", "&7Contributors: &e" + SlimefunPlugin.getGitHubService().getContributors().size(), "", "&7Slimefun is an open-source project", "&7and maintained by a large community of people.", "&7Here you can see who helped shape the project.", "", "&7\u21E8 &eClick to see our contributors"), (pl, slot, action, item) -> {
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.add("");
contributorsLore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().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) -> {
ContributorsMenu.open(pl, 0);
return false;
});
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, "&aSlimefun Version", "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft Version: &a" + Bukkit.getBukkitVersion(), "&fSlimefun Version: &a" + SlimefunPlugin.getVersion(), "&fCS-CoreLib Version: &a" + SlimefunPlugin.getCSCoreLibVersion()), ChestMenuUtils.getEmptyClickHandler());
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(), "&fCS-CoreLib: &a" + SlimefunPlugin.getCSCoreLibVersion()), ChestMenuUtils.getEmptyClickHandler());
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.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/TheBusyBiscuit/Slimefun4");
@ -110,7 +118,7 @@ public final class SlimefunGuideSettings {
menu.addItem(49, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
}
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, "&cSoon", "", "&7Something will be added here later..."), (pl, slot, item, action) -> {
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> {
// Add something here
return false;
});

View File

@ -3,10 +3,12 @@ package io.github.thebusybiscuit.slimefun4.core.handlers;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EntityInteractionListener;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
@ -15,9 +17,9 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
*
* @author Linox
*
* @see EntityInteractionListener
* @see ItemHandler
* @see SimpleSlimefunItem
* @see PlayerInteractAtEntityEvent
*
*/
@FunctionalInterface
@ -27,16 +29,14 @@ public interface EntityInteractHandler extends ItemHandler {
* This function is triggered when a {@link Player} right clicks with the assigned {@link SlimefunItem}
* in his hand.
*
* @param p
* The {@link Player} that right clicked
* @param entity
* The {@link Entity} that was right clicked on
* @param e
* The {@link PlayerInteractAtEntityEvent} which was called
* @param item
* The {@link ItemStack} that was held and used while triggering
* @param offHand
* <code>true</code> if the {@link EquipmentSlot} is off hand
*/
void onInteract(Player p, Entity entity, ItemStack item, boolean offHand);
void onInteract(PlayerInteractEntityEvent e, ItemStack item, boolean offHand);
@Override
default Class<? extends ItemHandler> getIdentifier() {

View File

@ -175,7 +175,7 @@ public class CargoNet extends ChestTerminalNetwork {
display();
}
SlimefunPlugin.getProfiler().scheduleEntries(1 + inputNodes.size());
SlimefunPlugin.getProfiler().scheduleEntries((terminals.isEmpty() ? 1 : 2) + inputs.size());
CargoNetworkTask runnable = new CargoNetworkTask(this, inputs, outputs, chestTerminalInputs, chestTerminalOutputs);
Slimefun.runSync(runnable);

View File

@ -16,6 +16,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
@ -63,6 +64,7 @@ class CargoNetworkTask implements Runnable {
// All operations happen here: Everything gets iterated from the Input Nodes.
// (Apart from ChestTerminal Buses)
SlimefunItem inputNode = SlimefunItems.CARGO_INPUT_NODE.getItem();
for (Map.Entry<Location, Integer> entry : inputs.entrySet()) {
long nodeTimestamp = System.nanoTime();
Location input = entry.getKey();
@ -71,12 +73,13 @@ class CargoNetworkTask implements Runnable {
attachedBlock.ifPresent(block -> routeItems(input, block, entry.getValue(), outputs));
// This will prevent this timings from showing up for the Cargo Manager
timestamp += SlimefunPlugin.getProfiler().closeEntry(entry.getKey(), SlimefunItems.CARGO_INPUT_NODE.getItem(), nodeTimestamp);
timestamp += SlimefunPlugin.getProfiler().closeEntry(entry.getKey(), inputNode, nodeTimestamp);
}
// Chest Terminal Code
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) {
network.updateTerminals(chestTerminalInputs);
// This will deduct any CT timings and attribute them towards the actual terminal
timestamp += network.updateTerminals(chestTerminalInputs);
}
// Submit a timings report

View File

@ -409,18 +409,36 @@ final class CargoUtils {
}
private static boolean matchesFilterList(ItemStack item, BlockMenu menu, boolean respectLore, boolean defaultValue) {
ItemStackWrapper wrapper = null;
// Little performance optimization:
// First check if there is more than one item to compare, if so
// then we know we should create an ItemStackWrapper, otherwise it would
// be of no benefit to us and just be redundant
int itemsToCompare = 0;
for (int slot : FILTER_SLOTS) {
ItemStack stack = menu.getItemInSlot(slot);
if (stack != null) {
if (wrapper == null) {
// Only create this as needed to save performance
wrapper = new ItemStackWrapper(item);
}
if (stack != null && stack.getType() != Material.AIR) {
itemsToCompare++;
if (SlimefunUtils.isItemSimilar(stack, wrapper, respectLore, false)) {
if (itemsToCompare > 1) {
break;
}
}
}
// Check if there are event non-air items
if (itemsToCompare > 0) {
// Only create the Wrapper if its worth it
if (itemsToCompare > 1) {
// Create an itemStackWrapper to save performance
item = new ItemStackWrapper(item);
}
for (int slot : FILTER_SLOTS) {
ItemStack stack = menu.getItemInSlot(slot);
if (SlimefunUtils.isItemSimilar(stack, item, respectLore, false)) {
return !defaultValue;
}
}

View File

@ -274,37 +274,49 @@ abstract class ChestTerminalNetwork extends Network {
*
* @param providers
* A {@link Set} of providers to this {@link ChestTerminalNetwork}
*
* @return The time it took to compute this operation
*/
protected void updateTerminals(Set<Location> providers) {
protected long updateTerminals(Set<Location> providers) {
if (terminals.isEmpty()) {
// Performance improvement - We don't need to compute items for
// Cargo networks without any Chest Terminals
return;
return 0;
}
// Timings will be slightly inaccurate here but most often people are gonna
// use no more than one terminal anyway, so this might be fine
long timestamp = SlimefunPlugin.getProfiler().newEntry();
// Timings will be slightly inaccurate here but most often people are not
// gonna use no more than one terminal anyway, so this might be fine
long timestamp = System.nanoTime();
Location firstTerminal = null;
SlimefunItem item = SlimefunItem.getByID("CHEST_TERMINAL");
List<ItemStackAndInteger> items = findAvailableItems(providers);
for (Location l : terminals) {
BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
try {
for (Location l : terminals) {
BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1;
BlockStorage.addBlockInfo(l, "page", String.valueOf(1));
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1;
BlockStorage.addBlockInfo(l, "page", String.valueOf(1));
}
for (int i = 0; i < TERMINAL_SLOTS.length; i++) {
int slot = TERMINAL_SLOTS[i];
int index = i + (TERMINAL_SLOTS.length * (page - 1));
updateTerminal(l, terminal, slot, index, items);
}
if (firstTerminal == null) {
firstTerminal = l;
}
}
for (int i = 0; i < TERMINAL_SLOTS.length; i++) {
int slot = TERMINAL_SLOTS[i];
int index = i + (TERMINAL_SLOTS.length * (page - 1));
updateTerminal(l, terminal, slot, index, items);
}
SlimefunPlugin.getProfiler().closeEntry(l, item, timestamp);
}
catch (Exception | LinkageError x) {
item.error("An Exception was caused while trying to tick Chest terminals", x);
}
return SlimefunPlugin.getProfiler().closeEntry(firstTerminal, item, timestamp);
}
private void updateTerminal(Location l, BlockMenu terminal, int slot, int index, List<ItemStackAndInteger> items) {
@ -316,7 +328,7 @@ abstract class ChestTerminalNetwork extends Network {
ItemMeta im = stack.getItemMeta();
List<String> lore = new ArrayList<>();
lore.add("");
lore.add(ChatColors.color("&7Stored Items: &r" + DoubleHandler.getFancyDouble(item.getInt())));
lore.add(ChatColors.color("&7Stored Items: &f" + DoubleHandler.getFancyDouble(item.getInt())));
if (stack.getMaxStackSize() > 1) {
int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt();
@ -437,7 +449,7 @@ abstract class ChestTerminalNetwork extends Network {
boolean add = true;
for (ItemStackAndInteger item : items) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true)) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true, false)) {
add = false;
item.add(stack.getAmount());
}

View File

@ -89,7 +89,7 @@ public class AutoSavingService {
Slimefun.getLogger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
for (BlockStorage storage : worlds) {
storage.save(false);
storage.save();
}
}

View File

@ -37,7 +37,7 @@ public class BackupService implements Runnable {
if (backups.size() > MAX_BACKUPS) {
try {
deleteOldBackups(backups);
purgeBackups(backups);
}
catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Could not delete an old backup", e);
@ -112,7 +112,16 @@ public class BackupService implements Runnable {
}
}
private void deleteOldBackups(List<File> backups) throws IOException {
/**
* This method will delete old backups.
*
* @param backups
* The {@link List} of all backups
*
* @throws IOException
* An {@link IOException} is thrown if a {@link File} could not be deleted
*/
private void purgeBackups(List<File> backups) throws IOException {
Collections.sort(backups, (a, b) -> {
LocalDateTime time1 = LocalDateTime.parse(a.getName().substring(0, a.getName().length() - 4), format);
LocalDateTime time2 = LocalDateTime.parse(b.getName().substring(0, b.getName().length() - 4), format);

View File

@ -5,11 +5,14 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration;
@ -116,7 +119,16 @@ public class LocalizationService extends SlimefunLocalization implements Persist
return containsResource("messages_" + language);
}
/**
* This returns whether the given {@link Language} is loaded or not.
*
* @param id
* The id of that {@link Language}
*
* @return Whether or not this {@link Language} is loaded
*/
public boolean isLanguageLoaded(String id) {
Validate.notNull(id, "The language id cannot be null!");
return languages.containsKey(id);
}
@ -173,7 +185,10 @@ public class LocalizationService extends SlimefunLocalization implements Persist
}
@Override
protected void addLanguage(String id, String hash) {
protected void addLanguage(String id, String texture) {
Validate.notNull(id, "The language id cannot be null!");
Validate.notNull(texture, "The language texture cannot be null");
if (hasLanguage(id)) {
FileConfiguration messages = streamConfigFile("messages_" + id + ".yml", getConfig().getConfiguration());
FileConfiguration researches = streamConfigFile("researches_" + id + ".yml", null);
@ -181,7 +196,7 @@ public class LocalizationService extends SlimefunLocalization implements Persist
FileConfiguration categories = streamConfigFile("categories_" + id + ".yml", null);
FileConfiguration recipes = streamConfigFile("recipes_" + id + ".yml", null);
Language language = new Language(id, hash);
Language language = new Language(id, texture);
language.setMessagesFile(messages);
language.setResearchesFile(researches);
language.setResourcesFile(resources);
@ -202,25 +217,36 @@ public class LocalizationService extends SlimefunLocalization implements Persist
*
* @return A percentage {@code (0.0 - 100.0)} for the progress of translation of that {@link Language}
*/
public double getProgress(Language lang) {
int defaultKeys = getTotalKeys(languages.get("en"));
public double calculateProgress(Language lang) {
Validate.notNull(lang, "Cannot get the language progress of null");
if (defaultKeys == 0) {
Set<String> defaultKeys = getTotalKeys(languages.get("en"));
if (defaultKeys.isEmpty()) {
return 0;
}
return Math.min(DoubleHandler.fixDouble(100.0 * (getTotalKeys(lang) / (double) defaultKeys)), 100.0);
Set<String> keys = getTotalKeys(lang);
int matches = 0;
for (String key : defaultKeys) {
if (keys.contains(key)) {
matches++;
}
}
return Math.min(DoubleHandler.fixDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
}
private int getTotalKeys(Language lang) {
private Set<String> getTotalKeys(Language lang) {
return getKeys(lang.getFiles());
}
private int getKeys(FileConfiguration... files) {
int keys = 0;
private Set<String> getKeys(FileConfiguration... files) {
Set<String> keys = new HashSet<>();
for (FileConfiguration cfg : files) {
keys += cfg != null ? cfg.getKeys(true).size() : 0;
keys.addAll(cfg.getKeys(true));
}
return keys;

View File

@ -32,9 +32,11 @@ import org.bukkit.plugin.Plugin;
*/
public class MetricsService {
private static final String API_URL = "https://api.github.com/";
private static final String REPO_NAME = "MetricsModule";
private static final String GH_API = "https://api.github.com/repos/Slimefun/" + REPO_NAME;
private static final String GH_RELEASES = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private static final String RELEASES_URL = API_URL + "repos/Slimefun/" + REPO_NAME + "/releases/latest";
private static final String DOWNLOAD_URL = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private final SlimefunPlugin plugin;
private final File parentFolder;
@ -160,7 +162,7 @@ public class MetricsService {
*/
private int getLatestVersion() {
try {
HttpResponse<JsonNode> response = Unirest.get(GH_API + "/releases/latest").asJson();
HttpResponse<JsonNode> response = Unirest.get(RELEASES_URL).asJson();
if (!response.isSuccess()) {
return -1;
@ -198,7 +200,7 @@ public class MetricsService {
}
AtomicInteger lastPercentPosted = new AtomicInteger();
GetRequest request = Unirest.get(GH_RELEASES + "/" + version + "/" + REPO_NAME + ".jar");
GetRequest request = Unirest.get(DOWNLOAD_URL + "/" + version + "/" + REPO_NAME + ".jar");
HttpResponse<File> response = request.downloadMonitor((b, fileName, bytesWritten, totalBytes) -> {
int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20)));

View File

@ -18,6 +18,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
abstract class GitHubConnector {
private static final String API_URL = "https://api.github.com/";
protected File file;
protected String repository;
protected final GitHubService github;
@ -45,7 +47,7 @@ abstract class GitHubConnector {
}
try {
HttpResponse<JsonNode> resp = Unirest.get("https://api.github.com/repos/" + repository + getURLSuffix())
HttpResponse<JsonNode> resp = Unirest.get(API_URL + "repos/" + repository + getURLSuffix())
.header("User-Agent", "Slimefun4 (https://github.com/Slimefun)")
.asJson();

View File

@ -25,6 +25,7 @@ public final class Language {
private final String id;
private final ItemStack item;
private double progress = -1;
private FileConfiguration messages;
private FileConfiguration researches;
@ -60,6 +61,26 @@ public final class Language {
return id;
}
/**
* This method returns the progress of translation for this {@link Language}.
* The progress is determined by the amount of translated strings divided by the amount
* of strings in the english {@link Language} file and multiplied by 100.0
*
* @return A percentage {@code (0.0 - 100.0)} for the progress of translation of this {@link Language}
*/
public double getTranslationProgress() {
if (id.equals("en")) {
return 100.0;
}
else {
if (progress < 0) {
progress = SlimefunPlugin.getLocalization().calculateProgress(this);
}
return progress;
}
}
FileConfiguration getMessagesFile() {
return messages;
}
@ -145,7 +166,7 @@ public final class Language {
@Override
public String toString() {
return "Language [ id= " + id + " | default=" + isDefault() + " ]";
return "Language {id= " + id + ", default=" + isDefault() + " }";
}
public FileConfiguration[] getFiles() {

View File

@ -119,6 +119,13 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
return messages;
}
public List<String> getMessages(Player p, String key, UnaryOperator<String> function) {
List<String> messages = getMessages(p, key);
messages.replaceAll(function);
return messages;
}
public String getResearchName(Player p, NamespacedKey key) {
Language language = getLanguage(p);

View File

@ -44,7 +44,7 @@ public class SlimefunProfiler {
// two ticks (sync and async blocks), so we use 100ms as a reference here
private static final int MAX_TICK_DURATION = 100;
private final ExecutorService executor = Executors.newFixedThreadPool(4);
private final ExecutorService executor = Executors.newFixedThreadPool(5);
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicInteger queued = new AtomicInteger(0);
@ -118,7 +118,8 @@ public class SlimefunProfiler {
executor.execute(() -> {
ProfiledBlock block = new ProfiledBlock(l, item);
timings.putIfAbsent(block, elapsedTime);
// Merge (if we have multiple samples for whatever reason)
timings.merge(block, elapsedTime, Long::sum);
queued.decrementAndGet();
});
@ -143,7 +144,7 @@ public class SlimefunProfiler {
private void finishReport() {
// We will only wait for a maximum of this many 1ms sleeps
int iterations = 1000;
int iterations = 4000;
// Wait for all timing results to come in
while (!running.get() && queued.get() > 0) {
@ -153,6 +154,12 @@ public class SlimefunProfiler {
// If we waited for too long, then we should just abort
if (iterations <= 0) {
Iterator<CommandSender> iterator = requests.iterator();
while (iterator.hasNext()) {
iterator.next().sendMessage("Your timings report has timed out, we were still waiting for " + queued.get() + " samples to be collected :/");
iterator.remove();
}
return;
}
}

View File

@ -144,11 +144,11 @@ public final class SlimefunItems {
public static final SlimefunItemStack DIET_COOKIE = new SlimefunItemStack("DIET_COOKIE", Material.COOKIE, "&6Diet Cookie", "", "&aA very &olightweight &f&acookie.");
public static final SlimefunItemStack MAGIC_SUGAR = new SlimefunItemStack("MAGIC_SUGAR", Material.SUGAR, "&6Magic Sugar", "", "&a&oFeel the Power of Hermes!");
public static final SlimefunItemStack MONSTER_JERKY = new SlimefunItemStack("MONSTER_JERKY", Material.ROTTEN_FLESH, "&6Monster Jerky", "", "&a&oNo longer hungry");
public static final SlimefunItemStack APPLE_JUICE = new SlimefunItemStack("APPLE_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cApple Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack MELON_JUICE = new SlimefunItemStack("MELON_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cMelon Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack CARROT_JUICE = new SlimefunItemStack("CARROT_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&6Carrot Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack PUMPKIN_JUICE = new SlimefunItemStack("PUMPKIN_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&6Pumpkin Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack SWEET_BERRY_JUICE = new SlimefunItemStack("SWEET_BERRY_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cSweet Berry Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack APPLE_JUICE = new SlimefunItemStack("APPLE_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cApple Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack MELON_JUICE = new SlimefunItemStack("MELON_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cMelon Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack CARROT_JUICE = new SlimefunItemStack("CARROT_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Carrot Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack PUMPKIN_JUICE = new SlimefunItemStack("PUMPKIN_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Pumpkin Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack SWEET_BERRY_JUICE = new SlimefunItemStack("SWEET_BERRY_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cSweet Berry Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack GOLDEN_APPLE_JUICE = new SlimefunItemStack("GOLDEN_APPLE_JUICE", Color.YELLOW, new PotionEffect(PotionEffectType.ABSORPTION, 20 * 20, 0), "&bGolden Apple Juice");
public static final SlimefunItemStack BEEF_JERKY = new SlimefunItemStack("BEEF_JERKY", Material.COOKED_BEEF, "&6Beef Jerky", "", "&fExtra saturating!");
@ -161,14 +161,14 @@ public final class SlimefunItems {
public static final SlimefunItemStack KELP_COOKIE = new SlimefunItemStack("KELP_COOKIE", Material.COOKIE, "&2Kelp Cookie");
/* Christmas */
public static final SlimefunItemStack CHRISTMAS_MILK = new SlimefunItemStack("CHRISTMAS_MILK", Color.WHITE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Glass of Milk", "", LoreBuilder.hunger(2.5));
public static final SlimefunItemStack CHRISTMAS_CHOCOLATE_MILK = new SlimefunItemStack("CHRISTMAS_CHOCOLATE_MILK", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 12, 0), "&6Chocolate Milk", "", LoreBuilder.hunger(6));
public static final SlimefunItemStack CHRISTMAS_EGG_NOG = new SlimefunItemStack("CHRISTMAS_EGG_NOG", Color.GRAY, new PotionEffect(PotionEffectType.SATURATION, 7, 0), "&aEgg Nog", "", LoreBuilder.hunger(3.5));
public static final SlimefunItemStack CHRISTMAS_APPLE_CIDER = new SlimefunItemStack("CHRISTMAS_APPLE_CIDER", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 14, 0), "&cApple Cider", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_MILK = new SlimefunItemStack("CHRISTMAS_MILK", Color.WHITE, new PotionEffect(PotionEffectType.SATURATION, 4, 0), "&6Glass of Milk", "", LoreBuilder.hunger(2.5));
public static final SlimefunItemStack CHRISTMAS_CHOCOLATE_MILK = new SlimefunItemStack("CHRISTMAS_CHOCOLATE_MILK", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 11, 0), "&6Chocolate Milk", "", LoreBuilder.hunger(6));
public static final SlimefunItemStack CHRISTMAS_EGG_NOG = new SlimefunItemStack("CHRISTMAS_EGG_NOG", Color.GRAY, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&aEgg Nog", "", LoreBuilder.hunger(3.5));
public static final SlimefunItemStack CHRISTMAS_APPLE_CIDER = new SlimefunItemStack("CHRISTMAS_APPLE_CIDER", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 13, 0), "&cApple Cider", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_COOKIE = new SlimefunItemStack("CHRISTMAS_COOKIE", Material.COOKIE, ChatUtils.christmas("Christmas Cookie"));
public static final SlimefunItemStack CHRISTMAS_FRUIT_CAKE = new SlimefunItemStack("CHRISTMAS_FRUIT_CAKE", Material.PUMPKIN_PIE, ChatUtils.christmas("Fruit Cake"));
public static final SlimefunItemStack CHRISTMAS_APPLE_PIE = new SlimefunItemStack("CHRISTMAS_APPLE_PIE", Material.PUMPKIN_PIE, "&fApple Pie");
public static final SlimefunItemStack CHRISTMAS_HOT_CHOCOLATE = new SlimefunItemStack("CHRISTMAS_HOT_CHOCOLATE", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 14, 0), "&6Hot Chocolate", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_HOT_CHOCOLATE = new SlimefunItemStack("CHRISTMAS_HOT_CHOCOLATE", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 13, 0), "&6Hot Chocolate", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_CAKE = new SlimefunItemStack("CHRISTMAS_CAKE", Material.PUMPKIN_PIE, ChatUtils.christmas("Christmas Cake"));
public static final SlimefunItemStack CHRISTMAS_CARAMEL = new SlimefunItemStack("CHRISTMAS_CARAMEL", Material.BRICK, "&6Caramel");
public static final SlimefunItemStack CHRISTMAS_CARAMEL_APPLE = new SlimefunItemStack("CHRISTMAS_CARAMEL_APPLE", Material.APPLE, "&6Caramel Apple");
@ -286,10 +286,10 @@ public final class SlimefunItems {
public static final SlimefunItemStack GILDED_IRON_LEGGINGS = new SlimefunItemStack("GILDED_IRON_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Gilded Iron Leggings");
public static final SlimefunItemStack GILDED_IRON_BOOTS = new SlimefunItemStack("GILDED_IRON_BOOTS", Material.GOLDEN_BOOTS, "&6Gilded Iron Boots");
public static final SlimefunItemStack GOLD_HELMET = new SlimefunItemStack("GOLD_12K_HELMET", Material.GOLDEN_HELMET, "&6Gold Helmet", "&912-Carat");
public static final SlimefunItemStack GOLD_CHESTPLATE = new SlimefunItemStack("GOLD_12K_CHESTPLATE", Material.GOLDEN_CHESTPLATE, "&6Gold Chestplate", "&912-Carat");
public static final SlimefunItemStack GOLD_LEGGINGS = new SlimefunItemStack("GOLD_12K_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Gold Leggings", "&912-Carat");
public static final SlimefunItemStack GOLD_BOOTS = new SlimefunItemStack("GOLD_12K_BOOTS", Material.GOLDEN_BOOTS, "&6Gold Boots", "&912-Carat");
public static final SlimefunItemStack GOLDEN_HELMET_12K = new SlimefunItemStack("GOLD_12K_HELMET", Material.GOLDEN_HELMET, "&6Golden Helmet &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_CHESTPLATE_12K = new SlimefunItemStack("GOLD_12K_CHESTPLATE", Material.GOLDEN_CHESTPLATE, "&6Golden Chestplate &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_LEGGINGS_12K = new SlimefunItemStack("GOLD_12K_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Golden Leggings &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_BOOTS_12K = new SlimefunItemStack("GOLD_12K_BOOTS", Material.GOLDEN_BOOTS, "&6Golden Boots &7(12-Carat)");
public static final SlimefunItemStack SLIME_HELMET_STEEL = new SlimefunItemStack("SLIME_STEEL_HELMET", Material.IRON_HELMET, "&a&lSlime Helmet", "&7&oReinforced", "", "&a&oBouncy Feeling");
public static final SlimefunItemStack SLIME_CHESTPLATE_STEEL = new SlimefunItemStack("SLIME_STEEL_CHESTPLATE", Material.IRON_CHESTPLATE, "&a&lSlime Chestplate", "&7&oReinforced", "", "&a&oBouncy Feeling");
@ -335,10 +335,10 @@ public final class SlimefunItems {
GILDED_IRON_LEGGINGS.addUnsafeEnchantments(gilded);
GILDED_IRON_BOOTS.addUnsafeEnchantments(gilded);
GOLD_HELMET.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_CHESTPLATE.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_LEGGINGS.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_BOOTS.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_HELMET_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_CHESTPLATE_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_LEGGINGS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_BOOTS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
Map<Enchantment, Integer> slime = new HashMap<>();
slime.put(Enchantment.DURABILITY, 4);
@ -406,12 +406,13 @@ public final class SlimefunItems {
public static final SlimefunItemStack ANCIENT_ALTAR = new SlimefunItemStack("ANCIENT_ALTAR", Material.ENCHANTING_TABLE, "&dAncient Altar", "", "&5Multi-Block Altar for", "&5magical Crafting Processes");
public static final SlimefunItemStack COPPER_WIRE = new SlimefunItemStack("COPPER_WIRE", Material.STRING, "&6Copper Wire", "", "&6Crucial component in electric modules");
public static final SlimefunItemStack RAINBOW_WOOL = new SlimefunItemStack("RAINBOW_WOOL", Material.WHITE_WOOL, "&5Rainbow Wool", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLASS = new SlimefunItemStack("RAINBOW_GLASS", Material.WHITE_STAINED_GLASS, "&5Rainbow Glass", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_CLAY = new SlimefunItemStack("RAINBOW_CLAY", Material.WHITE_TERRACOTTA, "&5Rainbow Clay", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLASS_PANE = new SlimefunItemStack("RAINBOW_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE, "&5Rainbow Glass Pane", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_CONCRETE = new SlimefunItemStack("RAINBOW_CONCRETE", Material.WHITE_CONCRETE, "&5Rainbow Concrete", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLAZED_TERRACOTTA = new SlimefunItemStack("RAINBOW_GLAZED_TERRACOTTA", Material.WHITE_GLAZED_TERRACOTTA, "&5Rainbow Glazed Terracotta", "", "&dCycles through all Colors of the Rainbow!");
private static final String RAINBOW = "&dCycles through all Colors of the Rainbow!";
public static final SlimefunItemStack RAINBOW_WOOL = new SlimefunItemStack("RAINBOW_WOOL", Material.WHITE_WOOL, "&5Rainbow Wool", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLASS = new SlimefunItemStack("RAINBOW_GLASS", Material.WHITE_STAINED_GLASS, "&5Rainbow Glass", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_CLAY = new SlimefunItemStack("RAINBOW_CLAY", Material.WHITE_TERRACOTTA, "&5Rainbow Clay", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLASS_PANE = new SlimefunItemStack("RAINBOW_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE, "&5Rainbow Glass Pane", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_CONCRETE = new SlimefunItemStack("RAINBOW_CONCRETE", Material.WHITE_CONCRETE, "&5Rainbow Concrete", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLAZED_TERRACOTTA = new SlimefunItemStack("RAINBOW_GLAZED_TERRACOTTA", Material.WHITE_GLAZED_TERRACOTTA, "&5Rainbow Glazed Terracotta", "", RAINBOW);
/* Seasonal */
private static final String CHRISTMAS = ChatUtils.christmas("[Christmas Edition]");

View File

@ -61,6 +61,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.DeathpointLis
import io.github.thebusybiscuit.slimefun4.implementation.listeners.DebugFishListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.DispenserListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EnhancedFurnaceListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EntityInteractionListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ExplosionsListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GadgetsListener;
@ -70,7 +71,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupLis
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MobDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerInteractEntityListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerProfileListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBootsListener;
@ -82,6 +82,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundList
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VillagerTradingListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WitherListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener;
import io.github.thebusybiscuit.slimefun4.implementation.resources.GEOResourcesSetup;
@ -165,6 +166,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
local = new LocalizationService(this, "", null);
gpsNetwork = new GPSNetwork();
command.register();
registry.load(config);
}
else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
long timestamp = System.nanoTime();
@ -255,7 +257,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Armor Update Task
if (config.getBoolean("options.enable-armor-effects")) {
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(), 0L, config.getInt("options.armor-update-interval") * 20L);
boolean radioactiveFire = config.getBoolean("options.burn-players-when-radioactive");
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(radioactiveFire), 0L, config.getInt("options.armor-update-interval") * 20L);
}
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
@ -364,7 +367,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Save all registered Worlds
for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) {
try {
entry.getValue().save(true);
entry.getValue().saveAndRemove();
}
catch (Exception x) {
getLogger().log(Level.SEVERE, x, () -> "An Error occurred while saving Slimefun-Blocks in World '" + entry.getKey() + "' for Slimefun " + getVersion());
@ -440,8 +443,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new FireworksListener(this);
new WitherListener(this);
new IronGolemListener(this);
new PlayerInteractEntityListener(this);
new EntityInteractionListener(this);
new MobDropListener(this);
new VillagerTradingListener(this);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
new BeeListener(this);

View File

@ -10,6 +10,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
@ -18,7 +19,6 @@ import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
@ -36,6 +36,24 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance(), "search");
private final ItemStack item;
public BookSlimefunGuide() {
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Book GUI)"));
List<String> lore = new LinkedList<>();
lore.add("");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
public SlimefunGuideLayout getLayout() {
@ -49,7 +67,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
@Override
public ItemStack getItem() {
return new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&aSlimefun Guide &7(Book GUI)", "", "&eRight Click &8\u21E8 &7Browse Items", "&eShift + Right Click &8\u21E8 &7Open Settings / Credits");
return item;
}
private void openBook(Player p, PlayerProfile profile, List<ChatComponent> lines, boolean backButton) {
@ -112,37 +130,41 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
lines.add(new ChatComponent(ChatColor.DARK_GRAY + "\u21E8" + ChatColor.DARK_BLUE + " Tier " + tier + "\n"));
}
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
}
else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
addCategory(p, profile, category, lines);
}
}
openBook(p, profile, lines, false);
}
private void addCategory(Player p, PlayerProfile profile, Category category, List<ChatComponent> lines) {
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
}
else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
}
@Override
public void openCategory(PlayerProfile profile, Category category, int page) {
Player p = profile.getPlayer();
@ -159,20 +181,20 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
List<ChatComponent> items = new LinkedList<>();
for (SlimefunItem item : category.getItems()) {
if (Slimefun.hasPermission(p, item, false)) {
if (Slimefun.isEnabled(p, item, false)) {
appendSlimefunItem(category, page, p, profile, item, items);
for (SlimefunItem slimefunItem : category.getItems()) {
if (Slimefun.hasPermission(p, slimefunItem, false)) {
if (Slimefun.isEnabled(p, slimefunItem, false)) {
addSlimefunItem(category, page, p, profile, slimefunItem, items);
}
}
else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(item.getItem())) + "\n");
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(slimefunItem.getItem())) + "\n");
List<String> lore = new ArrayList<>();
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(item.getItem())));
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(slimefunItem.getItem())));
lore.add("");
for (String line : SlimefunPlugin.getPermissionsService().getLore(item)) {
for (String line : SlimefunPlugin.getPermissionsService().getLore(slimefunItem)) {
lore.add(ChatColors.color(line));
}
@ -188,7 +210,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
private void appendSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
private void addSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getID().toLowerCase(Locale.ROOT));
if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
@ -196,21 +218,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n");
component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)"));
component.setClickEvent(new ClickEvent(key, player -> Slimefun.runSync(() -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(p.getUniqueId())) {
if (research.canUnlock(p)) {
if (profile.hasUnlocked(research)) {
openCategory(profile, category, page);
}
else {
unlockItem(p, item, pl -> openCategory(profile, category, page));
}
}
else {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-enough-xp", true);
}
}
})));
component.setClickEvent(new ClickEvent(key, player -> research(player, profile, item, research, category, page)));
items.add(component);
}
@ -230,6 +238,24 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
private void research(Player p, PlayerProfile profile, SlimefunItem item, Research research, Category category, int page) {
Slimefun.runSync(() -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(p.getUniqueId())) {
if (research.canUnlock(p)) {
if (profile.hasUnlocked(research)) {
openCategory(profile, category, page);
}
else {
unlockItem(p, item, pl -> openCategory(profile, category, page));
}
}
else {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-enough-xp", true);
}
}
});
}
@Override
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
// We need to write a book implementation for this at some point

View File

@ -1,16 +1,41 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;
import org.bukkit.entity.Player;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
private final ItemStack item;
public CheatSheetSlimefunGuide() {
super(false);
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&cSlimefun Guide &4(Cheat Sheet)"));
List<String> lore = new LinkedList<>();
lore.add(ChatColors.color("&4&lOnly openable by Admins"));
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
@ -23,6 +48,11 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
return SlimefunGuideLayout.CHEAT_SHEET;
}
@Override
public ItemStack getItem() {
return item;
}
@Override
protected void createHeader(Player p, PlayerProfile profile, ChestMenu menu) {
super.createHeader(p, profile, menu);

View File

@ -18,7 +18,9 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.RecipeChoice.MaterialChoice;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
@ -50,6 +52,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36;
private final ItemStack item;
private final int[] recipeSlots = { 3, 4, 5, 12, 13, 14, 21, 22, 23 };
private final Sound sound;
private final boolean showVanillaRecipes;
@ -63,6 +66,21 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
else {
sound = Sound.ENTITY_BAT_TAKEOFF;
}
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Chest GUI)"));
List<String> lore = new LinkedList<>();
lore.add("");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
@ -72,7 +90,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
@Override
public ItemStack getItem() {
return new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&aSlimefun Guide &7(Chest GUI)", "", "&eRight Click &8\u21E8 &7Browse Items", "&eShift + Right Click &8\u21E8 &7Open Settings / Credits");
return item;
}
@Override
@ -313,17 +331,17 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
int index = 9;
// Find items and add them
for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
String itemName = ChatColor.stripColor(item.getItemName()).toLowerCase(Locale.ROOT);
for (SlimefunItem slimefunItem : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
String itemName = ChatColor.stripColor(slimefunItem.getItemName()).toLowerCase(Locale.ROOT);
if (index == 44) {
break;
}
if (!itemName.isEmpty() && (itemName.equals(searchTerm) || itemName.contains(searchTerm))) {
ItemStack itemstack = new CustomItem(item.getItem(), meta -> {
ItemStack itemstack = new CustomItem(slimefunItem.getItem(), meta -> {
List<String> lore = null;
Category category = item.getCategory();
Category category = slimefunItem.getCategory();
if (category != null) {
ItemStack categoryItem = category.getItem(p);
@ -341,10 +359,10 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
menu.addMenuClickHandler(index, (pl, slot, itm, action) -> {
try {
if (!isSurvivalMode()) {
pl.getInventory().addItem(item.getItem().clone());
pl.getInventory().addItem(slimefunItem.getItem().clone());
}
else {
displayItem(profile, item, true);
displayItem(profile, slimefunItem, true);
}
}
catch (Exception | LinkageError x) {
@ -400,30 +418,9 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
RecipeChoiceTask task = new RecipeChoiceTask();
if (optional.isPresent()) {
MinecraftRecipe<?> mcRecipe = optional.get();
showRecipeChoices(recipe, recipeItems, task);
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
if (choices.length == 1 && choices[0] instanceof MaterialChoice) {
recipeItems[4] = new ItemStack(((MaterialChoice) choices[0]).getChoices().get(0));
if (((MaterialChoice) choices[0]).getChoices().size() > 1) {
task.add(recipeSlots[4], (MaterialChoice) choices[0]);
}
}
else {
for (int i = 0; i < choices.length; i++) {
if (choices[i] instanceof MaterialChoice) {
recipeItems[i] = new ItemStack(((MaterialChoice) choices[i]).getChoices().get(0));
if (((MaterialChoice) choices[i]).getChoices().size() > 1) {
task.add(recipeSlots[i], (MaterialChoice) choices[i]);
}
}
}
}
recipeType = new RecipeType(mcRecipe);
recipeType = new RecipeType(optional.get());
result = recipe.getResult();
}
else {
@ -465,6 +462,29 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
}
}
private <T extends Recipe> void showRecipeChoices(T recipe, ItemStack[] recipeItems, RecipeChoiceTask task) {
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
if (choices.length == 1 && choices[0] instanceof MaterialChoice) {
recipeItems[4] = new ItemStack(((MaterialChoice) choices[0]).getChoices().get(0));
if (((MaterialChoice) choices[0]).getChoices().size() > 1) {
task.add(recipeSlots[4], (MaterialChoice) choices[0]);
}
}
else {
for (int i = 0; i < choices.length; i++) {
if (choices[i] instanceof MaterialChoice) {
recipeItems[i] = new ItemStack(((MaterialChoice) choices[i]).getChoices().get(0));
if (((MaterialChoice) choices[i]).getChoices().size() > 1) {
task.add(recipeSlots[i], (MaterialChoice) choices[i]);
}
}
}
}
}
@Override
public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
Player p = profile.getPlayer();
@ -670,15 +690,15 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private void addDisplayRecipe(ChestMenu menu, PlayerProfile profile, List<ItemStack> recipes, int slot, int i, int page) {
if ((i + (page * 18)) < recipes.size()) {
ItemStack item = recipes.get(i + (page * 18));
ItemStack displayItem = recipes.get(i + (page * 18));
// We want to clone this item to avoid corrupting the original
// but we wanna make sure no stupid addon creator sneaked some nulls in here
if (item != null) {
item = item.clone();
if (displayItem != null) {
displayItem = displayItem.clone();
}
menu.replaceExistingItem(slot, item);
menu.replaceExistingItem(slot, displayItem);
if (page == 0) {
menu.addMenuClickHandler(slot, (pl, s, itemstack, action) -> {

View File

@ -6,6 +6,7 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
@ -39,24 +40,28 @@ public abstract class MinerAndroid extends ProgrammableAndroid {
protected void dig(Block b, BlockMenu menu, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
String blockId = BlockStorage.checkID(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
// We only want to break non-Slimefun blocks
String blockId = BlockStorage.checkID(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
}
}
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
}
}
}
@ -66,30 +71,34 @@ public abstract class MinerAndroid extends ProgrammableAndroid {
protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
SlimefunItem blockId = BlockStorage.check(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
move(b, face, block);
b.setType(Material.AIR);
BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation());
}
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
SlimefunItem blockId = BlockStorage.check(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
}
}
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
move(b, face, block);
}
}
else {
move(b, face, block);
}
}
else {

View File

@ -1,26 +1,33 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Nameable;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Dispenser;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -39,7 +46,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see BlockPlacerPlaceEvent
*
*/
public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
public class BlockPlacer extends SlimefunItem {
private final ItemSetting<List<String>> blacklist = new ItemSetting<>("unplaceable-blocks", MaterialCollections.getAllUnbreakableBlocks().stream().map(Material::name).collect(Collectors.toList()));
@ -47,11 +54,28 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
super(category, item, recipeType, recipe);
addItemSetting(blacklist);
addItemHandler(onPlace(), onBlockDispense());
}
@Override
public BlockDispenseHandler getItemHandler() {
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
Player p = e.getPlayer();
Block b = e.getBlock();
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
}
};
}
private BlockDispenseHandler onBlockDispense() {
return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) {
return;
}
if (isShulkerBox(e.getItem().getType())) {
// Since vanilla Dispensers can already place Shulker boxes, we
// simply fallback to the vanilla behaviour.
@ -76,6 +100,31 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
};
}
/**
* This checks whether the {@link Player} who placed down this {@link BlockPlacer} has
* building permissions at that {@link Location}.
*
* @param dispenser
* The {@link Dispenser} who represents our {@link BlockPlacer}
* @param target
* The {@link Block} where it should be placed
*
* @return Whether this action is permitted or not
*/
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.
return true;
}
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner));
return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK);
}
private boolean isShulkerBox(Material type) {
return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX");
}
@ -139,14 +188,17 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
ItemMeta meta = item.getItemMeta();
if (meta.hasDisplayName()) {
BlockState blockState = facedBlock.getState();
BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false);
if ((blockState instanceof Nameable)) {
((Nameable) blockState).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);
}
}
// Update block state after changing name
blockState.update();
}
}

View File

@ -10,8 +10,8 @@ public class AdvancedCargoOutputNode extends AbstractFilterNode {
private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 22, 23, 24, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe, null);
}
@Override

View File

@ -60,10 +60,14 @@ public class EnergyRegulator extends SlimefunItem {
@Override
public void tick(Block b, SlimefunItem item, Config data) {
EnergyNet network = EnergyNet.getNetworkFromLocationOrCreate(b.getLocation());
network.tick(b);
EnergyRegulator.this.tick(b);
}
});
}
private void tick(Block b) {
EnergyNet network = EnergyNet.getNetworkFromLocationOrCreate(b.getLocation());
network.tick(b);
}
}

View File

@ -11,6 +11,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -42,6 +43,21 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
return capacity;
}
private int nextIndex(int i) {
int index = i;
do {
index++;
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
return index;
}
protected ItemUseHandler getItemUseHandler() {
return e -> {
Player p = e.getPlayer();
@ -64,29 +80,33 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
SlimefunItem selectedItem = modes.get(index).getItem();
String itemName = selectedItem != null ? selectedItem.getItemName() : "Unknown";
SlimefunPlugin.getLocalization().sendMessage(p, "messages.mode-change", true, msg -> msg.replace("%device%", "Multi Tool").replace("%mode%", ChatColor.stripColor(itemName)));
SlimefunPlugin.getLocalization().sendMessage(p, "messages.multi-tool.mode-change", true, msg -> msg.replace("%device%", "Multi Tool").replace("%mode%", ChatColor.stripColor(itemName)));
selectedMode.put(p.getUniqueId(), index);
}
};
}
private int nextIndex(int i) {
int index = i;
do {
index++;
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
return index;
private ToolUseHandler getToolUseHandler() {
return (e, tool, fortune, drops) -> {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
e.setCancelled(true);
};
}
private ToolUseHandler getToolUseHandler() {
return (e, tool, fortune, drops) -> e.setCancelled(true);
private EntityInteractHandler getEntityInteractionHandler() {
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;
}
};
}
@Override
@ -95,6 +115,7 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
addItemHandler(getItemUseHandler());
addItemHandler(getToolUseHandler());
addItemHandler(getEntityInteractionHandler());
}
}

View File

@ -11,23 +11,23 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public abstract class LavaGenerator extends AGenerator {
public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
@Override
protected void registerDefaultFuelTypes() {
registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET)));
}
registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET)));
}
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL);
}
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL);
}
@Override
public String getInventoryTitle() {
return "&4Lava Generator";
}
@Override
public String getInventoryTitle() {
return "&4Lava Generator";
}
}

View File

@ -48,6 +48,8 @@ public abstract class ElectricPress extends AContainer implements RecipeDisplayI
addRecipe(4, new ItemStack(Material.IRON_NUGGET, 9), new ItemStack(Material.IRON_INGOT));
addRecipe(4, new ItemStack(Material.GOLD_NUGGET, 9), new ItemStack(Material.GOLD_INGOT));
addRecipe(4, new ItemStack(Material.COAL, 9), new ItemStack(Material.COAL_BLOCK));
addRecipe(4, new ItemStack(Material.SAND, 4), new ItemStack(Material.SANDSTONE));
addRecipe(4, new ItemStack(Material.RED_SAND, 4), new ItemStack(Material.RED_SANDSTONE));
addRecipe(5, new ItemStack(Material.IRON_INGOT, 9), new ItemStack(Material.IRON_BLOCK));
addRecipe(5, new ItemStack(Material.GOLD_INGOT, 9), new ItemStack(Material.GOLD_BLOCK));

View File

@ -1,12 +1,25 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.food;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CoolerListener;
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;
/**
@ -19,10 +32,69 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see CoolerListener
*
*/
public class Juice extends SlimefunItem {
public class Juice extends SimpleSlimefunItem<ItemConsumptionHandler> {
private final List<PotionEffect> effects;
public Juice(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this(category, item, recipeType, recipe, null);
}
public Juice(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
ItemMeta meta = item.getItemMeta();
if (meta instanceof PotionMeta) {
effects = ((PotionMeta) meta).getCustomEffects();
}
else {
effects = new ArrayList<>();
}
}
@Override
public ItemConsumptionHandler getItemHandler() {
return (e, p, item) -> {
// Fix for Saturation on potions is no longer working,
// Minecraft has been broken when it comes to Saturation potions for a long time
for (PotionEffect effect : effects) {
if (effect.getType().equals(PotionEffectType.SATURATION)) {
p.addPotionEffect(effect);
break;
}
}
removeGlassBottle(p, item);
};
}
/**
* Determines from which hand the juice is being drunk, and its amount
*
* @param p
* The {@link Player} that triggered this
* @param item
* The {@link ItemStack} in question
*/
private void removeGlassBottle(Player p, ItemStack item) {
if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInMainHand(), true)) {
if (p.getInventory().getItemInMainHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInMainHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
else if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInOffHand(), true)) {
if (p.getInventory().getItemInOffHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInOffHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
}
}

View File

@ -25,13 +25,12 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
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;
public abstract class GEOMiner extends AContainer implements InventoryBlock, RecipeDisplayItem {
public abstract class GEOMiner extends AContainer implements RecipeDisplayItem {
private static final int[] BORDER = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 26, 27, 35, 36, 44, 45, 53 };
private static final int[] OUTPUT_BORDER = { 19, 20, 21, 22, 23, 24, 25, 28, 34, 37, 43, 46, 47, 48, 49, 50, 51, 52 };

View File

@ -1,14 +1,15 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import org.bukkit.GameMode;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.entity.ZombieVillager;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -38,8 +39,11 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
@Override
public EntityInteractHandler getItemHandler() {
return (p, entity, item, offhand) -> {
return (e, item, offhand) -> {
Entity entity = e.getRightClicked();
if (entity.getType() == EntityType.ZOMBIE_VILLAGER) {
Player p = e.getPlayer();
if (p.getGameMode() != GameMode.CREATIVE) {
ItemUtils.consumeItem(item, false);

View File

@ -11,6 +11,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityEvent;
@ -127,7 +128,7 @@ public class Talisman extends SlimefunItem {
}
private static boolean hasMessage(Talisman talisman) {
return !("").equalsIgnoreCase(talisman.getMessageSuffix());
return talisman.getMessageSuffix() != null;
}
public static boolean checkFor(Event e, SlimefunItemStack stack) {
@ -224,6 +225,9 @@ public class Talisman extends SlimefunItem {
else if (e instanceof BlockBreakEvent) {
return ((BlockBreakEvent) e).getPlayer();
}
else if (e instanceof BlockDropItemEvent) {
return ((BlockDropItemEvent) e).getPlayer();
}
else if (e instanceof PlayerEvent) {
return ((PlayerEvent) e).getPlayer();
}

View File

@ -0,0 +1,29 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.misc;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VillagerTradingListener;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link SyntheticEmerald} is an almost normal emerald.
* It can even be used to trade with {@link Villager Villagers}.
*
* @author TheBusyBiscuit
*
* @see VillagerTradingListener
*
*/
public class SyntheticEmerald extends SlimefunItem {
public SyntheticEmerald(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
setUseableInWorkbench(true);
}
}

View File

@ -131,10 +131,8 @@ public class IndustrialMiner extends MultiBlockMachine {
return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2));
case LAPIS_ORE:
return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4));
case ANCIENT_DEBRIS:
return new ItemStack(Material.ANCIENT_DEBRIS);
default:
// This includes Iron and Gold ore
// This includes Iron and Gold ore (and Ancient Debris)
return new ItemStack(ore);
}
}
@ -212,7 +210,19 @@ public class IndustrialMiner extends MultiBlockMachine {
* @return Whether this {@link IndustrialMiner} is capable of mining this {@link Material}
*/
public boolean canMine(Material type) {
return type.name().endsWith("_ORE") || (type == Material.ANCIENT_DEBRIS && canMineAncientDebris.getValue());
if (type.name().endsWith("_ORE")) {
return true;
}
else if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
if (type == Material.GILDED_BLACKSTONE) {
return true;
}
else if (type == Material.ANCIENT_DEBRIS) {
return canMineAncientDebris.getValue();
}
}
return false;
}
}

View File

@ -80,17 +80,18 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
}
private void pushEntity(Player p, Entity entity) {
Vector vector = entity.getLocation().toVector().subtract(p.getLocation().toVector()).normalize();
vector.multiply(STRENGTH);
vector.setY(0.9);
entity.setVelocity(vector);
if (entity.getType() != EntityType.PLAYER || p.getWorld().getPVP()) {
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, entity, DamageCause.ENTITY_ATTACK, 6D);
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, entity, DamageCause.ENTITY_ATTACK, DAMAGE);
Bukkit.getPluginManager().callEvent(event);
// Fixes #2207 - Only apply Vector if the Player is able to damage the entity
if (!event.isCancelled()) {
((LivingEntity) entity).damage(DAMAGE);
Vector vector = entity.getLocation().toVector().subtract(p.getLocation().toVector()).normalize();
vector.multiply(STRENGTH);
vector.setY(0.9);
entity.setVelocity(vector);
((LivingEntity) entity).damage(event.getDamage());
}
}
}

View File

@ -27,6 +27,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
@ -53,6 +54,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/
public class AncientAltarListener implements Listener {
public static final String ITEM_PREFIX = ChatColors.color("&dALTAR &3Probe - &e");
private AncientAltar altar;
private final Set<AltarRecipe> altarRecipes = new HashSet<>();
@ -303,7 +306,7 @@ public class AncientAltarListener implements Listener {
}
String nametag = ItemUtils.getItemName(stack);
Item entity = b.getWorld().dropItem(b.getLocation().add(0.5, 1.2, 0.5), new CustomItem(stack, "&5&dALTAR &3Probe - &e" + System.nanoTime()));
Item entity = b.getWorld().dropItem(b.getLocation().add(0.5, 1.2, 0.5), new CustomItem(stack, ITEM_PREFIX + System.nanoTime()));
entity.setVelocity(new Vector(0, 0.1, 0));
SlimefunUtils.markAsNoPickup(entity, "altar_item");
entity.setCustomNameVisible(true);

View File

@ -42,7 +42,9 @@ public class BeeListener implements Listener {
if (profile.hasFullProtectionAgainst(ProtectionType.BEES)) {
for (ItemStack armor : p.getInventory().getArmorContents()) {
ItemUtils.damageItem(armor, 1, false);
if (armor != null) {
ItemUtils.damageItem(armor, 1, false);
}
}
e.setDamage(0D);

View File

@ -32,6 +32,17 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link BlockListener} is responsible for listening to the {@link BlockPlaceEvent}
* and {@link BlockBreakEvent}.
*
* @author TheBusyBiscuit
*
* @see BlockPlaceHandler
* @see BlockBreakHandler
* @see ToolUseHandler
*
*/
public class BlockListener implements Listener {
// Materials that require a Block under it, e.g. Pressure Plates
@ -49,7 +60,7 @@ public class BlockListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockRegister(BlockPlaceEvent e) {
public void onBlockPlace(BlockPlaceEvent e) {
if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true);
return;
@ -81,7 +92,7 @@ public class BlockListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockUnregister(BlockBreakEvent e) {
public void onBlockBreak(BlockBreakEvent e) {
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock());
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
@ -89,50 +100,58 @@ public class BlockListener implements Listener {
List<ItemStack> drops = new ArrayList<>();
if (item.getType() != Material.AIR) {
SlimefunItem tool = SlimefunItem.getByItem(item);
if (tool != null) {
if (Slimefun.hasUnlocked(e.getPlayer(), tool, true)) {
tool.callItemHandler(ToolUseHandler.class, handler -> handler.onToolUse(e, item, fortune, drops));
}
else {
e.setCancelled(true);
}
}
callToolHandler(e, item, fortune, drops);
}
if (!e.isCancelled()) {
SlimefunItem sfItem = BlockStorage.check(e.getBlock());
if (sfItem == null && SlimefunPlugin.getBlockDataService().isTileEntity(e.getBlock().getType())) {
Optional<String> blockData = SlimefunPlugin.getBlockDataService().getBlockData(e.getBlock());
if (blockData.isPresent()) {
sfItem = SlimefunItem.getByID(blockData.get());
}
}
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getID());
if (blockHandler != null) {
if (!blockHandler.onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK)) {
e.setCancelled(true);
return;
}
}
else {
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onBlockBreak(e, item, fortune, drops));
}
drops.addAll(sfItem.getDrops());
BlockStorage.clearBlockInfo(e.getBlock());
}
callBlockHandler(e, item, fortune, drops);
}
dropItems(e, drops);
}
private void callToolHandler(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
SlimefunItem tool = SlimefunItem.getByItem(item);
if (tool != null) {
if (Slimefun.hasUnlocked(e.getPlayer(), tool, true)) {
tool.callItemHandler(ToolUseHandler.class, handler -> handler.onToolUse(e, item, fortune, drops));
}
else {
e.setCancelled(true);
}
}
}
private void callBlockHandler(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
SlimefunItem sfItem = BlockStorage.check(e.getBlock());
if (sfItem == null && SlimefunPlugin.getBlockDataService().isTileEntity(e.getBlock().getType())) {
Optional<String> blockData = SlimefunPlugin.getBlockDataService().getBlockData(e.getBlock());
if (blockData.isPresent()) {
sfItem = SlimefunItem.getByID(blockData.get());
}
}
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getID());
if (blockHandler != null) {
if (!blockHandler.onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK)) {
e.setCancelled(true);
return;
}
}
else {
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onBlockBreak(e, item, fortune, drops));
}
drops.addAll(sfItem.getDrops());
BlockStorage.clearBlockInfo(e.getBlock());
}
}
private void dropItems(BlockBreakEvent e, List<ItemStack> drops) {
if (!drops.isEmpty()) {
e.getBlock().setType(Material.AIR);

View File

@ -4,6 +4,7 @@ import java.util.logging.Level;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Skull;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.Rotatable;
@ -58,29 +59,10 @@ public class DebugFishListener implements Listener {
if (p.hasPermission("slimefun.debugging")) {
if (e.getAction() == Action.LEFT_CLICK_BLOCK) {
if (p.isSneaking()) {
if (BlockStorage.hasBlockInfo(e.getClickedBlock())) {
BlockStorage.clearBlockInfo(e.getClickedBlock());
}
}
else {
e.setCancelled(false);
}
onLeftClick(p, e.getClickedBlock(), e);
}
else if (e.getAction() == Action.RIGHT_CLICK_BLOCK) {
if (p.isSneaking()) {
Block b = e.getClickedBlock().getRelative(e.getBlockFace());
b.setType(Material.PLAYER_HEAD);
SkullBlock.setFromHash(b, HeadTexture.MISSING_TEXTURE.getTexture());
}
else if (BlockStorage.hasBlockInfo(e.getClickedBlock())) {
try {
sendInfo(p, e.getClickedBlock());
}
catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception occured while using a Debug-Fish", x);
}
}
onRightClick(p, e.getClickedBlock(), e.getBlockFace());
}
}
else {
@ -89,6 +71,33 @@ public class DebugFishListener implements Listener {
}
}
private void onLeftClick(Player p, Block b, PlayerInteractEvent e) {
if (p.isSneaking()) {
if (BlockStorage.hasBlockInfo(b)) {
BlockStorage.clearBlockInfo(b);
}
}
else {
e.setCancelled(false);
}
}
private void onRightClick(Player p, Block b, BlockFace face) {
if (p.isSneaking()) {
Block block = b.getRelative(face);
block.setType(Material.PLAYER_HEAD);
SkullBlock.setFromHash(block, HeadTexture.MISSING_TEXTURE.getTexture());
}
else if (BlockStorage.hasBlockInfo(b)) {
try {
sendInfo(p, b);
}
catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception occured while using a Debug-Fish", x);
}
}
}
private void sendInfo(Player p, Block b) {
SlimefunItem item = BlockStorage.check(b);

View File

@ -4,7 +4,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
@ -21,14 +21,14 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
* @see EntityInteractHandler
*
*/
public class PlayerInteractEntityListener implements Listener {
public class EntityInteractionListener implements Listener {
public PlayerInteractEntityListener(SlimefunPlugin plugin) {
public EntityInteractionListener(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onInteractEntity(PlayerInteractAtEntityEvent e) {
public void onInteractEntity(PlayerInteractEntityEvent e) {
if (!e.getRightClicked().isValid()) {
return;
}
@ -45,7 +45,7 @@ public class PlayerInteractEntityListener implements Listener {
SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
if (sfItem != null && Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) {
sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e.getPlayer(), e.getRightClicked(), itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
}
}
}

View File

@ -4,8 +4,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@ -16,8 +16,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
*/
public class ItemPickupListener implements Listener {
private static final String ITEM_PREFIX = ChatColors.color("&5&dALTAR &3Probe - &e");
public ItemPickupListener(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@ -27,9 +25,13 @@ public class ItemPickupListener implements Listener {
if (SlimefunUtils.hasNoPickupFlag(e.getItem())) {
e.setCancelled(true);
}
else if (e.getItem().getItemStack().hasItemMeta() && e.getItem().getItemStack().getItemMeta().hasDisplayName() && e.getItem().getItemStack().getItemMeta().getDisplayName().startsWith(ITEM_PREFIX)) {
e.setCancelled(true);
e.getItem().remove();
else if (e.getItem().getItemStack().hasItemMeta()) {
ItemMeta meta = e.getItem().getItemStack().getItemMeta();
if (meta.hasDisplayName() && meta.getDisplayName().startsWith(AncientAltarListener.ITEM_PREFIX)) {
e.setCancelled(true);
e.getItem().remove();
}
}
}
@ -38,9 +40,13 @@ public class ItemPickupListener implements Listener {
if (SlimefunUtils.hasNoPickupFlag(e.getItem())) {
e.setCancelled(true);
}
else if (e.getItem().getItemStack().hasItemMeta() && e.getItem().getItemStack().getItemMeta().hasDisplayName() && e.getItem().getItemStack().getItemMeta().getDisplayName().startsWith(ITEM_PREFIX)) {
e.setCancelled(true);
e.getItem().remove();
else if (e.getItem().getItemStack().hasItemMeta()) {
ItemMeta meta = e.getItem().getItemStack().getItemMeta();
if (meta.hasDisplayName() && meta.getDisplayName().startsWith(AncientAltarListener.ITEM_PREFIX)) {
e.setCancelled(true);
e.getItem().remove();
}
}
}
}

View File

@ -36,7 +36,7 @@ public class PiglinListener implements Listener {
}
@EventHandler
public void onEntityPickup(EntityPickupItemEvent e) {
public void onPickup(EntityPickupItemEvent e) {
if (e.getEntityType() == EntityType.PIGLIN) {
ItemStack item = e.getItem().getItemStack();
@ -47,6 +47,33 @@ public class PiglinListener implements Listener {
}
}
@EventHandler
public void onInteract(PlayerInteractEntityEvent e) {
if (!e.getRightClicked().isValid() || e.getRightClicked().getType() != EntityType.PIGLIN) {
return;
}
Player p = e.getPlayer();
ItemStack item;
if (e.getHand() == EquipmentSlot.OFF_HAND) {
item = p.getInventory().getItemInOffHand();
}
else {
item = p.getInventory().getItemInMainHand();
}
// We only care about Gold since it's the actual "Bartering" we wanna prevent
if (item.getType() == Material.GOLD_INGOT) {
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null) {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.piglin-barter", true);
e.setCancelled(true);
}
}
}
@EventHandler
public void onPiglinDropItem(EntityDropItemEvent e) {
if (e.getEntity() instanceof Piglin) {
@ -76,31 +103,4 @@ public class PiglinListener implements Listener {
}
}
}
@EventHandler
public void onInteractEntity(PlayerInteractEntityEvent e) {
if (!e.getRightClicked().isValid() || e.getRightClicked().getType() != EntityType.PIGLIN) {
return;
}
Player p = e.getPlayer();
ItemStack item;
if (e.getHand() == EquipmentSlot.OFF_HAND) {
item = p.getInventory().getItemInOffHand();
}
else {
item = p.getInventory().getItemInMainHand();
}
// We only care about Gold since it's the actual "Bartering" we wanna prevent
if (item.getType() == Material.GOLD_INGOT) {
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null) {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.piglin-barter", true);
e.setCancelled(true);
}
}
}
}

View File

@ -33,8 +33,8 @@ public class SlimefunGuideListener implements Listener {
return;
}
SlimefunGuideLayout type = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST;
p.getInventory().addItem(SlimefunGuide.getItem(type));
SlimefunGuideLayout type = SlimefunGuide.getDefaultLayout();
p.getInventory().addItem(SlimefunGuide.getItem(type).clone());
}
}
@ -69,7 +69,7 @@ public class SlimefunGuideListener implements Listener {
Player p = e.getPlayer();
ItemStack item = e.getItem();
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true)) {
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true, false)) {
e.cancel();
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {

View File

@ -1,22 +1,23 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice;
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 handling the {@link ItemConsumptionHandler}
* for any {@link SlimefunItem}.
*
* @author TheBusyBiscuit
*
*/
public class SlimefunItemConsumeListener implements Listener {
public SlimefunItemConsumeListener(SlimefunPlugin plugin) {
@ -31,53 +32,11 @@ public class SlimefunItemConsumeListener implements Listener {
if (sfItem != null) {
if (Slimefun.hasUnlocked(p, sfItem, true)) {
if (sfItem instanceof Juice) {
// Fix for Saturation on potions is no longer working
for (PotionEffect effect : ((PotionMeta) item.getItemMeta()).getCustomEffects()) {
if (effect.getType().equals(PotionEffectType.SATURATION)) {
p.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, effect.getDuration(), effect.getAmplifier()));
break;
}
}
removeGlassBottle(p, item);
}
else {
sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item));
}
sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item));
}
else {
e.setCancelled(true);
}
}
}
/**
* Determines from which hand the juice is being drunk, and its amount
*
* @param p
* The {@link Player} that triggered this
* @param item
* The {@link ItemStack} in question
*/
private void removeGlassBottle(Player p, ItemStack item) {
if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInMainHand(), true)) {
if (p.getInventory().getItemInMainHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInMainHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
else if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInOffHand(), true)) {
if (p.getInventory().getItemInOffHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInOffHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
}
}

View File

@ -13,13 +13,14 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
@ -35,7 +36,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
@ -229,32 +229,48 @@ public class TalismanListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
@EventHandler(ignoreCancelled = true)
public void onBlockDropItems(BlockDropItemEvent e) {
// We only want to double ores
if (MaterialCollections.getAllOres().contains(e.getBlock().getType())) {
Material type = e.getBlockState().getType();
if (type.name().endsWith("_ORE")) {
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
if (item.getType() != Material.AIR && item.getAmount() > 0) {
Collection<ItemStack> drops = e.getBlock().getDrops(item);
int dropAmount = 1;
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
Collection<Item> drops = e.getItems();
if (item.getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS) && !item.getEnchantments().containsKey(Enchantment.SILK_TOUCH)) {
Random random = ThreadLocalRandom.current();
dropAmount = random.nextInt(item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS) + 2) - 1;
dropAmount = Math.max(dropAmount, 1);
dropAmount = (e.getBlock().getType() == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1) * (dropAmount + 1);
}
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) {
int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
boolean doubledDrops = false;
if (!item.getEnchantments().containsKey(Enchantment.SILK_TOUCH) && Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) {
for (ItemStack drop : drops) {
if (!drop.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - drop.getAmount());
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(drop, amount));
for (Item drop : drops) {
ItemStack droppedItem = drop.getItemStack();
if (!droppedItem.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount());
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount));
doubledDrops = true;
}
}
if (doubledDrops) {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.miner", true);
}
}
}
}
}
private int getAmountWithFortune(Material type, int fortuneLevel) {
if (fortuneLevel > 0) {
Random random = ThreadLocalRandom.current();
int amount = random.nextInt(fortuneLevel + 2) - 1;
amount = Math.max(amount, 1);
amount = (type == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1) * (amount + 1);
return amount;
}
else {
return 1;
}
}
}

View File

@ -6,6 +6,7 @@ import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
@ -95,10 +96,24 @@ public class VanillaMachinesListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onPreBrew(InventoryClickEvent e) {
Inventory inventory = e.getInventory();
Inventory clickedInventory = e.getClickedInventory();
Inventory topInventory = e.getView().getTopInventory();
if (inventory.getType() == InventoryType.BREWING && e.getRawSlot() < inventory.getSize() && inventory.getHolder() instanceof BrewingStand) {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor())));
if (clickedInventory != null && topInventory.getType() == InventoryType.BREWING && topInventory.getHolder() instanceof BrewingStand) {
if (e.getAction() == InventoryAction.HOTBAR_SWAP) {
e.setCancelled(true);
return;
}
if (clickedInventory.getType() == InventoryType.BREWING) {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor())));
} else {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCurrentItem())));
}
if (e.getResult() == Result.DENY) {
SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "brewing_stand.not-working", true);
}
}
}

View File

@ -0,0 +1,57 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.SyntheticEmerald;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Listener} prevents any {@link SlimefunItem} from being used to trade with
* Villagers, with one exception being {@link SyntheticEmerald}.
*
* @author TheBusyBiscuit
*
*/
public class VillagerTradingListener implements Listener {
public VillagerTradingListener(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(ignoreCancelled = true)
public void onPreBrew(InventoryClickEvent e) {
Inventory clickedInventory = e.getClickedInventory();
Inventory topInventory = e.getView().getTopInventory();
if (clickedInventory != null && topInventory.getType() == InventoryType.MERCHANT) {
if (e.getAction() == InventoryAction.HOTBAR_SWAP) {
e.setCancelled(true);
return;
}
if (clickedInventory.getType() == InventoryType.MERCHANT) {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor())));
}
else {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCurrentItem())));
}
if (e.getResult() == Result.DENY) {
SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "villagers.no-trading", true);
}
}
}
private boolean isUnallowed(SlimefunItem item) {
return item != null && !(item instanceof VanillaItem) && !(item instanceof SyntheticEmerald) && !item.isDisabled();
}
}

View File

@ -28,7 +28,7 @@ public class WorldListener implements Listener {
BlockStorage storage = BlockStorage.getStorage(e.getWorld());
if (storage != null) {
storage.save(true);
storage.saveAndRemove();
}
else {
Slimefun.getLogger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName());

View File

@ -110,7 +110,7 @@ public final class ResearchSetup {
register("redstone_alloy", 84, "Redstone Alloy", 16, SlimefunItems.REDSTONE_ALLOY);
register("carbonado_tools", 85, "Top Tier Machines", 24, SlimefunItems.CARBONADO_MULTI_TOOL, SlimefunItems.CARBONADO_JETPACK, SlimefunItems.CARBONADO_JETBOOTS);
register("first_aid", 86, "First Aid", 2, SlimefunItems.CLOTH, SlimefunItems.RAG, SlimefunItems.BANDAGE, SlimefunItems.SPLINT, SlimefunItems.TIN_CAN, SlimefunItems.VITAMINS, SlimefunItems.MEDICINE);
register("gold_armor", 87, "Shiny Armor", 13, SlimefunItems.GOLD_HELMET, SlimefunItems.GOLD_CHESTPLATE, SlimefunItems.GOLD_LEGGINGS, SlimefunItems.GOLD_BOOTS);
register("gold_armor", 87, "Shiny Armor", 13, SlimefunItems.GOLDEN_HELMET_12K, SlimefunItems.GOLDEN_CHESTPLATE_12K, SlimefunItems.GOLDEN_LEGGINGS_12K, SlimefunItems.GOLDEN_BOOTS_12K);
register("night_vision_googles", 89, "Night Vision Goggles", 10, SlimefunItems.NIGHT_VISION_GOGGLES);
register("pickaxe_of_containment", 90, "Pickaxe of Containment", 14, SlimefunItems.PICKAXE_OF_CONTAINMENT, SlimefunItems.BROKEN_SPAWNER);
register("hercules_pickaxe", 91, "Hercules Pickaxe", 28, SlimefunItems.HERCULES_PICKAXE);

View File

@ -35,8 +35,17 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class ArmorTask implements Runnable {
private final Set<PotionEffect> radiationEffects;
private final boolean radioactiveFire;
/**
* This creates a new {@link ArmorTask}.
*
* @param radioactiveFire
* Whether radiation also causes a {@link Player} to burn
*/
public ArmorTask(boolean radioactiveFire) {
this.radioactiveFire = radioactiveFire;
public ArmorTask() {
Set<PotionEffect> effects = new HashSet<>();
effects.add(new PotionEffect(PotionEffectType.WITHER, 400, 2));
effects.add(new PotionEffect(PotionEffectType.BLINDNESS, 400, 3));
@ -47,6 +56,16 @@ public class ArmorTask implements Runnable {
radiationEffects = Collections.unmodifiableSet(effects);
}
/**
* This returns a {@link Set} of {@link PotionEffect PotionEffects} which get applied to
* a {@link Player} when they are exposed to deadly radiation.
*
* @return The {@link Set} of {@link PotionEffect PotionEffects} applied upon radioactive contact
*/
public Set<PotionEffect> getRadiationEffects() {
return radiationEffects;
}
@Override
public void run() {
for (Player p : Bukkit.getOnlinePlayers()) {
@ -144,7 +163,11 @@ public class ArmorTask implements Runnable {
Slimefun.runSync(() -> {
p.addPotionEffects(radiationEffects);
p.setFireTicks(400);
// if radiative fire is enabled
if (radioactiveFire) {
p.setFireTicks(400);
}
});
return true;

View File

@ -99,7 +99,9 @@ public enum HeadTexture {
MINECRAFT_CHUNK("8449b9318e33158e64a46ab0de121c3d40000e3332c1574932b3c849d8fa0dc2"),
CHEST_TERMINAL("7a44ff3a5f49c69cab676bad8d98a063fa78cfa61916fdef3e267557fec18283"),
CARGO_ARROW_LEFT("f2599bd986659b8ce2c4988525c94e19ddd39fad08a38284a197f1b70675acc"),
CARGO_ARROW_RIGHT("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516");
CARGO_ARROW_RIGHT("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516"),
ADD_NEW_LANGUAGE("3edd20be93520949e6ce789dc4f43efaeb28c717ee6bfcbbe02780142f716"),
IRON_GOLEM("89091d79ea0f59ef7ef94d7bba6e5f17f2f7d4572c44f90f76c4819a714");
private final String texture;

View File

@ -274,78 +274,42 @@ public final class SlimefunUtils {
private static boolean equalsItemMeta(ItemMeta itemMeta, ImmutableItemMeta meta, boolean checkLore) {
Optional<String> displayName = meta.getDisplayName();
if (itemMeta.hasDisplayName() && displayName.isPresent()) {
if (itemMeta.getDisplayName().equals(displayName.get())) {
Optional<List<String>> itemLore = meta.getLore();
if (checkLore) {
if (itemMeta.hasLore() && itemLore.isPresent()) {
return equalsLore(itemMeta.getLore(), itemLore.get());
}
else {
return !itemMeta.hasLore() && !itemLore.isPresent();
}
}
else {
return true;
}
}
else {
return false;
}
if (itemMeta.hasDisplayName() != displayName.isPresent()) {
return false;
}
else if (!itemMeta.hasDisplayName() && !displayName.isPresent()) {
else if (itemMeta.hasDisplayName() && displayName.isPresent() && !itemMeta.getDisplayName().equals(displayName.get())) {
return false;
}
else if (!checkLore) {
return true;
}
else {
Optional<List<String>> itemLore = meta.getLore();
if (checkLore) {
if (itemMeta.hasLore() && itemLore.isPresent()) {
return equalsLore(itemMeta.getLore(), itemLore.get());
}
else {
return !itemMeta.hasLore() && !itemLore.isPresent();
}
if (itemMeta.hasLore() && itemLore.isPresent()) {
return equalsLore(itemMeta.getLore(), itemLore.get());
}
else {
return true;
return !itemMeta.hasLore() && !itemLore.isPresent();
}
}
else return false;
}
private static boolean equalsItemMeta(ItemMeta itemMeta, ItemMeta sfitemMeta, boolean checkLore) {
if (itemMeta.hasDisplayName() && sfitemMeta.hasDisplayName()) {
if (itemMeta.getDisplayName().equals(sfitemMeta.getDisplayName())) {
if (checkLore) {
if (itemMeta.hasLore() && sfitemMeta.hasLore()) {
return equalsLore(itemMeta.getLore(), sfitemMeta.getLore());
}
else {
return !itemMeta.hasLore() && !sfitemMeta.hasLore();
}
}
else {
return true;
}
}
else {
return false;
}
if (itemMeta.hasDisplayName() != sfitemMeta.hasDisplayName()) {
return false;
}
else if (!itemMeta.hasDisplayName() && !sfitemMeta.hasDisplayName()) {
if (checkLore) {
if (itemMeta.hasLore() && sfitemMeta.hasLore()) {
return equalsLore(itemMeta.getLore(), sfitemMeta.getLore());
}
else {
return !itemMeta.hasLore() && !sfitemMeta.hasLore();
}
}
else {
return true;
}
else if (itemMeta.hasDisplayName() && sfitemMeta.hasDisplayName() && !itemMeta.getDisplayName().equals(sfitemMeta.getDisplayName())) {
return false;
}
else if (!checkLore) {
return true;
}
else if (itemMeta.hasLore() && sfitemMeta.hasLore()) {
return equalsLore(itemMeta.getLore(), sfitemMeta.getLore());
}
else {
return false;
return !itemMeta.hasLore() && !sfitemMeta.hasLore();
}
}

View File

@ -155,10 +155,10 @@ public final class SlimefunItems {
public static final SlimefunItemStack GILDED_IRON_CHESTPLATE = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GILDED_IRON_CHESTPLATE;
public static final SlimefunItemStack GILDED_IRON_LEGGINGS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GILDED_IRON_LEGGINGS;
public static final SlimefunItemStack GILDED_IRON_BOOTS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GILDED_IRON_BOOTS;
public static final SlimefunItemStack GOLD_HELMET = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLD_HELMET;
public static final SlimefunItemStack GOLD_CHESTPLATE = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLD_CHESTPLATE;
public static final SlimefunItemStack GOLD_LEGGINGS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLD_LEGGINGS;
public static final SlimefunItemStack GOLD_BOOTS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLD_BOOTS;
public static final SlimefunItemStack GOLD_HELMET = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLDEN_HELMET_12K;
public static final SlimefunItemStack GOLD_CHESTPLATE = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLDEN_CHESTPLATE_12K;
public static final SlimefunItemStack GOLD_LEGGINGS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLDEN_LEGGINGS_12K;
public static final SlimefunItemStack GOLD_BOOTS = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLDEN_BOOTS_12K;
public static final SlimefunItemStack SLIME_HELMET_STEEL = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.SLIME_HELMET_STEEL;
public static final SlimefunItemStack SLIME_CHESTPLATE_STEEL = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.SLIME_CHESTPLATE_STEEL;
public static final SlimefunItemStack SLIME_LEGGINGS_STEEL = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.SLIME_LEGGINGS_STEEL;

View File

@ -87,10 +87,6 @@ public class BlockInfoConfig extends Config {
return data.keySet();
}
private UnsupportedOperationException invalidType(String path) {
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
}
@Override
public int getInt(String path) {
throw invalidType(path);
@ -121,6 +117,10 @@ public class BlockInfoConfig extends Config {
throw invalidType(path);
}
private UnsupportedOperationException invalidType(String path) {
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
}
@Override
public File getFile() {
throw new UnsupportedOperationException();

View File

@ -288,14 +288,8 @@ public class BlockStorage {
return changes;
}
public void save(boolean remove) {
save(true, remove);
}
public void save(boolean computeChanges, boolean remove) {
if (computeChanges) {
computeChanges();
}
public void save() {
computeChanges();
if (changes == 0) {
return;
@ -344,10 +338,11 @@ public class BlockStorage {
}
changes = 0;
}
if (remove) {
SlimefunPlugin.getRegistry().getWorlds().remove(world.getName());
}
public void saveAndRemove() {
save();
SlimefunPlugin.getRegistry().getWorlds().remove(world.getName());
}
public static void saveChunks() {

View File

@ -17,6 +17,7 @@ options:
language: en
enable-translations: true
log-duplicate-block-entries: true
burn-players-when-radioactive: true
guide:
default-view-book: false

View File

@ -41,6 +41,12 @@ guide:
select: Klicke hier um diese Sprache auszuwählen
select-default: Klicke hier um die Standardsprache auszuwählen
selected-language: 'Aktuell ausgewählt:'
change: Klicke um die Sprache zu ändern
description:
- "&7Hier kannst du deine Spracheinstellungen"
- "&7verwalten. Derzeit umfasst dies"
- "&7jedoch nur bestimmte Nachrichten,"
- "&7Items können noch nicht übersetzt werden."
title:
main: Slimefun-Handbuch
settings: Einstellungen & Infos
@ -50,6 +56,7 @@ guide:
addons: Addons für Slimefun4
bugs: Fehlermeldungen
source: Quellcode
versions: Installierte Versionen
credits:
commit: Beitrag
commits: Beiträge
@ -59,6 +66,12 @@ guide:
resourcepack: "&cRessourcenpaket-Designer"
translator: "&9Übersetzer"
profile-link: Klick um mich auf GitHub zu sehen
open: Klicke um Mitwirkende zu sehen
description:
- "&7Slimefun ist ein Open-Source Projekt"
- "&7und wird von einer riesigen Community entwickelt."
- "&7Über &e%contributors% &7Personen haben bereits"
- "&7an Slimefun mitgewirkt."
pages:
previous: Vorherige Seite
next: Nächste Seite
@ -80,6 +93,7 @@ guide:
- Um diese Kategorie freizuschalten,
- müssen zuerst sämtliche Items der
- folgenden Kategorien freigeschaltet werden
work-in-progress: Dieses Feature befindet sich noch in der Testphase!
messages:
not-researched: "&4Du hast diesen Gegenstand noch nicht freigeschaltet!"
not-enough-xp: "&4Du hast nicht genügend Erfahrungspunkte, um dies freizuschalten"
@ -96,7 +110,6 @@ messages:
not-valid-research: "&4%research% &cist kein gültiger Erfahrungsgrad!"
give-research: '&bDu hast %player% den Erfahrungsgrad &7"%research%&7" vergeben'
hungry: "&cDu bist zu hungrig, um dies zu tun!"
mode-change: "&bDer Modus von deinem %device% wurde geändert zu: &9%mode%"
disabled-in-world: "&4&lDieses Item wurde in dieser Welt deaktiviert!"
disabled-item: "&4&lDieses Item wurde von einem Server-Administrator deaktiviert!"
no-tome-yourself: "&cDu kannst dieses Item nicht an dir selbst anwenden..."
@ -164,6 +177,10 @@ messages:
wrong-world: "&cDein Ankerpunkt scheint sich in einer anderen Dimension zu befinden!"
distance: "&7Messung erfolgreich. &eDistanz: %distance%"
anchor-set: "&aErfolgreich den Ankerpunkt gesetzt:&e %anchor%"
multi-tool:
mode-change: "&bDer Modus von deinem Multi-Tool wurde geändert zu: &9%mode%"
not-shears: "&cEinMulti Tool kann nicht als Schere verwendet werden!"
mode-change: "&bDer Modus von deinem %device% wurde geändert zu: &9%mode%"
machines:
pattern-not-found: "&eEs tut mir leid, aber ich konnte kein passendes Rezept finden."
unknown-material: "&eEs tut mir leid, aber ich erkenne das Item in meinem Werfer
@ -234,6 +251,7 @@ gps:
werden unterstützt!)"
added: "&aEin neuer Wegpunkt wurde hinzugefügt"
max: "&4Du hast die maximale Anzahl an Wegpunkten erreicht"
duplicate: "&4Es existiert bereits ein Wegpunkt mit folgendem Namen: &f%waypoint%"
insufficient-complexity:
- "&4Unzureichende Komplexität deines GPS-Netzwerkes! Folgende Komplexität wird
benötigt: &c%complexity%"
@ -306,6 +324,8 @@ languages:
zh-CN: Chinesisch (China)
el: Griechisch
he: Hebräisch
pt: Portugiesisch (Portugal)
pt-BR: Portugiesisch (Brasilien)
ar: Arabisch
af: Afrikaans
da: Dänisch
@ -317,8 +337,6 @@ languages:
fa: Persisch
th: Thailändisch
ro: Rumänisch
pt: Portugiesisch (Portugal)
pt-BR: Portugiesisch (Brasilien)
bg: Bulgarisch
ko: Koreanisch
tr: Türkisch
@ -327,5 +345,9 @@ languages:
sr: Serbisch
be: Belarusisch
tl: Tagalog
brewing_stand:
not-working: "&4Items von Slimefun können nicht zum Brauen verwendet werden!"
villagers:
no-trading: "&4Items von Slimefun können nicht zum Handeln verwendet werden!"
miner:
no-ores: "&eIch konnte leider keine Erze in der Nähe finden!"

View File

@ -24,6 +24,7 @@ commands:
guide:
locked: 'LOCKED'
work-in-progress: 'This feature is not fully finished yet!'
locked-category:
- 'To unlock this category you will'
@ -64,6 +65,13 @@ guide:
selected-language: 'Currently selected:'
select: 'Click to select this language'
select-default: 'Click to select the default language'
change: 'Click to select a new language'
description:
- '&7You now have the option to change'
- '&7the language in which Slimefun'
- '&7will be presented to you. Items'
- '&7cannot be translated for now.'
translations:
name: '&aIs something missing?'
@ -78,11 +86,19 @@ guide:
addons: 'Addons for Slimefun4'
bugs: 'Bug Reports'
source: 'Source Code'
versions: 'Installed versions'
credits:
commit: 'Commit'
commits: 'Commits'
profile-link: 'Click to visit their profile on GitHub'
open: 'Click to see our contributors'
description:
- '&7Slimefun is an open-source project'
- '&7and maintained by a large community of people.'
- '&7Over &e%contributors% &7people have worked on'
- '&7Slimefun throughout all these years.'
roles:
developer: '&6Developer'
wiki: '&3Wiki Editor'
@ -105,13 +121,16 @@ messages:
not-valid-research: '&4%research% &cis not a valid Research!'
give-research: '&bYou have given %player% the Research &7"%research%&7"'
hungry: '&cYou are too hungry to do that!'
mode-change: '&b%device% mode changed to: &9%mode%'
disabled-in-world: '&4&lThis Item has been disabled in this world'
disabled-item: '&4&lThis Item has been disabled! How did you even get that?'
no-tome-yourself: '&cYou cannot use the &4Tome of Knowledge &con yourself...'
multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%'
piglin-barter: '&4You cannot barter with piglins using Slimefun items'
multi-tool:
mode-change: '&b%device% mode changed to: &9%mode%'
not-shears: '&cA Multi Tool cannot be used as shears!'
talisman:
anvil: '&a&oYour Talisman saved your tool from breaking'
miner: '&a&oYour Talisman just doubled your drops'
@ -232,6 +251,12 @@ machines:
anvil:
not-working: '&4You cannot use Slimefun Items in an anvil!'
brewing_stand:
not-working: '&4You cannot use Slimefun Items in a brewing stand!'
villagers:
no-trading: '&4You cannot trade Slimefun Items with Villagers!'
backpack:
already-open: '&cSorry, this Backpack is open somewhere else!'
no-stack: '&cYou cannot stack Backpacks'
@ -245,6 +270,7 @@ gps:
new: '&ePlease type in a name for your new waypoint in the chat. &7(Color Codes supported!)'
added: '&aSuccessfully added a new waypoint'
max: '&4You have reached the maximum amount of waypoints'
duplicate: '&4You have already created a waypoint named: &f%waypoint%'
insufficient-complexity:
- '&4Insufficient GPS Network Complexity: &c%complexity%'

View File

@ -24,21 +24,27 @@ guide:
search:
message: "&b¿Qué te gustaría buscar?"
name: "&7Busca..."
tooltip: "&bClick para buscar un item"
tooltip: "&bCliquea para buscar un objeto"
inventory: 'Buscando: %item%'
lore:
- "&b¿Qué te gustaría buscar?"
- "&7Escribe en el chat el término que quieres buscar."
cheat:
no-multiblocks: "&4¡No puedes obtener los Multiblocks, tienes que construirlos!"
no-multiblocks: "&4¡No puedes regalarte los Multiblocks, tienes que construirlos!"
languages:
updated: "&aTu lenguaje fue cambiado a: &b%lang%"
translations:
name: "&a¿Falta algo?"
lore: Clic para agregar tu propia traducción.
select: Clic para seleccionar este idioma.
select-default: Clic para seleccionar el idioma predeterminado.
lore: Cliquea para agregar tu propia traducción.
select: Cliquea para seleccionar este idioma.
select-default: Cliquea para seleccionar el idioma predeterminado.
selected-language: 'Actualmente seleccionado:'
change: Click para seleccionar un nuevo lenguaje
description:
- "&7Ahora tienes la opción de cambiar"
- "&7el idioma en el que Slimefun"
- "&7se le presentará. Los objetos"
- "&7no pueden ser traducidos por ahora."
title:
main: Guía de Slimefun.
settings: Configuración e Información.
@ -48,6 +54,7 @@ guide:
addons: Complementos para Slimefun4
bugs: Reportes de Bugs
source: Código base
versions: Versiones instaladas
credits:
commit: Contribución
commits: Contribuciones
@ -56,12 +63,18 @@ guide:
wiki: "&3Editor de Wiki"
resourcepack: "&cArtista de Resourcepack"
translator: "&9Traductor"
profile-link: Clic para visitar su perfil en GitHub.
profile-link: Cliquea para visitar su perfil en GitHub.
open: Cliquea para ver nuestros contribuyentes
description:
- "&7Slimefun es un proyecto open-source"
- "&7mantenido por una gran comunidad."
- "&7Mas de &e%contributors% &7personas han trabajado en"
- "&7Slimefun en todos estos años."
pages:
previous: Página anterior
next: Página siguiente
tooltips:
open-category: Clic para abrir
open-category: Cliquea para abrir
versions-notice: "¡Esto es muy importante cuando se reportan bugs!"
wiki: Ve este objeto en la wiki oficial de Slimefun
recipes:
@ -78,6 +91,7 @@ guide:
- Para desbloquear esta categoría deberás
- desbloquear todos los objetos de las
- siguientes categorías
work-in-progress: "¡¡¡Esta característica no está completamente terminada todavía!!"
messages:
not-researched: "&4No tienes conocimiento suficiente para entender esto."
not-enough-xp: "&4No tienes suficiente XP para desbloquear esto."
@ -95,7 +109,6 @@ messages:
not-valid-research: "&c¡&4%research% &cno es un conocimiento válido!"
give-research: '&bLe has dado a %player% la investigación &7"%research%&7"'
hungry: "&c¡Tienes demasiada hambre para hacer eso!"
mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%'
disabled-in-world: "&4&lEste item ha sido desactivado en el mundo."
disabled-item: "&4&l¡Este item ha sido desactivado! ¿Cómo es que lo tienes?"
no-tome-yourself: "&cNo puedes usar el &4Tome of Knowledge &cen ti mismo..."
@ -150,6 +163,20 @@ messages:
- "&7¡Siempre mira el lado bueno de la vida!"
- "&7Esta era un bizcocho y no una galleta"
- "&7¡Los signos de neón son lo MEJOR!"
piglin-barter: "&4No puedes trocar con piglins usando objetos de Slimefun"
enchantment-rune:
fail: "&cNo puedes encantar este objeto."
no-enchantment: "&cNo se pudo encontrar un encantamiento aplicable a este objeto."
success: "&aHas aplicado con éxito un encantamiento aleatorio a este objeto."
tape-measure:
no-anchor: "&c¡Necesitas establecer un ancla antes de comenzar a medir!"
wrong-world: "&c¡Parece ser que tu ancla se encuentra en un mundo diferente!"
distance: "&7Medida tomada. &eDistancia: %distance%"
anchor-set: "&aAncla establecida con éxito:&e %anchor%"
multi-tool:
mode-change: "&b%device% modo cambiado a: &9%mode%"
not-shears: "&c¡Una Multi Tool no puede ser usada como tijeras!"
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."
@ -186,7 +213,7 @@ machines:
invulnerability: "&b&l¡Tienes 30 segundos de invulnerabilidad!"
gui:
title: Tus waypoints
tooltip: Click para teletransportarte
tooltip: Cliquea para teletransportarte
time: Tiempo estimado
CARGO_NODES:
must-be-placed: "&4¡Tiene que ponerse sobre un cofre o máquina!"
@ -218,6 +245,7 @@ gps:
códigos de color!)"
added: "&aNuevo waypoint agregado exitosamente."
max: "&4Has alcanzado el máximo número de waypoints permitidos."
duplicate: "&4Ya has creado un waypoint llamado: &f%waypoint%"
insufficient-complexity:
- "&4Complejidad de red GPS insuficiente: &c%complexity%"
- "&4a) No tienes una red GPS armada aún."
@ -291,8 +319,6 @@ languages:
zh-CN: Chino (China)
el: Griego
he: Hebreo
pt: Portugués (Portugal)
pt-BR: Portugués (Brasil)
ar: Árabe
af: Africano
da: Danés
@ -304,6 +330,8 @@ languages:
fa: Persa
th: Tailandés
ro: Rumano
pt: Portugués (Portugal)
pt-BR: Portugués (Brasil)
bg: Búlgaro
ko: Coreano
tr: Turco
@ -312,5 +340,9 @@ languages:
sr: Serbio
be: Bielorruso
tl: Tagalog
brewing_stand:
not-working: "&4¡No puedes usar objetos de Slimefun en un soporte para pociones!"
villagers:
no-trading: "&4¡No puedes comerciar objetos de Slimefun con los aldeanos!"
miner:
no-ores: "&ePerdón, ¡No encuentro ningún mineral cerca!"

View File

@ -121,7 +121,7 @@ messages:
meghalsz."
research:
start: "&7Az Ősi Lelkek titokzatos szavakat súgnak a füledbe!"
progress: "&7Elkezdel kíváncsiskodni a kutatásról, neve: &b%research% &e(%progress%)"
progress: "&7Elkezdtél kíváncsiskodni a következő kutatásról: &b%research% &e(%progress%)"
fire-extinguish: "&7Eloltottad magad!"
cannot-place: "&cNem teheted ezt a blokkot oda!"
no-pvp: "&cA pvp itt nem engedélyezett!"
@ -300,8 +300,6 @@ languages:
zh-CN: Kínai (Kína)
el: Görög
he: Héber
pt: Portugál (Portugália)
pt-BR: Portugál (Brazília)
ar: Arab
af: Afrikánsz
da: Dán
@ -313,6 +311,8 @@ languages:
fa: Perzsa
th: Thai
ro: Román
pt: Portugál (Portugália)
pt-BR: Portugál (Brazília)
bg: Bolgár
ko: Koreai
tr: Török
@ -321,5 +321,7 @@ languages:
sr: Szerb
be: Belorusz
tl: Tagalog
brewing_stand:
not-working: "&4Nem használhatsz Slimefun tárgyakat a Főzőállványban!"
miner:
no-ores: "&eSajnálom, nem találtam semmilyen Ércet a közelben!"

View File

@ -284,6 +284,8 @@ languages:
zh-CN: 中国語(中国)
el: ギリシャ語
he: ヘブライ語
pt: ポルトガル語(ポルトガル)
pt-BR: ポルトガル語(ブラジル)
ar: アラビア語
af: アフリカーンス語
da: デンマーク語
@ -295,8 +297,6 @@ languages:
fa: ペルシア語
th: タイ語
ro: ルーマニア語
pt: ポルトガル語(ポルトガル)
pt-BR: ポルトガル語(ブラジル)
bg: ブルガリア語
ko: 韓国語
tr: トルコ語
@ -305,5 +305,7 @@ languages:
sr: セルビア語
be: ベラルーシ語
tl: タガログ語
brewing_stand:
not-working: "&4Slimefunのアイテムは醸造台で使えません"
miner:
no-ores: "&e周辺には鉱石が見つかりませんでした"

View File

@ -40,6 +40,12 @@ guide:
select: Нажмите для выбора этого языка
select-default: Нажмите для выбора языка по умолчанию
selected-language: 'Сейчас выбрано:'
change: Нажмите для выбора нового языка
description:
- "&7У Вас теперь есть возможность"
- "&7выбрать язык, на котором Slimefun"
- "&7будет отправлять сообщения."
- "&7Предметы пока не могут быть переведены."
title:
main: Руководство Slimefun
settings: Информация и настройки
@ -49,6 +55,7 @@ guide:
addons: Дополнения к Slimefun4
bugs: Отчёты об ошибках
source: Исходный код
versions: Установленные версии
credits:
commit: Коммит
commits: Коммитов
@ -58,6 +65,12 @@ guide:
resourcepack: "&cТекстурщик"
translator: "&9Локализатор"
profile-link: Нажмите, чтобы посетить GitHub профиль
open: Нажмите для просмотра списка авторов
description:
- "&7Slimefun — проект с открытым исходным кодом,"
- "&7и поддерживается большим сообществом хороших людей."
- "&7Свыше &e%contributors% &7людей работали над"
- "&7Slimefun за все эти долгие годы."
pages:
previous: Предыдущая страница
next: Следующая страница
@ -79,6 +92,7 @@ guide:
- Для начала Вы должны
- разблокировать все предметы
- из следующих категорий
work-in-progress: Эта функция ещё не полностью завершена!
messages:
not-researched: "&4Вам не хватает знаний, чтобы понять это"
not-enough-xp: "&4У Вас недостаточно опыта, чтобы исследовать это"
@ -96,7 +110,6 @@ messages:
not-valid-research: "&4%research% &cне является допустимым исследованием!"
give-research: '&bВы выдали игроку %player% исследование &7"%research%&7"'
hungry: "&cВы слишком голодны для этого!"
mode-change: "&b%device% | Режим изменён на: &9%mode%"
disabled-in-world: "&4&lДанный предмет отключен в этом мире"
disabled-item: "&4&lЭтот предмет был отключен! Где Вы вообще его взяли?"
no-tome-yourself: "&cВы не можете использовать &4том обмена знаниями &cна себе…"
@ -161,6 +174,10 @@ messages:
wrong-world: "&cВаш якорь находится в другом мире!"
distance: "&7Измерение завершено. &eРасстояние: %distance%"
anchor-set: "&aЯкорь успешно установлен:&e %anchor%"
multi-tool:
mode-change: "&bРежим «%device%» изменён на: &9%mode%"
not-shears: "&cМультиинструмент не может быть использован в качестве ножниц!"
mode-change: "&b%device% | Режим изменён на: &9%mode%"
machines:
pattern-not-found: "&eК сожалению, не удалось распознать этот рецепт. Пожалуйста,
разложите предметы в верной последовательности в раздатчик."
@ -230,6 +247,7 @@ gps:
цветовые коды!)"
added: "&aКонтрольная точка успешно добавлена"
max: "&4Вы достигли максимального количества контрольных точек"
duplicate: "&4Вы уже создали контрольную точку с таким названием: &f%waypoint%"
insufficient-complexity:
- "&4Недостаточная общая сила сигнала GPS сети: &c%complexity%"
- "&4а) Ваша GPS сеть пока что не подключена"
@ -302,7 +320,7 @@ languages:
zh-CN: Китайский (Китай)
el: Греческий
he: Иврит
pt: Португальский (Португалия)
pt-BR: Португальский (Бразилия)
ar: Арабский
af: Бурский
da: Датский
@ -314,7 +332,7 @@ languages:
fa: Персидский
th: Тайский
ro: Румынский
pt-BR: Португальский (Бразилия)
pt: Португальский (Португалия)
bg: Болгарский
ko: Корейский
tr: Турецкий
@ -323,5 +341,9 @@ languages:
sr: Сербский
be: Белорусский
tl: Тагальский
brewing_stand:
not-working: "&4Вы не можете использовать Slimefun предметы в варочной стойке!"
villagers:
no-trading: "&4Вы не можете торговаться с крестьянами Slimefun предметами!"
miner:
no-ores: "&eК сожалению, не удалось найти какую-либо руду поблизости!"

View File

@ -38,6 +38,12 @@ guide:
select: I-click ito upang piliin ang wikang ito.
select-default: I-click ito upang piliin ang default na wika.
selected-language: 'Kasalukuyang pinili:'
change: Mag-click upang pumili ng bagong wika.
description:
- "&7Meron ka nang pagpipilian upang pumili"
- "&7ng wika kung saan ang Slimefun"
- "&7ay may ipapakita sa iyo. Ang mga"
- "&7items ay bawal pa i-translate sa ngayon."
title:
main: Slimefun Guide
settings: Mga Settings & Impormasyon
@ -77,6 +83,7 @@ guide:
- Upang i-unlock ang kategoryang ito,
- kailangang i-unlock ang lahat ng mga item mula sa
- sumusunod na kategorya.
work-in-progress: Ang feature na ito ay hindi pa tapos!
messages:
not-researched: "&4Kulang ang iyong Knowledge upang ito'y maintindihan."
not-enough-xp: "&4Kulang ang iyong XP upang ito'y ma-unlock."
@ -94,7 +101,6 @@ messages:
not-valid-research: "&4%research% &cay hindi valid na Research!"
give-research: '&bBinigyan mo si %player% ng Research &7"%research%&7"'
hungry: "&cIkaw ay sobrang gutom para gawin ito!"
mode-change: "&b%device% mode ay pinalitan ng: &9%mode%"
disabled-in-world: "&4&lDinisable ang Aytem sa world na ito."
disabled-item: "&4&lDinisable ang Aytem na ito! Paano mo ito nakuha?"
no-tome-yourself: "&cHindi mo magagamit ang &4Tome of Knowledge &cpara sa'yo..."
@ -166,6 +172,10 @@ messages:
wrong-world: "&cAng iyong angkla ay tila nasa ibang mundo!"
distance: "&7Measurement taken. &eDistansiya: %distance%"
anchor-set: "&aMatagumpay na na-set ang angla:&e %anchor%"
multi-tool:
mode-change: "&b%device% napalitan ang mode sa: &9%mode%"
not-shears: "&cBawal gamitin ang Multi-Tool bilang shears!"
mode-change: "&b%device% mode ay pinalitan ng: &9%mode%"
machines:
pattern-not-found: "&ePasensiya na, hindi ko maintindihan ang Recipe na ito. Pakilagay
ang mga Aytem sa tamang pattern sa loob ng Dispense."
@ -241,6 +251,7 @@ gps:
chat. &7(Supported ang Color Codes!)"
added: "&aTagumpay ang pag-add ng bagong waypoint."
max: "&4Naabot mo na ang maximum amount ng waypoints."
duplicate: "&4Nakagawa ka na ng isang waypoint na pinangalanan: & f%waypoint%"
insufficient-complexity:
- "&4Kulang ang GPS Network Complexity: &c%complexity%"
- "&4a) Wala ka pang GPS Network setup."
@ -334,3 +345,7 @@ languages:
sr: Serbian
be: Belarusian
tl: Tagalog/Filipino
brewing_stand:
not-working: "&4Hindi ka maaaring gumamit ng mga Item ng Slimefun sa Brewing Stand!"
villagers:
no-trading: "&4Hindi ka maaaring mag-trade ng mga Slimefun Items sa mga villagers!"

View File

@ -41,6 +41,12 @@ guide:
select: Bu dili seçmek için tıklayın
select-default: Varsayılan dili seçmek için tıklayın
selected-language: 'Şuan seçili:'
change: Yeni bir dil seçmek için tıklayın
description:
- "&7Artık Slimefun içerisinde size"
- "&7sunulacak olan dilinizi"
- "&7değiştirebilirsiniz. Henüz eşyalar"
- "&7çevrilememektedir."
title:
main: Slimefun Rehberi
settings: Ayarlar & Bilgi
@ -50,6 +56,7 @@ guide:
addons: Slimefun4 için Eklentiler
bugs: Hata Raporları
source: Kaynak Kodu
versions: Yüklü sürümler
credits:
commit: Geliştiirme
commits: Geliştirmeler
@ -59,6 +66,12 @@ guide:
resourcepack: "&cKaynak Paketi Tasarımcısı"
translator: "&9Çevirmen"
profile-link: GitHubdaki profillerini ziyaret etmek için tıklayın
open: Bize katkıda bulunanları görmek için tıklayın
description:
- "&7Slimefun açık kaynak kodlu bir projedir"
- "&7ve büyük bir topluluk tarafından geliştirilir."
- "&e%contributors%&7den(dan) fazla kişi yıllar"
- "&7boyunca Slimefun'a katkıda bulundu."
pages:
previous: Önceki sayfa
next: Sonraki sayfa
@ -80,6 +93,7 @@ guide:
- Bu kategoriyi açmak için
- aşağıdaki kategorilerde bulunan
- bütün eşyalarıın
work-in-progress: Bu özellik henüz tamamlanmadı!
messages:
not-researched: "&4Bunu anlayacak kadar bilgin yok"
not-enough-xp: "&4Bunun kilidini açmak için yeterli XP niz yok"
@ -96,7 +110,6 @@ messages:
not-valid-research: "&4%research% &cgeçerli bir araştırma değil!"
give-research: '&b%player% adlı oyuncu için bir araştırmayı açtın: &7"%research%&7"'
hungry: "&cBunu yapmak için çok açsın!"
mode-change: "&b%device% modu değişti: &9%mode%"
disabled-in-world: "&4&lBu eşya bu dünyada devre dışı bırakıldı."
disabled-item: "&4&lBu eşya devre dışı bırakıldı! Bunu nasıl aldın?"
no-tome-yourself: "&4Tome of Knowledge &cı kendin için kullanamazsın..."
@ -159,6 +172,10 @@ messages:
wrong-world: "&cSeçtiğiniz nokta başka bir dünyada gözüküyor!"
distance: "&7Ölçüm yapıldı. &eUzaklık: %distance%"
anchor-set: "&aBaşarılı bir şekilde bir nokta seçildi:&e %anchor%"
multi-tool:
mode-change: "&b%device% modül değiştirildi: &9%mode%"
not-shears: "&cBir Multi Tool makas olarak kullanılamaz!"
mode-change: "&b%device% modu değişti: &9%mode%"
machines:
pattern-not-found: "&eÜzgünüm, bu tarifi tanıyamadım. Lütfen Eşyaları Dağıtıcıya
doğru şekilde yerleştirin."
@ -225,6 +242,7 @@ gps:
new: "&eLütfen sohbette yeni yer noktanız için bir ad yazın. &7(Renk Kodları destekleniyor!)"
added: "&aYeni bir yer noktası başarıyla eklendi"
max: "&4Maksimum yer noktası sayısına ulaştınız"
duplicate: "&4Bu adla zaten bir yer noktası yarattınız: &f%waypoint%"
insufficient-complexity:
- "&4Yetersiz GPS Ağ Gücü: &c%complexity%"
- "&4a) Henüz bir GPS Ağı kurulumunuz yok"
@ -318,5 +336,9 @@ languages:
sr: Sırpça
be: Belarusça
tl: Tagalog
brewing_stand:
not-working: "&4Slimefun eşyalarını simya standında kullanamazsın!"
villagers:
no-trading: "&4Köylülerle Slimefun eşyalarını kullanarak ticaret yapamazsın!"
miner:
no-ores: "&eÜzgünüm, yakınlarda herhangi bir cevher bulamadım!"

View File

@ -213,6 +213,7 @@ gps:
new: "&e给你的路径点起个名字吧 &7(支持彩色代码!)"
added: "&a成功添加了新的传送点"
max: "&4你已到达设置传送点个数的最大上限"
duplicate: "&4你已经创建了一个相同名字的传送点了: &f%waypoint%"
insufficient-complexity:
- "&4GPS网络复杂度不足: &c%complexity%"
- "&4a) 你还没有设置一个 GPS 网络"
@ -284,6 +285,7 @@ languages:
zh-CN: 简体中文 (中国)
el: 希腊语
he: 希伯来语
pt: 葡萄牙语 (葡萄牙)
ar: 阿拉伯语
af: 南非语
da: 丹麦语
@ -295,7 +297,6 @@ languages:
fa: 波斯语
th: 泰语
ro: 罗马尼亚语
pt: 葡萄牙语 (葡萄牙)
pt-BR: 葡萄牙语 (巴西)
bg: 保加利亚语
ko: 韩语
@ -305,5 +306,9 @@ languages:
sr: 塞尔维亚语
be: 白俄罗斯语
tl: 他加禄语
brewing_stand:
not-working: "&4你不能在酿造台中使用 Slimefun 物品!"
villagers:
no-trading: "&4你不能用 Slimefun 的物品和村民交易!"
miner:
no-ores: "&e抱歉, 周围找不到矿石了!"

View File

@ -118,6 +118,11 @@ slimefun:
lore:
- Haz este objeto tal como se muestra
- usando una Refinery
barter_drop:
name: Piglin Bartering Drop
lore:
- Troca con Piglins usando
- Lingotes de Oro para obtener este objeto
minecraft:
shaped:
name: Receta de Crafteo con forma

View File

@ -32,7 +32,7 @@ slimefun:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Crusher segítségével
mob_drop:
name: Mob Drop
name: Élőlény Dobja
lore:
- Öld meg ezt az Élőlényt,
- hogy megszerezd ezt a tárgyat
@ -118,6 +118,11 @@ slimefun:
lore:
- Készítsd el ezt a Tárgyat az ábra alapján
- egy Refinery segítségével
barter_drop:
name: Piglinek Dobják Cserélésnél
lore:
- Cseréld el a Piglenekkel Aranyrudakat,
- hogy megszerezd ezt a tárgyat
minecraft:
shaped:
name: Barkácsrecept Forma

View File

@ -118,6 +118,11 @@ slimefun:
lore:
- Создаётся так, как показано,
- используя Refinery
barter_drop:
name: Предмет товарообмена с пиглином
lore:
- 'Обменяйтесь с пиглином, используя золотые '
- слитки, чтобы заполучить этот предмет
minecraft:
shaped:
name: Обычный рецепт

View File

@ -118,6 +118,11 @@ slimefun:
lore:
- 如合成表所示
- 用炼油机合成
barter_drop:
name: 猪灵交易掉落
lore:
- 使用金锭与猪灵交易
- 可以获得此物品
minecraft:
shaped:
name: 有序合成

View File

@ -236,3 +236,7 @@ slimefun:
advanced_industrial_miner: Minería Mejorada
magical_zombie_pills: De-Zombificación
auto_brewer: Alquimia Industrial
enchantment_rune: Encantamiento Antiguo
lead_clothing: Ropa de Plomo
tape_measure: Cinta Métrica
iron_golem_assembler: Iron Golems Automáticos

View File

@ -8,6 +8,7 @@ import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -22,7 +23,7 @@ import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestBackpackCommand {
class TestBackpackCommand {
private static ServerMock server;
@ -52,7 +53,8 @@ public class TestBackpackCommand {
}
@Test
public void testValidBackpack() throws InterruptedException {
@DisplayName("Test /sf backpack giving a restored backpack")
void testValidBackpack() throws InterruptedException {
Player player = server.addPlayer();
player.setOp(true);
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -64,8 +66,9 @@ public class TestBackpackCommand {
}
@ParameterizedTest
@ValueSource(strings = { "ABC", "-100", "123456789" })
public void testNonExistantBackpacks(String id) throws InterruptedException {
@DisplayName("Test /sf backpack with invalid id parameters")
@ValueSource(strings = { "", " ", "ABC", "-100", "123456789" })
void testNonExistentBackpacks(String id) throws InterruptedException {
Player player = server.addPlayer();
player.setOp(true);
TestUtilities.awaitProfile(player);

View File

@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -13,7 +14,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestDebugFishCommand {
class TestDebugFishCommand {
private static ServerMock server;
@ -30,7 +31,8 @@ public class TestDebugFishCommand {
@ParameterizedTest
@ValueSource(booleans = { true, false })
public void testCommand(boolean op) {
@DisplayName("Test if Debug Fish is given on /sf debug_fish")
void testCommand(boolean op) {
Player player = server.addPlayer();
player.setOp(op);
server.execute("slimefun", player, "debug_fish").assertSucceeded();

View File

@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -15,7 +16,7 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestGuideCommand {
class TestGuideCommand {
private static ServerMock server;
@ -31,8 +32,9 @@ public class TestGuideCommand {
}
@ParameterizedTest
@DisplayName("Test if Slimefun Guide is given on /sf guide")
@ValueSource(booleans = { true, false })
public void testCommand(boolean op) {
void testCommand(boolean op) {
Player player = server.addPlayer();
player.setOp(op);
server.execute("slimefun", player, "guide").assertSucceeded();

View File

@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.guide;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -10,7 +11,7 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
public class TestBookSlimefunGuide {
class TestBookSlimefunGuide {
@BeforeAll
public static void load() {
@ -24,7 +25,8 @@ public class TestBookSlimefunGuide {
}
@Test
public void testBasicGetters() {
@DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
BookSlimefunGuide guide = new BookSlimefunGuide();
Assertions.assertEquals(SlimefunGuideLayout.BOOK, guide.getLayout());

View File

@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.guide;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -10,7 +11,7 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
public class TestChestSlimefunGuide {
class TestChestSlimefunGuide {
@BeforeAll
public static void load() {
@ -24,7 +25,8 @@ public class TestChestSlimefunGuide {
}
@Test
public void testBasicGetters() {
@DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
ChestSlimefunGuide guide = new ChestSlimefunGuide(false);
Assertions.assertEquals(SlimefunGuideLayout.CHEST, guide.getLayout());

View File

@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -17,7 +18,7 @@ import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> {
class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> {
private static ServerMock server;
private static SlimefunPlugin plugin;
@ -42,7 +43,8 @@ public class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> {
}
@Test
public void testRightClickBehaviour() {
@DisplayName("Test Ender Backpack opening Enderchest")
void testRightClickBehaviour() {
Player player = server.addPlayer();
EnderBackpack backpack = registerSlimefunItem(plugin, "TEST_ENDER_BACKPACK");

View File

@ -7,7 +7,6 @@ import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -45,7 +44,6 @@ public class TestDietCookie implements SlimefunItemTest<DietCookie> {
}
@Test
@Disabled("Potion Effects are currently not fully implemented in MockBukkit")
public void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer();
DietCookie cookie = registerSlimefunItem(plugin, "TEST_DIET_COOKIE");

View File

@ -6,7 +6,6 @@ import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -44,7 +43,6 @@ public class TestMonsterJerky implements SlimefunItemTest<MonsterJerky> {
}
@Test
@Disabled("Potion Effects are currently not fully implemented in MockBukkit")
public void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer();
player.addPotionEffect(PotionEffectType.HUNGER.createEffect(20, 2));

View File

@ -0,0 +1,35 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
class MockBeeProtectionSuit extends SlimefunArmorPiece implements ProtectiveArmor {
public MockBeeProtectionSuit(Category category, SlimefunItemStack item) {
super(category, item, RecipeType.NULL, new ItemStack[9], new PotionEffect[0]);
}
@Override
public ProtectionType[] getProtectionTypes() {
return new ProtectionType[] { ProtectionType.BEES };
}
@Override
public boolean isFullSetRequired() {
return false;
}
@Override
public NamespacedKey getArmorSetId() {
return new NamespacedKey(getAddon().getJavaPlugin(), "mock_bees");
}
}

View File

@ -0,0 +1,75 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
import org.bukkit.Material;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mockito;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.BeeListener;
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
class TestBeeListener {
private static ServerMock server;
private static SlimefunPlugin plugin;
private static BeeListener listener;
@BeforeAll
public static void load() {
server = MockBukkit.mock();
plugin = MockBukkit.load(SlimefunPlugin.class);
listener = new BeeListener(plugin);
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@ParameterizedTest
@DisplayName("Test Bee damage protection")
@ValueSource(booleans = { true, false })
void testBeeDamage(boolean hasArmor) throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
if (hasArmor) {
Category category = TestUtilities.getCategory(plugin, "bee_suit_test");
SlimefunItemStack chestplate = new SlimefunItemStack("MOCK_BEE_SUIT", Material.LEATHER_CHESTPLATE, "&cBee Suit Prototype");
MockBeeProtectionSuit armor = new MockBeeProtectionSuit(category, chestplate);
armor.register(plugin);
player.getInventory().setChestplate(chestplate.clone());
// Force update the cached armor
profile.getArmor()[1].update(chestplate, armor);
}
double damage = 7.5;
Bee bee = Mockito.mock(Bee.class);
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(bee, player, DamageCause.ENTITY_ATTACK, damage);
listener.onDamage(event);
if (hasArmor) {
Assertions.assertEquals(0, event.getDamage());
}
else {
Assertions.assertEquals(damage, event.getDamage());
}
}
}

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