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: 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. 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. 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. 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. 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. 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. 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. 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. 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. 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") 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: jobs:
comment: comment:
name: Invalid Issues
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'Bug Report') == false if: contains(github.event.issue.labels.*.name, 'Bug Report') == false
steps: steps:
- name: Close Issue - name: Close Issue

View File

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

View File

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

View File

@ -17,6 +17,7 @@ on:
jobs: jobs:
build: build:
name: Maven build
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: 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' - '**.yml'
jobs: jobs:
build: linter:
name: YAML Linter
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View File

@ -29,6 +29,10 @@
* (API) Added support for adding custom Piglin Barter drops * (API) Added support for adding custom Piglin Barter drops
* (API) Added BlockPlacerPlaceEvent * (API) Added BlockPlacerPlaceEvent
* (API) Added ToolUseHandler * (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 #### Changes
* Performance improvement for Programmable Android rotations * Performance improvement for Programmable Android rotations
@ -37,6 +41,9 @@
* Performance improvements for idling Enhanced Furnaces when using Paper * Performance improvements for idling Enhanced Furnaces when using Paper
* Performance improvements for Rainbow Blocks * Performance improvements for Rainbow Blocks
* Crafting a Rag now yields two items * 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 #### Fixes
* Fixed Programmable Androids rotating in the wrong direction * Fixed Programmable Androids rotating in the wrong direction
@ -52,6 +59,17 @@
* Fixed #2181 * Fixed #2181
* Fixed #2180 * Fixed #2180
* Fixed #2122 * 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) ## 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 * date of the last commit to this repository
</details> </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. 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"> 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> <modelVersion>4.0.0</modelVersion>
<groupId>io.github.thebusybiscuit</groupId> <groupId>com.github.thebusybiscuit</groupId>
<artifactId>Slimefun</artifactId> <artifactId>Slimefun</artifactId>
<!-- Our default version will be UNOFFICIAL, this will prevent auto updates --> <!-- Our default version will be UNOFFICIAL, this will prevent auto updates -->
@ -22,7 +22,7 @@
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<!-- Spigot properties --> <!-- 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> <spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
<!-- Default settings for sonarcloud.io --> <!-- Default settings for sonarcloud.io -->
@ -47,6 +47,16 @@
</licenses> </licenses>
<repositories> <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> <repository>
<id>jitpack.io</id> <id>jitpack.io</id>
<url>https://jitpack.io</url> <url>https://jitpack.io</url>
@ -57,7 +67,7 @@
</repository> </repository>
<repository> <repository>
<id>paper-repo</id> <id>paper-repo</id>
<url>https://repo.destroystokyo.com/repository/maven-public/</url> <url>https://papermc.io/repo/repository/maven-public/</url>
</repository> </repository>
<repository> <repository>
<id>worldedit-repo</id> <id>worldedit-repo</id>
@ -303,14 +313,14 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.seeseemelk</groupId> <groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit</artifactId> <artifactId>MockBukkit-v1.15</artifactId>
<version>v1.15-d952559324-1</version> <version>0.3.1-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>3.4.6</version> <version>3.5.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>

View File

@ -84,7 +84,7 @@ public class ErrorReport {
addon.getLogger().log(Level.WARNING, ""); addon.getLogger().log(Level.WARNING, "");
addon.getLogger().log(Level.WARNING, "An Error occurred! It has been saved as: "); 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, "/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) { if (addon.getBugTrackerURL() != null) {
addon.getLogger().log(Level.WARNING, "Bug Tracker: {0}", addon.getBugTrackerURL()); addon.getLogger().log(Level.WARNING, "Bug Tracker: {0}", addon.getBugTrackerURL());

View File

@ -283,6 +283,14 @@ public class GPSNetwork {
if (!event.isCancelled()) { if (!event.isCancelled()) {
String id = ChatColor.stripColor(ChatColors.color(event.getName())).toUpperCase(Locale.ROOT).replace(' ', '_'); 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())); profile.addWaypoint(new Waypoint(profile, id, event.getLocation(), event.getName()));
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1F, 1F); p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1F, 1F);

View File

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

View File

@ -19,7 +19,8 @@ class GuideCommand extends SubCommand {
public void onExecute(CommandSender sender, String[] args) { public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) { if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.guide")) { 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 { else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true); SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -1,16 +1,10 @@
package io.github.thebusybiscuit.slimefun4.core.guide; package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; 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.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
@ -36,31 +30,7 @@ public final class SlimefunGuide {
private SlimefunGuide() {} private SlimefunGuide() {}
public static ItemStack getItem(SlimefunGuideLayout design) { public static ItemStack getItem(SlimefunGuideLayout design) {
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK); return SlimefunPlugin.getRegistry().getGuideLayout(design).getItem();
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;
} }
public static void openCheatMenu(Player p) { public static void openCheatMenu(Player p) {
@ -132,4 +102,13 @@ public final class SlimefunGuide {
public static boolean isGuideItem(ItemStack item) { 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); 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 io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
/**
* This menu shows a list of every {@link Contributor} to this project.
*
* @author TheBusyBiscuit
*
*/
final class ContributorsMenu { final class ContributorsMenu {
private ContributorsMenu() {} private ContributorsMenu() {}

View File

@ -102,7 +102,7 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
@Override @Override
public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) { public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.values()) { 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); return Optional.of(layout);
} }
} }

View File

@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.guide.options; package io.github.thebusybiscuit.slimefun4.core.guide.options;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.bukkit.ChatColor; 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.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -37,7 +40,16 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
Language language = SlimefunPlugin.getLocalization().getLanguage(p); 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()); 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 { else {
return Optional.empty(); return Optional.empty();
@ -78,7 +90,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
}); });
} }
else if (i == 7) { 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"); ChatUtils.sendURL(pl, "https://github.com/TheBusyBiscuit/Slimefun4/wiki/Translating-Slimefun");
pl.closeInventory(); pl.closeInventory();
return false; return false;
@ -105,7 +117,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
int slot = 10; int slot = 10;
for (Language language : SlimefunPlugin.getLocalization().getLanguages()) { 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)); SlimefunPlugin.instance().getServer().getPluginManager().callEvent(new PlayerLanguageChangeEvent(pl, SlimefunPlugin.getLocalization().getLanguage(pl), language));
setSelectedOption(pl, guide, language.getId()); 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 { public interface SlimefunGuideOption<T> extends Keyed {
/**
* This returns the {@link SlimefunAddon} which added this {@link SlimefunGuideOption}.
*
* @return The registering {@link SlimefunAddon}
*/
SlimefunAddon getAddon(); SlimefunAddon getAddon();
Optional<ItemStack> getDisplayItem(Player p, ItemStack guide); Optional<ItemStack> getDisplayItem(Player p, ItemStack guide);

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -73,14 +74,21 @@ public final class SlimefunGuideSettings {
return false; 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); ContributorsMenu.open(pl, 0);
return false; 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) -> { menu.addMenuClickHandler(6, (pl, slot, item, action) -> {
pl.closeInventory(); pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/TheBusyBiscuit/Slimefun4"); 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(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 // Add something here
return false; return false;
}); });

View File

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

View File

@ -175,7 +175,7 @@ public class CargoNet extends ChestTerminalNetwork {
display(); 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); CargoNetworkTask runnable = new CargoNetworkTask(this, inputs, outputs, chestTerminalInputs, chestTerminalOutputs);
Slimefun.runSync(runnable); 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.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; 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. // All operations happen here: Everything gets iterated from the Input Nodes.
// (Apart from ChestTerminal Buses) // (Apart from ChestTerminal Buses)
SlimefunItem inputNode = SlimefunItems.CARGO_INPUT_NODE.getItem();
for (Map.Entry<Location, Integer> entry : inputs.entrySet()) { for (Map.Entry<Location, Integer> entry : inputs.entrySet()) {
long nodeTimestamp = System.nanoTime(); long nodeTimestamp = System.nanoTime();
Location input = entry.getKey(); Location input = entry.getKey();
@ -71,12 +73,13 @@ class CargoNetworkTask implements Runnable {
attachedBlock.ifPresent(block -> routeItems(input, block, entry.getValue(), outputs)); attachedBlock.ifPresent(block -> routeItems(input, block, entry.getValue(), outputs));
// This will prevent this timings from showing up for the Cargo Manager // 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 // Chest Terminal Code
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) { 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 // 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) { 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) { for (int slot : FILTER_SLOTS) {
ItemStack stack = menu.getItemInSlot(slot); ItemStack stack = menu.getItemInSlot(slot);
if (stack != null) { if (stack != null && stack.getType() != Material.AIR) {
if (wrapper == null) { itemsToCompare++;
// Only create this as needed to save performance
wrapper = new ItemStackWrapper(item);
}
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; return !defaultValue;
} }
} }

View File

@ -274,37 +274,49 @@ abstract class ChestTerminalNetwork extends Network {
* *
* @param providers * @param providers
* A {@link Set} of providers to this {@link ChestTerminalNetwork} * 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()) { if (terminals.isEmpty()) {
// Performance improvement - We don't need to compute items for // Performance improvement - We don't need to compute items for
// Cargo networks without any Chest Terminals // Cargo networks without any Chest Terminals
return; return 0;
} }
// Timings will be slightly inaccurate here but most often people are gonna // Timings will be slightly inaccurate here but most often people are not
// use no more than one terminal anyway, so this might be fine // gonna use no more than one terminal anyway, so this might be fine
long timestamp = SlimefunPlugin.getProfiler().newEntry(); long timestamp = System.nanoTime();
Location firstTerminal = null;
SlimefunItem item = SlimefunItem.getByID("CHEST_TERMINAL"); SlimefunItem item = SlimefunItem.getByID("CHEST_TERMINAL");
List<ItemStackAndInteger> items = findAvailableItems(providers); List<ItemStackAndInteger> items = findAvailableItems(providers);
for (Location l : terminals) { try {
BlockMenu terminal = BlockStorage.getInventory(l); for (Location l : terminals) {
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page")); BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) { if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1; page = 1;
BlockStorage.addBlockInfo(l, "page", String.valueOf(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) { 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(); ItemMeta im = stack.getItemMeta();
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
lore.add(""); 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) { if (stack.getMaxStackSize() > 1) {
int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt(); int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt();
@ -437,7 +449,7 @@ abstract class ChestTerminalNetwork extends Network {
boolean add = true; boolean add = true;
for (ItemStackAndInteger item : items) { for (ItemStackAndInteger item : items) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true)) { if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true, false)) {
add = false; add = false;
item.add(stack.getAmount()); 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); Slimefun.getLogger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
for (BlockStorage storage : worlds) { 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) { if (backups.size() > MAX_BACKUPS) {
try { try {
deleteOldBackups(backups); purgeBackups(backups);
} }
catch (IOException e) { catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Could not delete an old backup", 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) -> { Collections.sort(backups, (a, b) -> {
LocalDateTime time1 = LocalDateTime.parse(a.getName().substring(0, a.getName().length() - 4), format); 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); 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.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@ -116,7 +119,16 @@ public class LocalizationService extends SlimefunLocalization implements Persist
return containsResource("messages_" + language); 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) { public boolean isLanguageLoaded(String id) {
Validate.notNull(id, "The language id cannot be null!");
return languages.containsKey(id); return languages.containsKey(id);
} }
@ -173,7 +185,10 @@ public class LocalizationService extends SlimefunLocalization implements Persist
} }
@Override @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)) { if (hasLanguage(id)) {
FileConfiguration messages = streamConfigFile("messages_" + id + ".yml", getConfig().getConfiguration()); FileConfiguration messages = streamConfigFile("messages_" + id + ".yml", getConfig().getConfiguration());
FileConfiguration researches = streamConfigFile("researches_" + id + ".yml", null); 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 categories = streamConfigFile("categories_" + id + ".yml", null);
FileConfiguration recipes = streamConfigFile("recipes_" + 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.setMessagesFile(messages);
language.setResearchesFile(researches); language.setResearchesFile(researches);
language.setResourcesFile(resources); 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} * @return A percentage {@code (0.0 - 100.0)} for the progress of translation of that {@link Language}
*/ */
public double getProgress(Language lang) { public double calculateProgress(Language lang) {
int defaultKeys = getTotalKeys(languages.get("en")); 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 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()); return getKeys(lang.getFiles());
} }
private int getKeys(FileConfiguration... files) { private Set<String> getKeys(FileConfiguration... files) {
int keys = 0; Set<String> keys = new HashSet<>();
for (FileConfiguration cfg : files) { for (FileConfiguration cfg : files) {
keys += cfg != null ? cfg.getKeys(true).size() : 0; keys.addAll(cfg.getKeys(true));
} }
return keys; return keys;

View File

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

View File

@ -25,6 +25,7 @@ public final class Language {
private final String id; private final String id;
private final ItemStack item; private final ItemStack item;
private double progress = -1;
private FileConfiguration messages; private FileConfiguration messages;
private FileConfiguration researches; private FileConfiguration researches;
@ -60,6 +61,26 @@ public final class Language {
return id; 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() { FileConfiguration getMessagesFile() {
return messages; return messages;
} }
@ -145,7 +166,7 @@ public final class Language {
@Override @Override
public String toString() { public String toString() {
return "Language [ id= " + id + " | default=" + isDefault() + " ]"; return "Language {id= " + id + ", default=" + isDefault() + " }";
} }
public FileConfiguration[] getFiles() { public FileConfiguration[] getFiles() {

View File

@ -119,6 +119,13 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
return messages; 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) { public String getResearchName(Player p, NamespacedKey key) {
Language language = getLanguage(p); 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 // two ticks (sync and async blocks), so we use 100ms as a reference here
private static final int MAX_TICK_DURATION = 100; 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 AtomicBoolean running = new AtomicBoolean(false);
private final AtomicInteger queued = new AtomicInteger(0); private final AtomicInteger queued = new AtomicInteger(0);
@ -118,7 +118,8 @@ public class SlimefunProfiler {
executor.execute(() -> { executor.execute(() -> {
ProfiledBlock block = new ProfiledBlock(l, item); 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(); queued.decrementAndGet();
}); });
@ -143,7 +144,7 @@ public class SlimefunProfiler {
private void finishReport() { private void finishReport() {
// We will only wait for a maximum of this many 1ms sleeps // 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 // Wait for all timing results to come in
while (!running.get() && queued.get() > 0) { 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 we waited for too long, then we should just abort
if (iterations <= 0) { 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; 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 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 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 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 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, 6, 0), "&cMelon 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, 6, 0), "&6Carrot 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, 6, 0), "&6Pumpkin 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, 6, 0), "&cSweet Berry 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 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!"); 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"); public static final SlimefunItemStack KELP_COOKIE = new SlimefunItemStack("KELP_COOKIE", Material.COOKIE, "&2Kelp Cookie");
/* Christmas */ /* 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_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, 12, 0), "&6Chocolate Milk", "", LoreBuilder.hunger(6)); 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, 7, 0), "&aEgg Nog", "", LoreBuilder.hunger(3.5)); 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, 14, 0), "&cApple Cider", "", LoreBuilder.hunger(7)); 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_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_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_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_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 = new SlimefunItemStack("CHRISTMAS_CARAMEL", Material.BRICK, "&6Caramel");
public static final SlimefunItemStack CHRISTMAS_CARAMEL_APPLE = new SlimefunItemStack("CHRISTMAS_CARAMEL_APPLE", Material.APPLE, "&6Caramel Apple"); 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_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 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 GOLDEN_HELMET_12K = new SlimefunItemStack("GOLD_12K_HELMET", Material.GOLDEN_HELMET, "&6Golden Helmet &7(12-Carat)");
public static final SlimefunItemStack GOLD_CHESTPLATE = new SlimefunItemStack("GOLD_12K_CHESTPLATE", Material.GOLDEN_CHESTPLATE, "&6Gold Chestplate", "&912-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 GOLD_LEGGINGS = new SlimefunItemStack("GOLD_12K_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Gold Leggings", "&912-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 GOLD_BOOTS = new SlimefunItemStack("GOLD_12K_BOOTS", Material.GOLDEN_BOOTS, "&6Gold Boots", "&912-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_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"); 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_LEGGINGS.addUnsafeEnchantments(gilded);
GILDED_IRON_BOOTS.addUnsafeEnchantments(gilded); GILDED_IRON_BOOTS.addUnsafeEnchantments(gilded);
GOLD_HELMET.addUnsafeEnchantment(Enchantment.DURABILITY, 10); GOLDEN_HELMET_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_CHESTPLATE.addUnsafeEnchantment(Enchantment.DURABILITY, 10); GOLDEN_CHESTPLATE_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_LEGGINGS.addUnsafeEnchantment(Enchantment.DURABILITY, 10); GOLDEN_LEGGINGS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_BOOTS.addUnsafeEnchantment(Enchantment.DURABILITY, 10); GOLDEN_BOOTS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
Map<Enchantment, Integer> slime = new HashMap<>(); Map<Enchantment, Integer> slime = new HashMap<>();
slime.put(Enchantment.DURABILITY, 4); 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 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 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!"); private static final String RAINBOW = "&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_WOOL = new SlimefunItemStack("RAINBOW_WOOL", Material.WHITE_WOOL, "&5Rainbow Wool", "", 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 = new SlimefunItemStack("RAINBOW_GLASS", Material.WHITE_STAINED_GLASS, "&5Rainbow Glass", "", 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_CLAY = new SlimefunItemStack("RAINBOW_CLAY", Material.WHITE_TERRACOTTA, "&5Rainbow Clay", "", 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_GLASS_PANE = new SlimefunItemStack("RAINBOW_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE, "&5Rainbow Glass Pane", "", 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!"); 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 */ /* Seasonal */
private static final String CHRISTMAS = ChatUtils.christmas("[Christmas Edition]"); 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.DebugFishListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.DispenserListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.DispenserListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EnhancedFurnaceListener; 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.ExplosionsListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GadgetsListener; 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.MobDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener; 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.PlayerProfileListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBootsListener; 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.TalismanListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener; 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.WitherListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener;
import io.github.thebusybiscuit.slimefun4.implementation.resources.GEOResourcesSetup; 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); local = new LocalizationService(this, "", null);
gpsNetwork = new GPSNetwork(); gpsNetwork = new GPSNetwork();
command.register(); command.register();
registry.load(config);
} }
else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) { else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
long timestamp = System.nanoTime(); long timestamp = System.nanoTime();
@ -255,7 +257,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Armor Update Task // Armor Update Task
if (config.getBoolean("options.enable-armor-effects")) { 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")); 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 // Save all registered Worlds
for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) { for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) {
try { try {
entry.getValue().save(true); entry.getValue().saveAndRemove();
} }
catch (Exception x) { catch (Exception x) {
getLogger().log(Level.SEVERE, x, () -> "An Error occurred while saving Slimefun-Blocks in World '" + entry.getKey() + "' for Slimefun " + getVersion()); 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 FireworksListener(this);
new WitherListener(this); new WitherListener(this);
new IronGolemListener(this); new IronGolemListener(this);
new PlayerInteractEntityListener(this); new EntityInteractionListener(this);
new MobDropListener(this); new MobDropListener(this);
new VillagerTradingListener(this);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) { if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
new BeeListener(this); new BeeListener(this);

View File

@ -10,6 +10,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput; import io.github.thebusybiscuit.cscorelib2.chat.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.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent; import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; 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.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory; import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory; import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
@ -36,6 +36,24 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class BookSlimefunGuide implements SlimefunGuideImplementation { public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance(), "search"); 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 @Override
public SlimefunGuideLayout getLayout() { public SlimefunGuideLayout getLayout() {
@ -49,7 +67,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
@Override @Override
public ItemStack getItem() { 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) { 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")); lines.add(new ChatComponent(ChatColor.DARK_GRAY + "\u21E8" + ChatColor.DARK_BLUE + " Tier " + tier + "\n"));
} }
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) { addCategory(p, profile, category, lines);
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);
}
} }
} }
openBook(p, profile, lines, false); 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 @Override
public void openCategory(PlayerProfile profile, Category category, int page) { public void openCategory(PlayerProfile profile, Category category, int page) {
Player p = profile.getPlayer(); Player p = profile.getPlayer();
@ -159,20 +181,20 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
List<ChatComponent> items = new LinkedList<>(); List<ChatComponent> items = new LinkedList<>();
for (SlimefunItem item : category.getItems()) { for (SlimefunItem slimefunItem : category.getItems()) {
if (Slimefun.hasPermission(p, item, false)) { if (Slimefun.hasPermission(p, slimefunItem, false)) {
if (Slimefun.isEnabled(p, item, false)) { if (Slimefun.isEnabled(p, slimefunItem, false)) {
appendSlimefunItem(category, page, p, profile, item, items); addSlimefunItem(category, page, p, profile, slimefunItem, items);
} }
} }
else { 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<>(); 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(""); lore.add("");
for (String line : SlimefunPlugin.getPermissionsService().getLore(item)) { for (String line : SlimefunPlugin.getPermissionsService().getLore(slimefunItem)) {
lore.add(ChatColors.color(line)); 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)); NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getID().toLowerCase(Locale.ROOT));
if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) { 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"); 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.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(() -> { component.setClickEvent(new ClickEvent(key, player -> research(player, profile, item, research, category, page)));
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);
}
}
})));
items.add(component); 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 @Override
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) { public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
// We need to write a book implementation for this at some point // 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; 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.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
public class CheatSheetSlimefunGuide extends ChestSlimefunGuide { public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
private final ItemStack item;
public CheatSheetSlimefunGuide() { public CheatSheetSlimefunGuide() {
super(false); 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 @Override
@ -23,6 +48,11 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
return SlimefunGuideLayout.CHEAT_SHEET; return SlimefunGuideLayout.CHEAT_SHEET;
} }
@Override
public ItemStack getItem() {
return item;
}
@Override @Override
protected void createHeader(Player p, PlayerProfile profile, ChestMenu menu) { protected void createHeader(Player p, PlayerProfile profile, ChestMenu menu) {
super.createHeader(p, profile, 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.Recipe;
import org.bukkit.inventory.RecipeChoice; import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.RecipeChoice.MaterialChoice; 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.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
@ -50,6 +52,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36; 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 int[] recipeSlots = { 3, 4, 5, 12, 13, 14, 21, 22, 23 };
private final Sound sound; private final Sound sound;
private final boolean showVanillaRecipes; private final boolean showVanillaRecipes;
@ -63,6 +66,21 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
else { else {
sound = Sound.ENTITY_BAT_TAKEOFF; 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 @Override
@ -72,7 +90,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
@Override @Override
public ItemStack getItem() { 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 @Override
@ -313,17 +331,17 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
int index = 9; int index = 9;
// Find items and add them // Find items and add them
for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) { for (SlimefunItem slimefunItem : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
String itemName = ChatColor.stripColor(item.getItemName()).toLowerCase(Locale.ROOT); String itemName = ChatColor.stripColor(slimefunItem.getItemName()).toLowerCase(Locale.ROOT);
if (index == 44) { if (index == 44) {
break; break;
} }
if (!itemName.isEmpty() && (itemName.equals(searchTerm) || itemName.contains(searchTerm))) { 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; List<String> lore = null;
Category category = item.getCategory(); Category category = slimefunItem.getCategory();
if (category != null) { if (category != null) {
ItemStack categoryItem = category.getItem(p); ItemStack categoryItem = category.getItem(p);
@ -341,10 +359,10 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
menu.addMenuClickHandler(index, (pl, slot, itm, action) -> { menu.addMenuClickHandler(index, (pl, slot, itm, action) -> {
try { try {
if (!isSurvivalMode()) { if (!isSurvivalMode()) {
pl.getInventory().addItem(item.getItem().clone()); pl.getInventory().addItem(slimefunItem.getItem().clone());
} }
else { else {
displayItem(profile, item, true); displayItem(profile, slimefunItem, true);
} }
} }
catch (Exception | LinkageError x) { catch (Exception | LinkageError x) {
@ -400,30 +418,9 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
RecipeChoiceTask task = new RecipeChoiceTask(); RecipeChoiceTask task = new RecipeChoiceTask();
if (optional.isPresent()) { if (optional.isPresent()) {
MinecraftRecipe<?> mcRecipe = optional.get(); showRecipeChoices(recipe, recipeItems, task);
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe); recipeType = new RecipeType(optional.get());
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);
result = recipe.getResult(); result = recipe.getResult();
} }
else { 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 @Override
public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) { public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
Player p = profile.getPlayer(); 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) { private void addDisplayRecipe(ChestMenu menu, PlayerProfile profile, List<ItemStack> recipes, int slot, int i, int page) {
if ((i + (page * 18)) < recipes.size()) { 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 // 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 // but we wanna make sure no stupid addon creator sneaked some nulls in here
if (item != null) { if (displayItem != null) {
item = item.clone(); displayItem = displayItem.clone();
} }
menu.replaceExistingItem(slot, item); menu.replaceExistingItem(slot, displayItem);
if (page == 0) { if (page == 0) {
menu.addMenuClickHandler(slot, (pl, s, itemstack, action) -> { menu.addMenuClickHandler(slot, (pl, s, itemstack, action) -> {

View File

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

View File

@ -1,26 +1,33 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks; package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Nameable; import org.bukkit.Nameable;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Dispenser; 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.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections; 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.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -39,7 +46,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see BlockPlacerPlaceEvent * @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())); 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); super(category, item, recipeType, recipe);
addItemSetting(blacklist); addItemSetting(blacklist);
addItemHandler(onPlace(), onBlockDispense());
} }
@Override private BlockPlaceHandler onPlace() {
public BlockDispenseHandler getItemHandler() { 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) -> { return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) {
return;
}
if (isShulkerBox(e.getItem().getType())) { if (isShulkerBox(e.getItem().getType())) {
// Since vanilla Dispensers can already place Shulker boxes, we // Since vanilla Dispensers can already place Shulker boxes, we
// simply fallback to the vanilla behaviour. // 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) { private boolean isShulkerBox(Material type) {
return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX"); return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX");
} }
@ -139,14 +188,17 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
if (meta.hasDisplayName()) { if (meta.hasDisplayName()) {
BlockState blockState = facedBlock.getState(); BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false);
if ((blockState instanceof Nameable)) { if ((blockState.getState() instanceof Nameable)) {
((Nameable) blockState).setCustomName(meta.getDisplayName()); 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 }; 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) { public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe, recipeOutput); super(category, item, recipeType, recipe, null);
} }
@Override @Override

View File

@ -60,10 +60,14 @@ public class EnergyRegulator extends SlimefunItem {
@Override @Override
public void tick(Block b, SlimefunItem item, Config data) { public void tick(Block b, SlimefunItem item, Config data) {
EnergyNet network = EnergyNet.getNetworkFromLocationOrCreate(b.getLocation()); EnergyRegulator.this.tick(b);
network.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 org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable; 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.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -42,6 +43,21 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
return capacity; 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() { protected ItemUseHandler getItemUseHandler() {
return e -> { return e -> {
Player p = e.getPlayer(); Player p = e.getPlayer();
@ -64,29 +80,33 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
SlimefunItem selectedItem = modes.get(index).getItem(); SlimefunItem selectedItem = modes.get(index).getItem();
String itemName = selectedItem != null ? selectedItem.getItemName() : "Unknown"; 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); selectedMode.put(p.getUniqueId(), index);
} }
}; };
} }
private int nextIndex(int i) { private ToolUseHandler getToolUseHandler() {
int index = i; return (e, tool, fortune, drops) -> {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
do { e.setCancelled(true);
index++; };
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
return index;
} }
private ToolUseHandler getToolUseHandler() { private EntityInteractHandler getEntityInteractionHandler() {
return (e, tool, fortune, drops) -> e.setCancelled(true); 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 @Override
@ -95,6 +115,7 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
addItemHandler(getItemUseHandler()); addItemHandler(getItemUseHandler());
addItemHandler(getToolUseHandler()); addItemHandler(getToolUseHandler());
addItemHandler(getEntityInteractionHandler());
} }
} }

View File

@ -11,23 +11,23 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public abstract class LavaGenerator extends AGenerator { public abstract class LavaGenerator extends AGenerator {
public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe); super(category, item, recipeType, recipe);
} }
@Override @Override
protected void registerDefaultFuelTypes() { protected void registerDefaultFuelTypes() {
registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET))); registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET)));
} }
@Override @Override
public ItemStack getProgressBar() { public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL); return new ItemStack(Material.FLINT_AND_STEEL);
} }
@Override @Override
public String getInventoryTitle() { public String getInventoryTitle() {
return "&4Lava Generator"; 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.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.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.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.IRON_INGOT, 9), new ItemStack(Material.IRON_BLOCK));
addRecipe(5, new ItemStack(Material.GOLD_INGOT, 9), new ItemStack(Material.GOLD_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; 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.items.backpacks.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CoolerListener; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -19,10 +32,69 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see CoolerListener * @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) { 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.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe; 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.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
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[] 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 }; 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; package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.entity.ZombieVillager; import org.bukkit.entity.ZombieVillager;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -38,8 +39,11 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
@Override @Override
public EntityInteractHandler getItemHandler() { public EntityInteractHandler getItemHandler() {
return (p, entity, item, offhand) -> { return (e, item, offhand) -> {
Entity entity = e.getRightClicked();
if (entity.getType() == EntityType.ZOMBIE_VILLAGER) { if (entity.getType() == EntityType.ZOMBIE_VILLAGER) {
Player p = e.getPlayer();
if (p.getGameMode() != GameMode.CREATIVE) { if (p.getGameMode() != GameMode.CREATIVE) {
ItemUtils.consumeItem(item, false); ItemUtils.consumeItem(item, false);

View File

@ -11,6 +11,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.enchantment.EnchantItemEvent; import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityEvent; import org.bukkit.event.entity.EntityEvent;
@ -127,7 +128,7 @@ public class Talisman extends SlimefunItem {
} }
private static boolean hasMessage(Talisman talisman) { private static boolean hasMessage(Talisman talisman) {
return !("").equalsIgnoreCase(talisman.getMessageSuffix()); return talisman.getMessageSuffix() != null;
} }
public static boolean checkFor(Event e, SlimefunItemStack stack) { public static boolean checkFor(Event e, SlimefunItemStack stack) {
@ -224,6 +225,9 @@ public class Talisman extends SlimefunItem {
else if (e instanceof BlockBreakEvent) { else if (e instanceof BlockBreakEvent) {
return ((BlockBreakEvent) e).getPlayer(); return ((BlockBreakEvent) e).getPlayer();
} }
else if (e instanceof BlockDropItemEvent) {
return ((BlockDropItemEvent) e).getPlayer();
}
else if (e instanceof PlayerEvent) { else if (e instanceof PlayerEvent) {
return ((PlayerEvent) e).getPlayer(); 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)); return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2));
case LAPIS_ORE: case LAPIS_ORE:
return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4));
case ANCIENT_DEBRIS:
return new ItemStack(Material.ANCIENT_DEBRIS);
default: default:
// This includes Iron and Gold ore // This includes Iron and Gold ore (and Ancient Debris)
return new ItemStack(ore); 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} * @return Whether this {@link IndustrialMiner} is capable of mining this {@link Material}
*/ */
public boolean canMine(Material type) { 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) { 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()) { 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); Bukkit.getPluginManager().callEvent(event);
// Fixes #2207 - Only apply Vector if the Player is able to damage the entity
if (!event.isCancelled()) { 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.inventory.meta.ItemMeta;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
@ -53,6 +54,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/ */
public class AncientAltarListener implements Listener { public class AncientAltarListener implements Listener {
public static final String ITEM_PREFIX = ChatColors.color("&dALTAR &3Probe - &e");
private AncientAltar altar; private AncientAltar altar;
private final Set<AltarRecipe> altarRecipes = new HashSet<>(); private final Set<AltarRecipe> altarRecipes = new HashSet<>();
@ -303,7 +306,7 @@ public class AncientAltarListener implements Listener {
} }
String nametag = ItemUtils.getItemName(stack); 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)); entity.setVelocity(new Vector(0, 0.1, 0));
SlimefunUtils.markAsNoPickup(entity, "altar_item"); SlimefunUtils.markAsNoPickup(entity, "altar_item");
entity.setCustomNameVisible(true); entity.setCustomNameVisible(true);

View File

@ -42,7 +42,9 @@ public class BeeListener implements Listener {
if (profile.hasFullProtectionAgainst(ProtectionType.BEES)) { if (profile.hasFullProtectionAgainst(ProtectionType.BEES)) {
for (ItemStack armor : p.getInventory().getArmorContents()) { for (ItemStack armor : p.getInventory().getArmorContents()) {
ItemUtils.damageItem(armor, 1, false); if (armor != null) {
ItemUtils.damageItem(armor, 1, false);
}
} }
e.setDamage(0D); 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.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun; 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 { public class BlockListener implements Listener {
// Materials that require a Block under it, e.g. Pressure Plates // 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) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockRegister(BlockPlaceEvent e) { public void onBlockPlace(BlockPlaceEvent e) {
if (BlockStorage.hasBlockInfo(e.getBlock())) { if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true); e.setCancelled(true);
return; return;
@ -81,7 +92,7 @@ public class BlockListener implements Listener {
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockUnregister(BlockBreakEvent e) { public void onBlockBreak(BlockBreakEvent e) {
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock()); checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock());
ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
@ -89,50 +100,58 @@ public class BlockListener implements Listener {
List<ItemStack> drops = new ArrayList<>(); List<ItemStack> drops = new ArrayList<>();
if (item.getType() != Material.AIR) { if (item.getType() != Material.AIR) {
SlimefunItem tool = SlimefunItem.getByItem(item); callToolHandler(e, item, fortune, drops);
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);
}
}
} }
if (!e.isCancelled()) { if (!e.isCancelled()) {
SlimefunItem sfItem = BlockStorage.check(e.getBlock()); callBlockHandler(e, item, fortune, drops);
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());
}
} }
dropItems(e, 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) { private void dropItems(BlockBreakEvent e, List<ItemStack> drops) {
if (!drops.isEmpty()) { if (!drops.isEmpty()) {
e.getBlock().setType(Material.AIR); e.getBlock().setType(Material.AIR);

View File

@ -4,6 +4,7 @@ import java.util.logging.Level;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Skull; import org.bukkit.block.Skull;
import org.bukkit.block.data.Directional; import org.bukkit.block.data.Directional;
import org.bukkit.block.data.Rotatable; import org.bukkit.block.data.Rotatable;
@ -58,29 +59,10 @@ public class DebugFishListener implements Listener {
if (p.hasPermission("slimefun.debugging")) { if (p.hasPermission("slimefun.debugging")) {
if (e.getAction() == Action.LEFT_CLICK_BLOCK) { if (e.getAction() == Action.LEFT_CLICK_BLOCK) {
if (p.isSneaking()) { onLeftClick(p, e.getClickedBlock(), e);
if (BlockStorage.hasBlockInfo(e.getClickedBlock())) {
BlockStorage.clearBlockInfo(e.getClickedBlock());
}
}
else {
e.setCancelled(false);
}
} }
else if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { else if (e.getAction() == Action.RIGHT_CLICK_BLOCK) {
if (p.isSneaking()) { onRightClick(p, e.getClickedBlock(), e.getBlockFace());
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);
}
}
} }
} }
else { 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) { private void sendInfo(Player p, Block b) {
SlimefunItem item = BlockStorage.check(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.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -21,14 +21,14 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
* @see EntityInteractHandler * @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); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }
@EventHandler @EventHandler
public void onInteractEntity(PlayerInteractAtEntityEvent e) { public void onInteractEntity(PlayerInteractEntityEvent e) {
if (!e.getRightClicked().isValid()) { if (!e.getRightClicked().isValid()) {
return; return;
} }
@ -45,7 +45,7 @@ public class PlayerInteractEntityListener implements Listener {
SlimefunItem sfItem = SlimefunItem.getByItem(itemStack); SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
if (sfItem != null && Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) { 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.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent; 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.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@ -16,8 +16,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
*/ */
public class ItemPickupListener implements Listener { public class ItemPickupListener implements Listener {
private static final String ITEM_PREFIX = ChatColors.color("&5&dALTAR &3Probe - &e");
public ItemPickupListener(SlimefunPlugin plugin) { public ItemPickupListener(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }
@ -27,9 +25,13 @@ public class ItemPickupListener implements Listener {
if (SlimefunUtils.hasNoPickupFlag(e.getItem())) { if (SlimefunUtils.hasNoPickupFlag(e.getItem())) {
e.setCancelled(true); e.setCancelled(true);
} }
else if (e.getItem().getItemStack().hasItemMeta() && e.getItem().getItemStack().getItemMeta().hasDisplayName() && e.getItem().getItemStack().getItemMeta().getDisplayName().startsWith(ITEM_PREFIX)) { else if (e.getItem().getItemStack().hasItemMeta()) {
e.setCancelled(true); ItemMeta meta = e.getItem().getItemStack().getItemMeta();
e.getItem().remove();
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())) { if (SlimefunUtils.hasNoPickupFlag(e.getItem())) {
e.setCancelled(true); e.setCancelled(true);
} }
else if (e.getItem().getItemStack().hasItemMeta() && e.getItem().getItemStack().getItemMeta().hasDisplayName() && e.getItem().getItemStack().getItemMeta().getDisplayName().startsWith(ITEM_PREFIX)) { else if (e.getItem().getItemStack().hasItemMeta()) {
e.setCancelled(true); ItemMeta meta = e.getItem().getItemStack().getItemMeta();
e.getItem().remove();
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 @EventHandler
public void onEntityPickup(EntityPickupItemEvent e) { public void onPickup(EntityPickupItemEvent e) {
if (e.getEntityType() == EntityType.PIGLIN) { if (e.getEntityType() == EntityType.PIGLIN) {
ItemStack item = e.getItem().getItemStack(); 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 @EventHandler
public void onPiglinDropItem(EntityDropItemEvent e) { public void onPiglinDropItem(EntityDropItemEvent e) {
if (e.getEntity() instanceof Piglin) { 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; return;
} }
SlimefunGuideLayout type = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST; SlimefunGuideLayout type = SlimefunGuide.getDefaultLayout();
p.getInventory().addItem(SlimefunGuide.getItem(type)); p.getInventory().addItem(SlimefunGuide.getItem(type).clone());
} }
} }
@ -69,7 +69,7 @@ public class SlimefunGuideListener implements Listener {
Player p = e.getPlayer(); Player p = e.getPlayer();
ItemStack item = e.getItem(); ItemStack item = e.getItem();
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true)) { if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true, false)) {
e.cancel(); e.cancel();
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {

View File

@ -1,22 +1,23 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners; package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.inventory.ItemStack; 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.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; 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.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun; 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 class SlimefunItemConsumeListener implements Listener {
public SlimefunItemConsumeListener(SlimefunPlugin plugin) { public SlimefunItemConsumeListener(SlimefunPlugin plugin) {
@ -31,53 +32,11 @@ public class SlimefunItemConsumeListener implements Listener {
if (sfItem != null) { if (sfItem != null) {
if (Slimefun.hasUnlocked(p, sfItem, true)) { if (Slimefun.hasUnlocked(p, sfItem, true)) {
if (sfItem instanceof Juice) { sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item));
// 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));
}
} }
else { else {
e.setCancelled(true); 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.AbstractArrow;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.ChestedHorse; import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile; import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; 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.enchantment.EnchantItemEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
@ -35,7 +36,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem; 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.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman; 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) @EventHandler(ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) { public void onBlockDropItems(BlockDropItemEvent e) {
// We only want to double ores // 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(); ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
if (item.getType() != Material.AIR && item.getAmount() > 0) { if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
Collection<ItemStack> drops = e.getBlock().getDrops(item); Collection<Item> drops = e.getItems();
int dropAmount = 1;
if (item.getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS) && !item.getEnchantments().containsKey(Enchantment.SILK_TOUCH)) { if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) {
Random random = ThreadLocalRandom.current(); int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
dropAmount = random.nextInt(item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS) + 2) - 1; boolean doubledDrops = false;
dropAmount = Math.max(dropAmount, 1);
dropAmount = (e.getBlock().getType() == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1) * (dropAmount + 1);
}
if (!item.getEnchantments().containsKey(Enchantment.SILK_TOUCH) && Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) { for (Item drop : drops) {
for (ItemStack drop : drops) { ItemStack droppedItem = drop.getItemStack();
if (!drop.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - drop.getAmount()); if (!droppedItem.getType().isBlock()) {
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(drop, amount)); 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.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.event.inventory.PrepareItemCraftEvent;
@ -95,10 +96,24 @@ public class VanillaMachinesListener implements Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPreBrew(InventoryClickEvent e) { 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) { if (clickedInventory != null && topInventory.getType() == InventoryType.BREWING && topInventory.getHolder() instanceof BrewingStand) {
e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor()))); 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()); BlockStorage storage = BlockStorage.getStorage(e.getWorld());
if (storage != null) { if (storage != null) {
storage.save(true); storage.saveAndRemove();
} }
else { else {
Slimefun.getLogger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName()); 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("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("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("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("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("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); 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 { public class ArmorTask implements Runnable {
private final Set<PotionEffect> radiationEffects; 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<>(); Set<PotionEffect> effects = new HashSet<>();
effects.add(new PotionEffect(PotionEffectType.WITHER, 400, 2)); effects.add(new PotionEffect(PotionEffectType.WITHER, 400, 2));
effects.add(new PotionEffect(PotionEffectType.BLINDNESS, 400, 3)); effects.add(new PotionEffect(PotionEffectType.BLINDNESS, 400, 3));
@ -47,6 +56,16 @@ public class ArmorTask implements Runnable {
radiationEffects = Collections.unmodifiableSet(effects); 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 @Override
public void run() { public void run() {
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
@ -144,7 +163,11 @@ public class ArmorTask implements Runnable {
Slimefun.runSync(() -> { Slimefun.runSync(() -> {
p.addPotionEffects(radiationEffects); p.addPotionEffects(radiationEffects);
p.setFireTicks(400);
// if radiative fire is enabled
if (radioactiveFire) {
p.setFireTicks(400);
}
}); });
return true; return true;

View File

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

View File

@ -274,78 +274,42 @@ public final class SlimefunUtils {
private static boolean equalsItemMeta(ItemMeta itemMeta, ImmutableItemMeta meta, boolean checkLore) { private static boolean equalsItemMeta(ItemMeta itemMeta, ImmutableItemMeta meta, boolean checkLore) {
Optional<String> displayName = meta.getDisplayName(); Optional<String> displayName = meta.getDisplayName();
if (itemMeta.hasDisplayName() && displayName.isPresent()) { if (itemMeta.hasDisplayName() != displayName.isPresent()) {
if (itemMeta.getDisplayName().equals(displayName.get())) { return false;
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;
}
} }
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(); Optional<List<String>> itemLore = meta.getLore();
if (checkLore) { if (itemMeta.hasLore() && itemLore.isPresent()) {
if (itemMeta.hasLore() && itemLore.isPresent()) { return equalsLore(itemMeta.getLore(), itemLore.get());
return equalsLore(itemMeta.getLore(), itemLore.get());
}
else {
return !itemMeta.hasLore() && !itemLore.isPresent();
}
} }
else { else {
return true; return !itemMeta.hasLore() && !itemLore.isPresent();
} }
} }
else return false;
} }
private static boolean equalsItemMeta(ItemMeta itemMeta, ItemMeta sfitemMeta, boolean checkLore) { private static boolean equalsItemMeta(ItemMeta itemMeta, ItemMeta sfitemMeta, boolean checkLore) {
if (itemMeta.hasDisplayName() && sfitemMeta.hasDisplayName()) { if (itemMeta.hasDisplayName() != sfitemMeta.hasDisplayName()) {
if (itemMeta.getDisplayName().equals(sfitemMeta.getDisplayName())) { return false;
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;
}
} }
else if (!itemMeta.hasDisplayName() && !sfitemMeta.hasDisplayName()) { else if (itemMeta.hasDisplayName() && sfitemMeta.hasDisplayName() && !itemMeta.getDisplayName().equals(sfitemMeta.getDisplayName())) {
if (checkLore) { return false;
if (itemMeta.hasLore() && sfitemMeta.hasLore()) { }
return equalsLore(itemMeta.getLore(), sfitemMeta.getLore()); else if (!checkLore) {
} return true;
else { }
return !itemMeta.hasLore() && !sfitemMeta.hasLore(); else if (itemMeta.hasLore() && sfitemMeta.hasLore()) {
} return equalsLore(itemMeta.getLore(), sfitemMeta.getLore());
}
else {
return true;
}
} }
else { 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_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_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 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_HELMET = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLDEN_HELMET_12K;
public static final SlimefunItemStack GOLD_CHESTPLATE = io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems.GOLD_CHESTPLATE; 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.GOLD_LEGGINGS; 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.GOLD_BOOTS; 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_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_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; 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(); return data.keySet();
} }
private UnsupportedOperationException invalidType(String path) {
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
}
@Override @Override
public int getInt(String path) { public int getInt(String path) {
throw invalidType(path); throw invalidType(path);
@ -121,6 +117,10 @@ public class BlockInfoConfig extends Config {
throw invalidType(path); throw invalidType(path);
} }
private UnsupportedOperationException invalidType(String path) {
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
}
@Override @Override
public File getFile() { public File getFile() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ commands:
guide: guide:
locked: 'LOCKED' locked: 'LOCKED'
work-in-progress: 'This feature is not fully finished yet!'
locked-category: locked-category:
- 'To unlock this category you will' - 'To unlock this category you will'
@ -64,6 +65,13 @@ guide:
selected-language: 'Currently selected:' selected-language: 'Currently selected:'
select: 'Click to select this language' select: 'Click to select this language'
select-default: 'Click to select the default 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: translations:
name: '&aIs something missing?' name: '&aIs something missing?'
@ -78,11 +86,19 @@ guide:
addons: 'Addons for Slimefun4' addons: 'Addons for Slimefun4'
bugs: 'Bug Reports' bugs: 'Bug Reports'
source: 'Source Code' source: 'Source Code'
versions: 'Installed versions'
credits: credits:
commit: 'Commit' commit: 'Commit'
commits: 'Commits' commits: 'Commits'
profile-link: 'Click to visit their profile on GitHub' 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: roles:
developer: '&6Developer' developer: '&6Developer'
wiki: '&3Wiki Editor' wiki: '&3Wiki Editor'
@ -105,13 +121,16 @@ messages:
not-valid-research: '&4%research% &cis not a valid Research!' not-valid-research: '&4%research% &cis not a valid Research!'
give-research: '&bYou have given %player% the Research &7"%research%&7"' give-research: '&bYou have given %player% the Research &7"%research%&7"'
hungry: '&cYou are too hungry to do that!' 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-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?' 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...' no-tome-yourself: '&cYou cannot use the &4Tome of Knowledge &con yourself...'
multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%' multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%'
piglin-barter: '&4You cannot barter with piglins using Slimefun items' 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: talisman:
anvil: '&a&oYour Talisman saved your tool from breaking' anvil: '&a&oYour Talisman saved your tool from breaking'
miner: '&a&oYour Talisman just doubled your drops' miner: '&a&oYour Talisman just doubled your drops'
@ -232,6 +251,12 @@ machines:
anvil: anvil:
not-working: '&4You cannot use Slimefun Items in an 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: backpack:
already-open: '&cSorry, this Backpack is open somewhere else!' already-open: '&cSorry, this Backpack is open somewhere else!'
no-stack: '&cYou cannot stack Backpacks' 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!)' new: '&ePlease type in a name for your new waypoint in the chat. &7(Color Codes supported!)'
added: '&aSuccessfully added a new waypoint' added: '&aSuccessfully added a new waypoint'
max: '&4You have reached the maximum amount of waypoints' max: '&4You have reached the maximum amount of waypoints'
duplicate: '&4You have already created a waypoint named: &f%waypoint%'
insufficient-complexity: insufficient-complexity:
- '&4Insufficient GPS Network Complexity: &c%complexity%' - '&4Insufficient GPS Network Complexity: &c%complexity%'

View File

@ -24,21 +24,27 @@ guide:
search: search:
message: "&b¿Qué te gustaría buscar?" message: "&b¿Qué te gustaría buscar?"
name: "&7Busca..." name: "&7Busca..."
tooltip: "&bClick para buscar un item" tooltip: "&bCliquea para buscar un objeto"
inventory: 'Buscando: %item%' inventory: 'Buscando: %item%'
lore: lore:
- "&b¿Qué te gustaría buscar?" - "&b¿Qué te gustaría buscar?"
- "&7Escribe en el chat el término que quieres buscar." - "&7Escribe en el chat el término que quieres buscar."
cheat: cheat:
no-multiblocks: "&4¡No puedes obtener los Multiblocks, tienes que construirlos!" no-multiblocks: "&4¡No puedes regalarte los Multiblocks, tienes que construirlos!"
languages: languages:
updated: "&aTu lenguaje fue cambiado a: &b%lang%" updated: "&aTu lenguaje fue cambiado a: &b%lang%"
translations: translations:
name: "&a¿Falta algo?" name: "&a¿Falta algo?"
lore: Clic para agregar tu propia traducción. lore: Cliquea para agregar tu propia traducción.
select: Clic para seleccionar este idioma. select: Cliquea para seleccionar este idioma.
select-default: Clic para seleccionar el idioma predeterminado. select-default: Cliquea para seleccionar el idioma predeterminado.
selected-language: 'Actualmente seleccionado:' 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: title:
main: Guía de Slimefun. main: Guía de Slimefun.
settings: Configuración e Información. settings: Configuración e Información.
@ -48,6 +54,7 @@ guide:
addons: Complementos para Slimefun4 addons: Complementos para Slimefun4
bugs: Reportes de Bugs bugs: Reportes de Bugs
source: Código base source: Código base
versions: Versiones instaladas
credits: credits:
commit: Contribución commit: Contribución
commits: Contribuciones commits: Contribuciones
@ -56,12 +63,18 @@ guide:
wiki: "&3Editor de Wiki" wiki: "&3Editor de Wiki"
resourcepack: "&cArtista de Resourcepack" resourcepack: "&cArtista de Resourcepack"
translator: "&9Traductor" 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: pages:
previous: Página anterior previous: Página anterior
next: Página siguiente next: Página siguiente
tooltips: tooltips:
open-category: Clic para abrir open-category: Cliquea para abrir
versions-notice: "¡Esto es muy importante cuando se reportan bugs!" versions-notice: "¡Esto es muy importante cuando se reportan bugs!"
wiki: Ve este objeto en la wiki oficial de Slimefun wiki: Ve este objeto en la wiki oficial de Slimefun
recipes: recipes:
@ -78,6 +91,7 @@ guide:
- Para desbloquear esta categoría deberás - Para desbloquear esta categoría deberás
- desbloquear todos los objetos de las - desbloquear todos los objetos de las
- siguientes categorías - siguientes categorías
work-in-progress: "¡¡¡Esta característica no está completamente terminada todavía!!"
messages: messages:
not-researched: "&4No tienes conocimiento suficiente para entender esto." not-researched: "&4No tienes conocimiento suficiente para entender esto."
not-enough-xp: "&4No tienes suficiente XP para desbloquear 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!" 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"' give-research: '&bLe has dado a %player% la investigación &7"%research%&7"'
hungry: "&c¡Tienes demasiada hambre para hacer eso!" 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-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?" 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..." 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!" - "&7¡Siempre mira el lado bueno de la vida!"
- "&7Esta era un bizcocho y no una galleta" - "&7Esta era un bizcocho y no una galleta"
- "&7¡Los signos de neón son lo MEJOR!" - "&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: machines:
pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca
el objeto en el patrón correcto dentro del dispensador." el objeto en el patrón correcto dentro del dispensador."
@ -186,7 +213,7 @@ machines:
invulnerability: "&b&l¡Tienes 30 segundos de invulnerabilidad!" invulnerability: "&b&l¡Tienes 30 segundos de invulnerabilidad!"
gui: gui:
title: Tus waypoints title: Tus waypoints
tooltip: Click para teletransportarte tooltip: Cliquea para teletransportarte
time: Tiempo estimado time: Tiempo estimado
CARGO_NODES: CARGO_NODES:
must-be-placed: "&4¡Tiene que ponerse sobre un cofre o máquina!" must-be-placed: "&4¡Tiene que ponerse sobre un cofre o máquina!"
@ -218,6 +245,7 @@ gps:
códigos de color!)" códigos de color!)"
added: "&aNuevo waypoint agregado exitosamente." added: "&aNuevo waypoint agregado exitosamente."
max: "&4Has alcanzado el máximo número de waypoints permitidos." max: "&4Has alcanzado el máximo número de waypoints permitidos."
duplicate: "&4Ya has creado un waypoint llamado: &f%waypoint%"
insufficient-complexity: insufficient-complexity:
- "&4Complejidad de red GPS insuficiente: &c%complexity%" - "&4Complejidad de red GPS insuficiente: &c%complexity%"
- "&4a) No tienes una red GPS armada aún." - "&4a) No tienes una red GPS armada aún."
@ -291,8 +319,6 @@ languages:
zh-CN: Chino (China) zh-CN: Chino (China)
el: Griego el: Griego
he: Hebreo he: Hebreo
pt: Portugués (Portugal)
pt-BR: Portugués (Brasil)
ar: Árabe ar: Árabe
af: Africano af: Africano
da: Danés da: Danés
@ -304,6 +330,8 @@ languages:
fa: Persa fa: Persa
th: Tailandés th: Tailandés
ro: Rumano ro: Rumano
pt: Portugués (Portugal)
pt-BR: Portugués (Brasil)
bg: Búlgaro bg: Búlgaro
ko: Coreano ko: Coreano
tr: Turco tr: Turco
@ -312,5 +340,9 @@ languages:
sr: Serbio sr: Serbio
be: Bielorruso be: Bielorruso
tl: Tagalog 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: miner:
no-ores: "&ePerdón, ¡No encuentro ningún mineral cerca!" no-ores: "&ePerdón, ¡No encuentro ningún mineral cerca!"

View File

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

View File

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

View File

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

View File

@ -38,6 +38,12 @@ guide:
select: I-click ito upang piliin ang wikang ito. select: I-click ito upang piliin ang wikang ito.
select-default: I-click ito upang piliin ang default na wika. select-default: I-click ito upang piliin ang default na wika.
selected-language: 'Kasalukuyang pinili:' 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: title:
main: Slimefun Guide main: Slimefun Guide
settings: Mga Settings & Impormasyon settings: Mga Settings & Impormasyon
@ -77,6 +83,7 @@ guide:
- Upang i-unlock ang kategoryang ito, - Upang i-unlock ang kategoryang ito,
- kailangang i-unlock ang lahat ng mga item mula sa - kailangang i-unlock ang lahat ng mga item mula sa
- sumusunod na kategorya. - sumusunod na kategorya.
work-in-progress: Ang feature na ito ay hindi pa tapos!
messages: messages:
not-researched: "&4Kulang ang iyong Knowledge upang ito'y maintindihan." not-researched: "&4Kulang ang iyong Knowledge upang ito'y maintindihan."
not-enough-xp: "&4Kulang ang iyong XP upang ito'y ma-unlock." 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!" not-valid-research: "&4%research% &cay hindi valid na Research!"
give-research: '&bBinigyan mo si %player% ng Research &7"%research%&7"' give-research: '&bBinigyan mo si %player% ng Research &7"%research%&7"'
hungry: "&cIkaw ay sobrang gutom para gawin ito!" 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-in-world: "&4&lDinisable ang Aytem sa world na ito."
disabled-item: "&4&lDinisable ang Aytem na ito! Paano mo ito nakuha?" 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..." 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!" wrong-world: "&cAng iyong angkla ay tila nasa ibang mundo!"
distance: "&7Measurement taken. &eDistansiya: %distance%" distance: "&7Measurement taken. &eDistansiya: %distance%"
anchor-set: "&aMatagumpay na na-set ang angla:&e %anchor%" 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: machines:
pattern-not-found: "&ePasensiya na, hindi ko maintindihan ang Recipe na ito. Pakilagay pattern-not-found: "&ePasensiya na, hindi ko maintindihan ang Recipe na ito. Pakilagay
ang mga Aytem sa tamang pattern sa loob ng Dispense." ang mga Aytem sa tamang pattern sa loob ng Dispense."
@ -241,6 +251,7 @@ gps:
chat. &7(Supported ang Color Codes!)" chat. &7(Supported ang Color Codes!)"
added: "&aTagumpay ang pag-add ng bagong waypoint." added: "&aTagumpay ang pag-add ng bagong waypoint."
max: "&4Naabot mo na ang maximum amount ng waypoints." max: "&4Naabot mo na ang maximum amount ng waypoints."
duplicate: "&4Nakagawa ka na ng isang waypoint na pinangalanan: & f%waypoint%"
insufficient-complexity: insufficient-complexity:
- "&4Kulang ang GPS Network Complexity: &c%complexity%" - "&4Kulang ang GPS Network Complexity: &c%complexity%"
- "&4a) Wala ka pang GPS Network setup." - "&4a) Wala ka pang GPS Network setup."
@ -334,3 +345,7 @@ languages:
sr: Serbian sr: Serbian
be: Belarusian be: Belarusian
tl: Tagalog/Filipino 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: Bu dili seçmek için tıklayın
select-default: Varsayılan 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:' 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: title:
main: Slimefun Rehberi main: Slimefun Rehberi
settings: Ayarlar & Bilgi settings: Ayarlar & Bilgi
@ -50,6 +56,7 @@ guide:
addons: Slimefun4 için Eklentiler addons: Slimefun4 için Eklentiler
bugs: Hata Raporları bugs: Hata Raporları
source: Kaynak Kodu source: Kaynak Kodu
versions: Yüklü sürümler
credits: credits:
commit: Geliştiirme commit: Geliştiirme
commits: Geliştirmeler commits: Geliştirmeler
@ -59,6 +66,12 @@ guide:
resourcepack: "&cKaynak Paketi Tasarımcısı" resourcepack: "&cKaynak Paketi Tasarımcısı"
translator: "&9Çevirmen" translator: "&9Çevirmen"
profile-link: GitHubdaki profillerini ziyaret etmek için tıklayın 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: pages:
previous: Önceki sayfa previous: Önceki sayfa
next: Sonraki sayfa next: Sonraki sayfa
@ -80,6 +93,7 @@ guide:
- Bu kategoriyi açmak için - Bu kategoriyi açmak için
- aşağıdaki kategorilerde bulunan - aşağıdaki kategorilerde bulunan
- bütün eşyalarıın - bütün eşyalarıın
work-in-progress: Bu özellik henüz tamamlanmadı!
messages: messages:
not-researched: "&4Bunu anlayacak kadar bilgin yok" not-researched: "&4Bunu anlayacak kadar bilgin yok"
not-enough-xp: "&4Bunun kilidini açmak için yeterli XP niz 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!" 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"' 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!" 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-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?" 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..." 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!" wrong-world: "&cSeçtiğiniz nokta başka bir dünyada gözüküyor!"
distance: "&7Ölçüm yapıldı. &eUzaklık: %distance%" distance: "&7Ölçüm yapıldı. &eUzaklık: %distance%"
anchor-set: "&aBaşarılı bir şekilde bir nokta seçildi:&e %anchor%" 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: machines:
pattern-not-found: "&eÜzgünüm, bu tarifi tanıyamadım. Lütfen Eşyaları Dağıtıcıya 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." 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!)" 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" added: "&aYeni bir yer noktası başarıyla eklendi"
max: "&4Maksimum yer noktası sayısına ulaştınız" 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: insufficient-complexity:
- "&4Yetersiz GPS Ağ Gücü: &c%complexity%" - "&4Yetersiz GPS Ağ Gücü: &c%complexity%"
- "&4a) Henüz bir GPS Ağı kurulumunuz yok" - "&4a) Henüz bir GPS Ağı kurulumunuz yok"
@ -318,5 +336,9 @@ languages:
sr: Sırpça sr: Sırpça
be: Belarusça be: Belarusça
tl: Tagalog 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: miner:
no-ores: "&eÜzgünüm, yakınlarda herhangi bir cevher bulamadım!" no-ores: "&eÜzgünüm, yakınlarda herhangi bir cevher bulamadım!"

View File

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

View File

@ -118,6 +118,11 @@ slimefun:
lore: lore:
- Haz este objeto tal como se muestra - Haz este objeto tal como se muestra
- usando una Refinery - usando una Refinery
barter_drop:
name: Piglin Bartering Drop
lore:
- Troca con Piglins usando
- Lingotes de Oro para obtener este objeto
minecraft: minecraft:
shaped: shaped:
name: Receta de Crafteo con forma 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 - Készítsd el ezt a Tárgyat az ábra alapján
- egy Ore Crusher segítségével - egy Ore Crusher segítségével
mob_drop: mob_drop:
name: Mob Drop name: Élőlény Dobja
lore: lore:
- Öld meg ezt az Élőlényt, - Öld meg ezt az Élőlényt,
- hogy megszerezd ezt a tárgyat - hogy megszerezd ezt a tárgyat
@ -118,6 +118,11 @@ slimefun:
lore: lore:
- Készítsd el ezt a Tárgyat az ábra alapján - Készítsd el ezt a Tárgyat az ábra alapján
- egy Refinery segítségével - 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: minecraft:
shaped: shaped:
name: Barkácsrecept Forma name: Barkácsrecept Forma

View File

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

View File

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

View File

@ -236,3 +236,7 @@ slimefun:
advanced_industrial_miner: Minería Mejorada advanced_industrial_miner: Minería Mejorada
magical_zombie_pills: De-Zombificación magical_zombie_pills: De-Zombificación
auto_brewer: Alquimia Industrial 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
@ -22,7 +23,7 @@ import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestBackpackCommand { class TestBackpackCommand {
private static ServerMock server; private static ServerMock server;
@ -52,7 +53,8 @@ public class TestBackpackCommand {
} }
@Test @Test
public void testValidBackpack() throws InterruptedException { @DisplayName("Test /sf backpack giving a restored backpack")
void testValidBackpack() throws InterruptedException {
Player player = server.addPlayer(); Player player = server.addPlayer();
player.setOp(true); player.setOp(true);
PlayerProfile profile = TestUtilities.awaitProfile(player); PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -64,8 +66,9 @@ public class TestBackpackCommand {
} }
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = { "ABC", "-100", "123456789" }) @DisplayName("Test /sf backpack with invalid id parameters")
public void testNonExistantBackpacks(String id) throws InterruptedException { @ValueSource(strings = { "", " ", "ABC", "-100", "123456789" })
void testNonExistentBackpacks(String id) throws InterruptedException {
Player player = server.addPlayer(); Player player = server.addPlayer();
player.setOp(true); player.setOp(true);
TestUtilities.awaitProfile(player); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
@ -13,7 +14,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestDebugFishCommand { class TestDebugFishCommand {
private static ServerMock server; private static ServerMock server;
@ -30,7 +31,8 @@ public class TestDebugFishCommand {
@ParameterizedTest @ParameterizedTest
@ValueSource(booleans = { true, false }) @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 player = server.addPlayer();
player.setOp(op); player.setOp(op);
server.execute("slimefun", player, "debug_fish").assertSucceeded(); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
@ -15,7 +16,7 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
public class TestGuideCommand { class TestGuideCommand {
private static ServerMock server; private static ServerMock server;
@ -31,8 +32,9 @@ public class TestGuideCommand {
} }
@ParameterizedTest @ParameterizedTest
@DisplayName("Test if Slimefun Guide is given on /sf guide")
@ValueSource(booleans = { true, false }) @ValueSource(booleans = { true, false })
public void testCommand(boolean op) { void testCommand(boolean op) {
Player player = server.addPlayer(); Player player = server.addPlayer();
player.setOp(op); player.setOp(op);
server.execute("slimefun", player, "guide").assertSucceeded(); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit; 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.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
public class TestBookSlimefunGuide { class TestBookSlimefunGuide {
@BeforeAll @BeforeAll
public static void load() { public static void load() {
@ -24,7 +25,8 @@ public class TestBookSlimefunGuide {
} }
@Test @Test
public void testBasicGetters() { @DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
BookSlimefunGuide guide = new BookSlimefunGuide(); BookSlimefunGuide guide = new BookSlimefunGuide();
Assertions.assertEquals(SlimefunGuideLayout.BOOK, guide.getLayout()); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit; 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.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
public class TestChestSlimefunGuide { class TestChestSlimefunGuide {
@BeforeAll @BeforeAll
public static void load() { public static void load() {
@ -24,7 +25,8 @@ public class TestChestSlimefunGuide {
} }
@Test @Test
public void testBasicGetters() { @DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
ChestSlimefunGuide guide = new ChestSlimefunGuide(false); ChestSlimefunGuide guide = new ChestSlimefunGuide(false);
Assertions.assertEquals(SlimefunGuideLayout.CHEST, guide.getLayout()); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> { class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> {
private static ServerMock server; private static ServerMock server;
private static SlimefunPlugin plugin; private static SlimefunPlugin plugin;
@ -42,7 +43,8 @@ public class TestEnderBackpack implements SlimefunItemTest<EnderBackpack> {
} }
@Test @Test
public void testRightClickBehaviour() { @DisplayName("Test Ender Backpack opening Enderchest")
void testRightClickBehaviour() {
Player player = server.addPlayer(); Player player = server.addPlayer();
EnderBackpack backpack = registerSlimefunItem(plugin, "TEST_ENDER_BACKPACK"); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.MockBukkit;
@ -45,7 +44,6 @@ public class TestDietCookie implements SlimefunItemTest<DietCookie> {
} }
@Test @Test
@Disabled("Potion Effects are currently not fully implemented in MockBukkit")
public void testConsumptionBehaviour() { public void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer(); PlayerMock player = server.addPlayer();
DietCookie cookie = registerSlimefunItem(plugin, "TEST_DIET_COOKIE"); 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.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.MockBukkit;
@ -44,7 +43,6 @@ public class TestMonsterJerky implements SlimefunItemTest<MonsterJerky> {
} }
@Test @Test
@Disabled("Potion Effects are currently not fully implemented in MockBukkit")
public void testConsumptionBehaviour() { public void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer(); PlayerMock player = server.addPlayer();
player.addPotionEffect(PotionEffectType.HUNGER.createEffect(20, 2)); 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