diff --git a/.github/configs/yaml-linter.yml b/.github/configs/yaml-linter.yml
index 90060a83c..3f056f2a1 100644
--- a/.github/configs/yaml-linter.yml
+++ b/.github/configs/yaml-linter.yml
@@ -6,10 +6,13 @@ yaml-files:
rules:
- ## A warning is sufficient here
- line-length:
- max: 180
- level: warning
+ ## Don't warn for line lengths
+ line-length: disable
+
+ truthy:
+ allowed-values: ['true', 'false']
+ ## We don't want it to trigger for the 'on' in our workflows
+ check-keys: false
## We don't need indentation warnings
indentation: disable
diff --git a/.github/workflows/maven-compiler.yml b/.github/workflows/maven-compiler.yml
index 1e041876b..9b02b166c 100644
--- a/.github/workflows/maven-compiler.yml
+++ b/.github/workflows/maven-compiler.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v1
+ uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@master
with:
diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml
index 20e965f91..d9c720087 100644
--- a/.github/workflows/update-changelog.yml
+++ b/.github/workflows/update-changelog.yml
@@ -16,7 +16,7 @@ jobs:
steps:
- name: TOC Generator
- uses: technote-space/toc-generator@v2.4.0
+ uses: technote-space/toc-generator@v2.6.1
with:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
TARGET_PATHS: 'CHANGELOG.md'
diff --git a/.github/workflows/url-checker.yml b/.github/workflows/url-checker.yml
index 523248f00..42483c750 100644
--- a/.github/workflows/url-checker.yml
+++ b/.github/workflows/url-checker.yml
@@ -6,7 +6,7 @@ on:
- master
jobs:
- build:
+ check:
name: URL Checker
runs-on: ubuntu-latest
@@ -17,7 +17,7 @@ jobs:
with:
git_path: https://github.com/Slimefun/Slimefun4
file_types: .md,.java,.yml
- print_all: False
+ 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,https://gitlocalize.com/repo/3841
diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml
index 00f94e27c..2c34456f9 100644
--- a/.github/workflows/yaml-linter.yml
+++ b/.github/workflows/yaml-linter.yml
@@ -16,8 +16,8 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v1
+ uses: actions/checkout@v2
- name: YAML Linter
- uses: ibiqlik/action-yamllint@v1.0.0
+ uses: ibiqlik/action-yamllint@v2.0.0
with:
config_file: '.github/configs/yaml-linter.yml'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ea71ada5..35cbdb690 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,8 @@
**Table of contents**
-- [Release Candidate 17 (TBD)](#release-candidate-17-tbd)
+- [Release Candidate 18 (TBD)](#release-candidate-18-tbd)
+- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020)
- [Release Candidate 16 (07 Sep 2020)](#release-candidate-16-07-sep-2020)
- [Release Candidate 15 (01 Aug 2020)](#release-candidate-15-01-aug-2020)
- [Release Candidate 14 (12 Jul 2020)](#release-candidate-14-12-jul-2020)
@@ -22,7 +23,33 @@
-## Release Candidate 17 (TBD)
+## Release Candidate 18 (TBD)
+
+#### Additions
+
+#### Changes
+* Removed 1.13 support
+* Cooling Units can no longer be placed down
+* Heating Coils can no longer be placed down
+* Electric Motors can no longer be placed down
+* Cargo Motors can no longer be placed down
+* Magnets can no longer be placed down
+* Electromagnets can no longer be placed down
+
+#### Fixes
+* Fixed #2448
+* Fixed #2470
+* Fixed #2478
+* Fixed #2493
+* Fixed a missing slot in the contributors menu
+* Fixed color codes in script downloading screen
+* Fixed #2505
+* Fixed contributors not showing correctly
+* Fixed #2469
+* Fixed #2509
+* Fixed #2499
+
+## Release Candidate 17 (17 Oct 2020)
#### Additions
* Added /sf charge
@@ -40,6 +67,10 @@
* (API) Added custom tags for developers
* The range of the Seeker Pickaxe is now configurable
* Added Energy Connector
+* Blackstone can now be turned into lava using a Crucible
+* Basalt can now be turned into lava using a Crucible
+* Added "Tainted Sheep" (You can dye a Sheep using Strange Nether Goo)
+* Added mcMMO support/integration
#### Changes
* Improved Auto-Updater (Multi-Threading and more)
@@ -81,6 +112,14 @@
* Fixed #2450
* Fixed Steel Thrusters being used to milk cows
* Fixed #2424
+* Fixed #2468
+* Fixed #2414
+* Fixed #2454
+* Fixed #2457
+* Fixed #2411
+* Fixed #2423
+* Fixed #2452
+* Fixed a dupe bug with mcMMO
## Release Candidate 16 (07 Sep 2020)
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#16
diff --git a/README.md b/README.md
index 80f30248b..f531b510d 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ Here is a full summary of the differences between the two different versions of
| | development (latest) | "stable" |
| ------------------ | -------- | -------- |
-| **Minecraft version(s)** | :video_game: **1.13.\* - 1.16.\*** | :video_game: **1.13.\* - 1.16.\*** |
+| **Minecraft version(s)** | :video_game: **1.14.\* - 1.16.\*** | :video_game: **1.13.\* - 1.16.\*** |
| **automatic updates** | :heavy_check_mark: | :heavy_check_mark: |
| **frequent updates** | :heavy_check_mark: | :x: |
| **latest content** | :heavy_check_mark: | :x: |
diff --git a/pom.xml b/pom.xml
index 217f7b2a1..0073cdbbc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,10 @@
worldedit-repo
https://maven.sk89q.com/repo/
+
+ codemc-repo
+ https://repo.codemc.org/repository/maven-public
+
placeholderapi-repo
https://repo.extendedclip.com/content/repositories/placeholderapi/
@@ -311,7 +315,7 @@
com.github.seeseemelk
MockBukkit-v1.16
- 0.10.2
+ 0.13.0
test
@@ -325,7 +329,7 @@
org.mockito
mockito-core
- 3.5.13
+ 3.6.0
test
@@ -345,7 +349,7 @@
com.konghq
unirest-java
- 3.11.01
+ 3.11.02
compile
@@ -368,6 +372,32 @@
de.schlichtherle
truezip
+
+ net.java.truevfs
+ truevfs-profile-default_2.13
+
+
+
+
+ com.gmail.nossr50.mcMMO
+ mcMMO
+ 2.1.150
+ provided
+
+
+
+
+ org.jetbrains
+ annotations
+
+
+ com.sk89q.worldguard
+ worldguard-core
+
+
+ com.sk89q.worldguard
+ worldguard-legacy
+
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java
index 9cb5793b9..3f49247a9 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java
@@ -14,12 +14,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
*/
public enum MinecraftVersion {
- /**
- * This constant represents Minecraft (Java Edition) Version 1.14
- * (The Update Aquatic)
- */
- MINECRAFT_1_13("1.13.x"),
-
/**
* This constant represents Minecraft (Java Edition) Version 1.14
* (The "Village & Pillage" Update)
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
index ae85b19ab..538a1dc49 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
@@ -22,14 +22,12 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.collections.KeyMap;
import io.github.thebusybiscuit.cscorelib2.config.Config;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
@@ -100,7 +98,7 @@ public final class SlimefunRegistry {
researchRanks.addAll(cfg.getStringList("research-ranks"));
- backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility") || SlimefunPlugin.getMinecraftVersion().isBefore(MinecraftVersion.MINECRAFT_1_14);
+ backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility");
freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode");
researchFireworks = cfg.getBoolean("researches.enable-fireworks");
logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries");
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java
index f19af55a5..b0e47b1a5 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java
@@ -13,7 +13,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import net.md_5.bungee.api.ChatColor;
@@ -39,9 +38,7 @@ final class RechargeableHelper {
BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP);
float value = decimal.floatValue();
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value);
- }
+ meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value);
List lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < lore.size(); i++) {
@@ -59,13 +56,11 @@ final class RechargeableHelper {
}
static float getCharge(@Nonnull ItemMeta meta) {
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT);
+ Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT);
- // If persistent data is available, we just return this value
- if (value != null) {
- return value;
- }
+ // If persistent data is available, we just return this value
+ if (value != null) {
+ return value;
}
// If no persistent data exists, we will just fall back to the lore
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/ContributorsMenu.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/ContributorsMenu.java
index df5d74cf0..5ed9c6918 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/ContributorsMenu.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/ContributorsMenu.java
@@ -37,7 +37,7 @@ final class ContributorsMenu {
menu.setEmptySlotsClickable(false);
menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.BLOCK_NOTE_BLOCK_HARP, 0.7F, 0.7F));
- ChestMenuUtils.drawBackground(menu, 0, 2, 3, 4, 5, 6, 7, 8, 45, 47, 48, 49, 50, 51, 52);
+ ChestMenuUtils.drawBackground(menu, 0, 2, 3, 4, 5, 6, 7, 8, 45, 47, 48, 49, 50, 51, 53);
menu.addItem(1, new CustomItem(ChestMenuUtils.getBackButton(p, "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.settings"))));
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
index 7c132d44f..1ed862a13 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
@@ -12,7 +12,6 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
@@ -41,11 +40,8 @@ public final class SlimefunGuideSettings {
static {
options.add(new GuideLayoutOption());
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- options.add(new FireworksOption());
- options.add(new PlayerLanguageOption());
- }
+ options.add(new FireworksOption());
+ options.add(new PlayerLanguageOption());
}
private SlimefunGuideSettings() {}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java
index 61d96ebf9..49b80dd9a 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java
@@ -41,10 +41,8 @@ public class MultiBlock {
SUPPORTED_TAGS.add(Tag.LOGS);
SUPPORTED_TAGS.add(Tag.WOODEN_TRAPDOORS);
SUPPORTED_TAGS.add(Tag.WOODEN_SLABS);
+ SUPPORTED_TAGS.add(Tag.WOODEN_FENCES);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- SUPPORTED_TAGS.add(Tag.WOODEN_FENCES);
- }
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
SUPPORTED_TAGS.add(Tag.FIRE);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java
index 81c8051c2..b7e5fabab 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java
@@ -18,10 +18,10 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
+import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@@ -54,6 +54,10 @@ final class CargoUtils {
Material type = block.getType();
+ if (SlimefunTag.SHULKER_BOXES.isTagged(type)) {
+ return true;
+ }
+
switch (type) {
case CHEST:
case TRAPPED_CHEST:
@@ -62,28 +66,13 @@ final class CargoUtils {
case DROPPER:
case HOPPER:
case BREWING_STAND:
- case SHULKER_BOX:
+ case BARREL:
+ case BLAST_FURNACE:
+ case SMOKER:
return true;
default:
- break;
+ return false;
}
-
- if (type.name().endsWith("_SHULKER_BOX")) {
- return true;
- }
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- switch (type) {
- case BARREL:
- case BLAST_FURNACE:
- case SMOKER:
- return true;
- default:
- break;
- }
- }
-
- return false;
}
static int[] getInputSlotRange(@Nonnull Inventory inv, @Nullable ItemStack item) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java
index 9dd1449f8..14b39c042 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java
@@ -2,6 +2,10 @@ package io.github.thebusybiscuit.slimefun4.core.services;
import java.util.Optional;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang.Validate;
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@@ -11,8 +15,8 @@ import org.bukkit.block.TileState;
import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.plugin.Plugin;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.papermc.lib.PaperLib;
+import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
/**
* The {@link BlockDataService} is similar to the {@link CustomItemDataService},
@@ -27,7 +31,17 @@ public class BlockDataService implements PersistentDataService, Keyed {
private final NamespacedKey namespacedKey;
- public BlockDataService(Plugin plugin, String key) {
+ /**
+ * This creates a new {@link BlockDataService} for the given {@link Plugin}.
+ * The {@link Plugin} and key will together form a {@link NamespacedKey} used to store
+ * data on a {@link TileState}.
+ *
+ * @param plugin
+ * The {@link Plugin} responsible for this service
+ * @param key
+ * The key under which to store data
+ */
+ public BlockDataService(@Nonnull Plugin plugin, @Nonnull String key) {
namespacedKey = new NamespacedKey(plugin, key);
}
@@ -44,12 +58,19 @@ public class BlockDataService implements PersistentDataService, Keyed {
* @param value
* The value to store
*/
- public void setBlockData(Block b, String value) {
- BlockState state = b.getState();
+ public void setBlockData(@Nonnull Block b, @Nonnull String value) {
+ Validate.notNull(b, "The block cannot be null!");
+ Validate.notNull(value, "The value cannot be null!");
+
+ BlockStateSnapshotResult result = PaperLib.getBlockState(b, false);
+ BlockState state = result.getState();
if (state instanceof TileState) {
setString((TileState) state, namespacedKey, value);
- state.update();
+
+ if (result.isSnapshot()) {
+ state.update();
+ }
}
}
@@ -60,8 +81,10 @@ public class BlockDataService implements PersistentDataService, Keyed {
* The {@link Block} to retrieve data from
* @return The stored value
*/
- public Optional getBlockData(Block b) {
- BlockState state = b.getState();
+ public Optional getBlockData(@Nonnull Block b) {
+ Validate.notNull(b, "The block cannot be null!");
+
+ BlockState state = PaperLib.getBlockState(b, false).getState();
if (state instanceof TileState) {
return getString((TileState) state, namespacedKey);
@@ -80,12 +103,12 @@ public class BlockDataService implements PersistentDataService, Keyed {
*
* @param type
* The {@link Material} to check for
+ *
* @return Whether the given {@link Material} is considered a Tile Entity
*/
- public boolean isTileEntity(Material type) {
- if (type == null || !SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- // We can only store data on Tile Entities in 1.14+
- // So we will just return false here in that case.
+ public boolean isTileEntity(@Nullable Material type) {
+ if (type == null || type.isAir()) {
+ // Cannot store data on air
return false;
}
@@ -108,10 +131,12 @@ public class BlockDataService implements PersistentDataService, Keyed {
case BARREL:
case SPAWNER:
case BEACON:
+ // All of the above Materials are Tile Entities
return true;
default:
+ // Otherwise we assume they're not Tile Entities
return false;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomItemDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomItemDataService.java
index b2ca07a7c..aed4e5d3e 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomItemDataService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomItemDataService.java
@@ -2,6 +2,10 @@ package io.github.thebusybiscuit.slimefun4.core.services;
import java.util.Optional;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang.Validate;
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@@ -35,7 +39,7 @@ public class CustomItemDataService implements PersistentDataService, Keyed {
* @param key
* The key under which to store data
*/
- public CustomItemDataService(Plugin plugin, String key) {
+ public CustomItemDataService(@Nonnull Plugin plugin, @Nonnull String key) {
// Null-Validation is performed in the NamespacedKey constructor
namespacedKey = new NamespacedKey(plugin, key);
}
@@ -45,13 +49,37 @@ public class CustomItemDataService implements PersistentDataService, Keyed {
return namespacedKey;
}
- public void setItemData(ItemStack item, String id) {
+ /**
+ * This method stores the given id on the provided {@link ItemStack} via
+ * persistent data.
+ *
+ * @param item
+ * The {@link ItemStack} to store data on
+ * @param id
+ * The id to store on the {@link ItemStack}
+ */
+ public void setItemData(@Nonnull ItemStack item, @Nonnull String id) {
+ Validate.notNull(item, "The Item cannot be null!");
+ Validate.notNull(id, "Cannot store null on an Item!");
+
ItemMeta im = item.getItemMeta();
setItemData(im, id);
item.setItemMeta(im);
}
- public void setItemData(ItemMeta im, String id) {
+ /**
+ * This method stores the given id on the provided {@link ItemMeta} via
+ * persistent data.
+ *
+ * @param im
+ * The {@link ItemMeta} to store data on
+ * @param id
+ * The id to store on the {@link ItemMeta}
+ */
+ public void setItemData(@Nonnull ItemMeta im, @Nonnull String id) {
+ Validate.notNull(im, "The ItemMeta cannot be null!");
+ Validate.notNull(id, "Cannot store null on an ItemMeta!");
+
setString(im, namespacedKey, id);
}
@@ -65,7 +93,8 @@ public class CustomItemDataService implements PersistentDataService, Keyed {
*
* @return An {@link Optional} describing the result
*/
- public Optional getItemData(ItemStack item) {
+ @Nonnull
+ public Optional getItemData(@Nullable ItemStack item) {
if (item == null || item.getType() == Material.AIR || !item.hasItemMeta()) {
return Optional.empty();
}
@@ -82,7 +111,10 @@ public class CustomItemDataService implements PersistentDataService, Keyed {
*
* @return An {@link Optional} describing the result
*/
- public Optional getItemData(ItemMeta meta) {
+ @Nonnull
+ public Optional getItemData(@Nonnull ItemMeta meta) {
+ Validate.notNull(meta, "Cannot read data from null!");
+
return getString(meta, namespacedKey);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java
index b94cecf1d..3caea1cbb 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java
@@ -10,8 +10,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.config.Config;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@@ -30,6 +28,12 @@ public class CustomTextureService {
private String version = null;
private boolean modified = false;
+ /**
+ * This creates a new {@link CustomTextureService} for the provided {@link Config}
+ *
+ * @param config
+ * The {@link Config} to read custom model data from
+ */
public CustomTextureService(@Nonnull Config config) {
this.config = config;
config.getConfiguration().options().header("This file is used to assign items from Slimefun or any of its addons\n" + "the 'CustomModelData' NBT tag. This can be used in conjunction with a custom resource pack\n" + "to give items custom textures.\n0 means there is no data assigned to that item.\n\n" + "There is no official Slimefun resource pack at the moment.");
@@ -51,6 +55,8 @@ public class CustomTextureService {
config.setDefaultValue("SLIMEFUN_GUIDE", 0);
config.setDefaultValue("_UI_BACKGROUND", 0);
+ config.setDefaultValue("_UI_NO_PERMISSION", 0);
+ config.setDefaultValue("_UI_NOT_RESEARCHED", 0);
config.setDefaultValue("_UI_INPUT_SLOT", 0);
config.setDefaultValue("_UI_OUTPUT_SLOT", 0);
config.setDefaultValue("_UI_BACK", 0);
@@ -84,27 +90,62 @@ public class CustomTextureService {
return version;
}
+ /**
+ * This returns true if any custom model data was configured.
+ * If every item id has no configured custom model data, it will return false.
+ *
+ * @return Whether any custom model data was configured
+ */
public boolean isActive() {
return modified;
}
+ /**
+ * This returns the configured custom model data for a given id.
+ *
+ * @param id
+ * The id to get the data for
+ *
+ * @return The configured custom model data
+ */
public int getModelData(@Nonnull String id) {
Validate.notNull(id, "Cannot get the ModelData for 'null'");
return config.getInt(id);
}
+ /**
+ * This method sets the custom model data for this {@link ItemStack}
+ * to the value configured for the provided item id.
+ *
+ * @param item
+ * The {@link ItemStack} to set the custom model data for
+ * @param id
+ * The id for which to get the configured model data
+ */
public void setTexture(@Nonnull ItemStack item, @Nonnull String id) {
+ Validate.notNull(item, "The Item cannot be null!");
+ Validate.notNull(id, "Cannot store null on an Item!");
+
ItemMeta im = item.getItemMeta();
setTexture(im, id);
item.setItemMeta(im);
}
+ /**
+ * This method sets the custom model data for this {@link ItemMeta}
+ * to the value configured for the provided item id.
+ *
+ * @param im
+ * The {@link ItemMeta} to set the custom model data for
+ * @param id
+ * The id for which to get the configured model data
+ */
public void setTexture(@Nonnull ItemMeta im, @Nonnull String id) {
- int data = getModelData(id);
+ Validate.notNull(im, "The ItemMeta cannot be null!");
+ Validate.notNull(id, "Cannot store null on an ItemMeta!");
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- im.setCustomModelData(data == 0 ? null : data);
- }
+ int data = getModelData(id);
+ im.setCustomModelData(data == 0 ? null : data);
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java
index 5835e9f86..74ddcd2e1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java
@@ -34,9 +34,26 @@ import kong.unirest.UnirestException;
*/
public class MetricsService {
+ /**
+ * The URL pointing towards the GitHub API.
+ */
private static final String API_URL = "https://api.github.com/";
+
+ /**
+ * The Name of our repository
+ */
private static final String REPO_NAME = "MetricsModule";
+
+ /**
+ * The URL pointing towards the /releases/ endpoint of our
+ * Metrics repository
+ */
private static final String RELEASES_URL = API_URL + "repos/Slimefun/" + REPO_NAME + "/releases/latest";
+
+ /**
+ * The URL pointing towards the download location for a
+ * GitHub release of our Metrics repository
+ */
private static final String DOWNLOAD_URL = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private final SlimefunPlugin plugin;
@@ -48,9 +65,22 @@ public class MetricsService {
private boolean hasDownloadedUpdate = false;
static {
- Unirest.config().concurrency(2, 1).setDefaultHeader("User-Agent", "MetricsModule Auto-Updater").setDefaultHeader("Accept", "application/vnd.github.v3+json").enableCookieManagement(false).cookieSpec("ignoreCookies");
+ // @formatter:off (We want this to stay this nicely aligned :D )
+ Unirest.config()
+ .concurrency(2, 1)
+ .setDefaultHeader("User-Agent", "MetricsModule Auto-Updater")
+ .setDefaultHeader("Accept", "application/vnd.github.v3+json")
+ .enableCookieManagement(false)
+ .cookieSpec("ignoreCookies");
+ // @formatter:on
}
+ /**
+ * This constructs a new instance of our {@link MetricsService}.
+ *
+ * @param plugin
+ * Our {@link SlimefunPlugin} instance
+ */
public MetricsService(@Nonnull SlimefunPlugin plugin) {
this.plugin = plugin;
this.parentFolder = new File(plugin.getDataFolder(), "cache" + File.separatorChar + "modules");
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java
index 8a1035d74..b1792f546 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java
@@ -7,32 +7,29 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.persistence.PersistentDataType;
+import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This interface is used to defer calls to Persistent Data and make sure they are only called
* if the {@link MinecraftVersion} supports it.
*
* @author TheBusyBiscuit
+ *
+ * @deprecated This is redundant, we can use {@link PersistentDataAPI} instead.
*
*/
+@Deprecated
interface PersistentDataService {
default void setString(Object obj, NamespacedKey key, String value) {
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && obj instanceof PersistentDataHolder) {
- PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer();
- container.set(key, PersistentDataType.STRING, value);
- }
+ PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer();
+ container.set(key, PersistentDataType.STRING, value);
}
default Optional getString(Object obj, NamespacedKey key) {
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && obj instanceof PersistentDataHolder) {
- PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer();
- return Optional.ofNullable(container.get(key, PersistentDataType.STRING));
- }
-
- return Optional.empty();
+ PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer();
+ return Optional.ofNullable(container.get(key, PersistentDataType.STRING));
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
index f38e0c035..3d2368cea 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
@@ -16,11 +16,28 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
class ContributionsConnector extends GitHubConnector {
- // GitHub Bots that do not count as Contributors
- // (includes "invalid-email-address" because it is an invalid contributor)
- private static final List blacklist = Arrays.asList("invalid-email-address", "renovate-bot", "TheBusyBot", "ImgBotApp", "imgbot", "imgbot[bot]", "github-actions[bot]", "gitlocalize-app", "gitlocalize-app[bot]", "mt-gitlocalize");
+ /*
+ * @formatter:off
+ * GitHub Bots that do not count as Contributors
+ * (includes "invalid-email-address" because it is an invalid contributor)
+ */
+ private static final List blacklist = Arrays.asList(
+ "invalid-email-address",
+ "renovate-bot",
+ "TheBusyBot",
+ "ImgBotApp",
+ "imgbot",
+ "imgbot[bot]",
+ "github-actions[bot]",
+ "gitlocalize-app",
+ "gitlocalize-app[bot]",
+ "mt-gitlocalize"
+ );
- // Matches a GitHub name with a Minecraft name.
+ /*
+ * @formatter:on
+ * Matches a GitHub name with a Minecraft name.
+ */
private static final Map aliases = new HashMap<>();
// Should probably be switched to UUIDs at some point...
@@ -82,8 +99,16 @@ class ContributionsConnector extends GitHubConnector {
}
@Override
- public String getURLSuffix() {
- return "/contributors?per_page=100&page=" + page;
+ public String getEndpoint() {
+ return "/contributors";
+ }
+
+ @Override
+ public Map getParameters() {
+ Map parameters = new HashMap<>();
+ parameters.put("per_page", 100);
+ parameters.put("page", page);
+ return parameters;
}
private void computeContributors(@Nonnull JSONArray array) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubActivityConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubActivityConnector.java
index e55fc722e..33b6d23e1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubActivityConnector.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubActivityConnector.java
@@ -1,6 +1,8 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -35,8 +37,13 @@ class GitHubActivityConnector extends GitHubConnector {
}
@Override
- public String getURLSuffix() {
+ public String getEndpoint() {
return "";
}
+ @Override
+ public Map getParameters() {
+ return new HashMap<>();
+ }
+
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java
index 0f9e3e317..e06e00129 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java
@@ -6,12 +6,13 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.URL;
import java.nio.charset.StandardCharsets;
+import java.util.Map;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
@@ -31,22 +32,49 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
abstract class GitHubConnector {
private static final String API_URL = "https://api.github.com/";
+ private static final String USER_AGENT = "Slimefun4 (https://github.com/Slimefun)";
- protected File file;
- protected String repository;
protected final GitHubService github;
+ private final String url;
+ private File file;
- @ParametersAreNonnullByDefault
- public GitHubConnector(GitHubService github, String repository) {
+ /**
+ * This creates a new {@link GitHubConnector} for the given repository.
+ *
+ * @param github
+ * Our instance of {@link GitHubService}
+ * @param repository
+ * The repository we want to connect to
+ */
+ GitHubConnector(@Nonnull GitHubService github, @Nonnull String repository) {
this.github = github;
- this.repository = repository;
+ this.url = API_URL + "repos/" + repository + getEndpoint();
}
+ /**
+ * This returns the name of our cache {@link File}.
+ *
+ * @return The cache {@link File} name
+ */
@Nonnull
public abstract String getFileName();
+ /**
+ * This is our {@link URL} endpoint.
+ * It is the suffix of the {@link URL} we want to connect to.
+ *
+ * @return Our endpoint
+ */
@Nonnull
- public abstract String getURLSuffix();
+ public abstract String getEndpoint();
+
+ /**
+ * This {@link Map} contains the query parameters for our {@link URL}.
+ *
+ * @return A {@link Map} with our query parameters
+ */
+ @Nonnull
+ public abstract Map getParameters();
/**
* This method is called when the connection finished successfully.
@@ -63,7 +91,12 @@ abstract class GitHubConnector {
// Don't do anything by default
}
- public void pullFile() {
+ /**
+ * This method will connect to GitHub and store the received data inside a local
+ * cache {@link File}.
+ * Make sure to call this method asynchronously!
+ */
+ void download() {
file = new File("plugins/Slimefun/cache/github/" + getFileName() + ".json");
if (github.isLoggingEnabled()) {
@@ -71,16 +104,19 @@ abstract class GitHubConnector {
}
try {
- HttpResponse resp = Unirest.get(API_URL + "repos/" + repository + getURLSuffix())
- .header("User-Agent", "Slimefun4 (https://github.com/Slimefun)")
+ // @formatter:off
+ HttpResponse response = Unirest.get(url)
+ .queryString(getParameters())
+ .header("User-Agent", USER_AGENT)
.asJson();
+ // @formatter:on
- if (resp.isSuccess()) {
- onSuccess(resp.getBody());
- writeCacheFile(resp.getBody());
+ if (response.isSuccess()) {
+ onSuccess(response.getBody());
+ writeCacheFile(response.getBody());
} else {
if (github.isLoggingEnabled()) {
- Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { repository + getURLSuffix(), resp.getStatus(), resp.getBody() });
+ Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { url, response.getStatus(), response.getBody() });
}
// It has the cached file, let's just read that then
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesConnector.java
index b22d9f491..38335e529 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesConnector.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesConnector.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
+import java.util.HashMap;
+import java.util.Map;
import java.util.logging.Level;
import javax.annotation.Nonnull;
@@ -50,8 +52,15 @@ class GitHubIssuesConnector extends GitHubConnector {
}
@Override
- public String getURLSuffix() {
- return "/issues?per_page=100";
+ public String getEndpoint() {
+ return "/issues";
+ }
+
+ @Override
+ public Map getParameters() {
+ Map parameters = new HashMap<>();
+ parameters.put("per_page", 100);
+ return parameters;
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java
index b7a2fc07d..f7d103f24 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java
@@ -57,7 +57,8 @@ public class GitHubService {
}
public void start(@Nonnull SlimefunPlugin plugin) {
- plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new GitHubTask(this), 80L, 60 * 60 * 20L);
+ GitHubTask task = new GitHubTask(this);
+ plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, task, 80L, 60 * 60 * 20L);
}
/**
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java
index 932bf7060..151afa635 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java
@@ -1,5 +1,6 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
+import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -38,10 +39,14 @@ class GitHubTask implements Runnable {
@Override
public void run() {
- gitHubService.getConnectors().forEach(GitHubConnector::pullFile);
+ gitHubService.getConnectors().forEach(GitHubConnector::download);
grabTextures();
}
+ /**
+ * This method will pull the skin textures for every {@link Contributor} and store
+ * the {@link UUID} and received skin inside a local cache {@link File}.
+ */
private void grabTextures() {
// Store all queried usernames to prevent 429 responses for pinging the
// same URL twice in one run.
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java
similarity index 75%
rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java
rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java
index 3722fcfd6..212bb1f3f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java
@@ -11,11 +11,19 @@ import org.bukkit.event.Listener;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
+import me.minebuilders.clearlag.Clearlag;
import me.minebuilders.clearlag.events.EntityRemoveEvent;
-class ClearLagHook implements Listener {
+/**
+ * This handles all integrations with {@link Clearlag}.
+ * We don't want it to clear our altar items.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+class ClearLagIntegration implements Listener {
- ClearLagHook(@Nonnull SlimefunPlugin plugin) {
+ ClearLagIntegration(@Nonnull SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java
index ecd2fd7b0..486c59af8 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java
@@ -12,6 +12,7 @@ import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import me.mrCookieSlime.EmeraldEnchants.EnchantmentGuide;
+@Deprecated
class EmeraldEnchantsCategory extends FlexCategory {
public EmeraldEnchantsCategory(@Nonnull NamespacedKey key) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java
new file mode 100644
index 000000000..553627469
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java
@@ -0,0 +1,60 @@
+package io.github.thebusybiscuit.slimefun4.core.services.plugins;
+
+import javax.annotation.Nonnull;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.inventory.ItemStack;
+
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.events.skills.salvage.McMMOPlayerSalvageCheckEvent;
+
+import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This handles all integrations with {@link mcMMO}.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+class McMMOIntegration implements Listener {
+
+ McMMOIntegration(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onBlockPlacerPlace(BlockPlacerPlaceEvent e) {
+ // This registers blocks placed by the BlockPlacer as "player-placed"
+ mcMMO.getPlaceStore().setTrue(e.getBlock());
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onItemSalvage(McMMOPlayerSalvageCheckEvent e) {
+ // Prevent Slimefun items from being salvaged
+ if (!isSalvageable(e.getSalvageItem())) {
+ e.setCancelled(true);
+ SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "anvil.mcmmo-salvaging");
+ }
+ }
+
+ /**
+ * This method checks if an {@link ItemStack} can be salvaged or not.
+ * We basically don't want players to salvage any {@link SlimefunItem} unless
+ * it is a {@link VanillaItem}.
+ *
+ * @param item
+ * The {@link ItemStack} to check
+ *
+ * @return Whether this item can be safely salvaged
+ */
+ private boolean isSalvageable(@Nonnull ItemStack item) {
+ SlimefunItem sfItem = SlimefunItem.getByItem(item);
+ return sfItem == null || sfItem instanceof VanillaItem;
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java
similarity index 93%
rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java
rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java
index 892729663..d49426458 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java
@@ -13,14 +13,21 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
-class PlaceholderAPIHook extends PlaceholderExpansion {
+/**
+ * This is our integration for {@link PlaceholderAPI}.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+class PlaceholderAPIIntegration extends PlaceholderExpansion {
private final String version;
private final String author;
- public PlaceholderAPIHook(@Nonnull SlimefunPlugin plugin) {
+ public PlaceholderAPIIntegration(@Nonnull SlimefunPlugin plugin) {
this.version = plugin.getDescription().getVersion();
this.author = plugin.getDescription().getAuthors().toString();
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java
index 877aac6b1..4bf85071f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java
@@ -5,12 +5,16 @@ import java.util.function.Function;
import java.util.logging.Level;
import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
+import org.bukkit.event.Event;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
+import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
+
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@@ -31,25 +35,41 @@ public class ThirdPartyPluginService {
private final SlimefunPlugin plugin;
+ private boolean initialized = false;
private boolean isExoticGardenInstalled = false;
private boolean isChestTerminalInstalled = false;
private boolean isEmeraldEnchantsInstalled = false;
- private boolean isCoreProtectInstalled = false;
- private boolean isPlaceholderAPIInstalled = false;
+ private boolean isMcMMOInstalled = false;
- // Overridden if ExoticGarden is loaded
+ /**
+ * This gets overridden if ExoticGarden is loaded
+ */
private Function> exoticGardenIntegration = b -> Optional.empty();
+ /**
+ * This initializes the {@link ThirdPartyPluginService}
+ *
+ * @param plugin
+ * Our instance of {@link SlimefunPlugin}
+ */
public ThirdPartyPluginService(@Nonnull SlimefunPlugin plugin) {
this.plugin = plugin;
}
+ /**
+ * This method initializes all third party integrations.
+ */
public void start() {
+ if (initialized) {
+ throw new UnsupportedOperationException("Third Party Integrations have already been initialized!");
+ }
+
+ initialized = true;
+
if (isPluginInstalled("PlaceholderAPI")) {
try {
- PlaceholderAPIHook hook = new PlaceholderAPIHook(plugin);
+ PlaceholderAPIIntegration hook = new PlaceholderAPIIntegration(plugin);
hook.register();
- isPlaceholderAPIInstalled = true;
} catch (Exception | LinkageError x) {
String version = plugin.getServer().getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion();
@@ -69,7 +89,7 @@ public class ThirdPartyPluginService {
if (isPluginInstalled("WorldEdit")) {
try {
Class.forName("com.sk89q.worldedit.extent.Extent");
- new WorldEditHook();
+ new WorldEditIntegration();
} catch (Exception | LinkageError x) {
String version = plugin.getServer().getPluginManager().getPlugin("WorldEdit").getDescription().getVersion();
@@ -78,6 +98,21 @@ public class ThirdPartyPluginService {
}
}
+ // mcMMO Integration
+ if (isPluginInstalled("mcMMO")) {
+ try {
+ // This makes sure that the FakeEvent interface is present.
+ // Class.forName("com.gmail.nossr50.events.fake.FakeEvent");
+
+ new McMMOIntegration(plugin);
+ isMcMMOInstalled = true;
+ } catch (Exception | LinkageError x) {
+ String version = plugin.getServer().getPluginManager().getPlugin("mcMMO").getDescription().getVersion();
+ Slimefun.getLogger().log(Level.WARNING, "Maybe consider updating mcMMO or Slimefun?");
+ Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to hook into mcMMO v" + version);
+ }
+ }
+
/*
* These Items are not marked as soft-dependencies and
* therefore need to be loaded after the Server has finished
@@ -85,7 +120,7 @@ public class ThirdPartyPluginService {
*/
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
if (isPluginInstalled("ClearLag")) {
- new ClearLagHook(plugin);
+ new ClearLagIntegration(plugin);
}
isChestTerminalInstalled = isPluginInstalled("ChestTerminal");
@@ -101,6 +136,7 @@ public class ThirdPartyPluginService {
}
}
+ @ParametersAreNonnullByDefault
public void loadExoticGarden(Plugin plugin, Function> method) {
if (plugin.getName().equals("ExoticGarden")) {
isExoticGardenInstalled = true;
@@ -120,16 +156,22 @@ public class ThirdPartyPluginService {
return isEmeraldEnchantsInstalled;
}
- public boolean isCoreProtectInstalled() {
- return isCoreProtectInstalled;
- }
-
- public boolean isPlaceholderAPIInstalled() {
- return isPlaceholderAPIInstalled;
- }
-
public Optional harvestExoticGardenPlant(Block block) {
return exoticGardenIntegration.apply(block);
}
+ /**
+ * This checks if one of our third party integrations faked an {@link Event}.
+ * Faked {@link Event Events} should be ignored in our logic.
+ *
+ * @param event
+ * The {@link Event} to test
+ *
+ * @return Whether this is a fake event
+ */
+ public boolean isEventFaked(@Nonnull Event event) {
+ // TODO: Change this to FakeEvent once the new mcMMO build was released
+ return isMcMMOInstalled && event instanceof FakeBlockBreakEvent;
+ }
+
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java
similarity index 86%
rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java
rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java
index 3b134df92..38af34726 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java
@@ -14,9 +14,16 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
-class WorldEditHook {
+/**
+ * This handles all integrations with {@link WorldEdit}.
+ * If an are is cleared, we also wanna clear all Slimefun-related block data.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+class WorldEditIntegration {
- WorldEditHook() {
+ WorldEditIntegration() {
WorldEdit.getInstance().getEventBus().register(this);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
index 5dbbed514..ed827eae7 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
@@ -394,7 +394,7 @@ public final class SlimefunItems {
public static final SlimefunItemStack PLASTIC_SHEET = new SlimefunItemStack("PLASTIC_SHEET", Material.PAPER, "&fPlastic Sheet");
public static final SlimefunItemStack MAGNET = new SlimefunItemStack("MAGNET", HeadTexture.MAGNET, "&cMagnet");
- public static final SlimefunItemStack NECROTIC_SKULL = new SlimefunItemStack("NECROTIC_SKULL", Material.WITHER_SKELETON_SKULL, "&cNecrotic Skull");
+ public static final SlimefunItemStack NECROTIC_SKULL = new SlimefunItemStack("NECROTIC_SKULL", HeadTexture.NECROTIC_SKULL, "&cNecrotic Skull");
public static final SlimefunItemStack ESSENCE_OF_AFTERLIFE = new SlimefunItemStack("ESSENCE_OF_AFTERLIFE", Material.GUNPOWDER, "&4Essence of Afterlife");
public static final SlimefunItemStack STRANGE_NETHER_GOO = new SlimefunItemStack("STRANGE_NETHER_GOO", Material.PURPLE_DYE, "&5Strange Nether Goo", "", "&fA strange bio matter that", "&fcan be acquired from", "&fbartering with Piglins");
public static final SlimefunItemStack ELECTRO_MAGNET = new SlimefunItemStack("ELECTRO_MAGNET", HeadTexture.MAGNET, "&cElectromagnet");
@@ -569,14 +569,14 @@ public final class SlimefunItems {
public static final SlimefunItemStack ENHANCED_CRAFTING_TABLE = new SlimefunItemStack("ENHANCED_CRAFTING_TABLE", Material.CRAFTING_TABLE, "&eEnhanced Crafting Table", "", "&aA regular Crafting Table cannot", "&ahold this massive Amount of Power...");
public static final SlimefunItemStack GRIND_STONE = new SlimefunItemStack("GRIND_STONE", Material.DISPENSER, "&bGrind Stone", "", "&aGrinds items down into other items");
public static final SlimefunItemStack ARMOR_FORGE = new SlimefunItemStack("ARMOR_FORGE", Material.ANVIL, "&6Armor Forge", "", "&aGives you the ability to create powerful armor");
- public static final SlimefunItemStack MAKESHIFT_SMELTERY;
+ public static final SlimefunItemStack MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.BLAST_FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots");
public static final SlimefunItemStack SMELTERY = new SlimefunItemStack("SMELTERY", Material.FURNACE, "&6Smeltery", "", "&fA high-temperature furnace", "&fthat allows you to smelt dusts", "&finto ingots and create alloys.");
public static final SlimefunItemStack ORE_CRUSHER = new SlimefunItemStack("ORE_CRUSHER", Material.DISPENSER, "&bOre Crusher", "", "&aCrushes ores to double them");
public static final SlimefunItemStack COMPRESSOR = new SlimefunItemStack("COMPRESSOR", Material.PISTON, "&bCompressor", "", "&aCompresses Items");
public static final SlimefunItemStack PRESSURE_CHAMBER = new SlimefunItemStack("PRESSURE_CHAMBER", Material.GLASS, "&bPressure Chamber", "", "&aCompresses Items even further");
public static final SlimefunItemStack MAGIC_WORKBENCH = new SlimefunItemStack("MAGIC_WORKBENCH", Material.CRAFTING_TABLE, "&6Magic Workbench", "", "&dInfuses Items with magical Energy");
public static final SlimefunItemStack ORE_WASHER = new SlimefunItemStack("ORE_WASHER", Material.CAULDRON, "&6Ore Washer", "", "&aWashes Sifted Ore to filter Ores", "&aand gives you small Stone Chunks");
- public static final SlimefunItemStack TABLE_SAW;
+ public static final SlimefunItemStack TABLE_SAW = new SlimefunItemStack("TABLE_SAW", Material.STONECUTTER, "&6Table Saw", "", "&aAllows you to get 8 planks from 1 Log", "&a(Works with all log types)");
public static final SlimefunItemStack JUICER = new SlimefunItemStack("JUICER", Material.GLASS_BOTTLE, "&aJuicer", "", "&aAllows you to create delicious Juice");
public static final SlimefunItemStack AUTOMATED_PANNING_MACHINE = new SlimefunItemStack("AUTOMATED_PANNING_MACHINE", Material.BOWL, "&eAutomated Panning Machine", "", "&fA MultiBlock Version of the Gold Pan", "&fand Nether Gold Pan combined in one machine.");
@@ -664,12 +664,12 @@ public final class SlimefunItems {
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER = new SlimefunItemStack("ELECTRIC_ORE_GRINDER", Material.FURNACE, "&cElectric Ore Grinder", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_2 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_2", Material.FURNACE, "&cElectric Ore Grinder &7(&eII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(4), LoreBuilder.powerPerSecond(30));
public static final SlimefunItemStack ELECTRIC_INGOT_PULVERIZER = new SlimefunItemStack("ELECTRIC_INGOT_PULVERIZER", Material.FURNACE, "&cElectric Ingot Pulverizer", "", "&fPulverizes Ingots into Dust", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(14));
- public static final SlimefunItemStack AUTO_DRIER;
+ public static final SlimefunItemStack AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10));
public static final SlimefunItemStack AUTO_ENCHANTER = new SlimefunItemStack("AUTO_ENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Enchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18));
public static final SlimefunItemStack AUTO_DISENCHANTER = new SlimefunItemStack("AUTO_DISENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Disenchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18));
public static final SlimefunItemStack AUTO_ANVIL = new SlimefunItemStack("AUTO_ANVIL", Material.IRON_BLOCK, "&7Auto Anvil", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &7Repair Factor: 10%", LoreBuilder.powerPerSecond(24));
public static final SlimefunItemStack AUTO_ANVIL_2 = new SlimefunItemStack("AUTO_ANVIL_2", Material.IRON_BLOCK, "&7Auto Anvil Mk.II", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Repair Factor: 25%", LoreBuilder.powerPerSecond(32));
- public static final SlimefunItemStack AUTO_BREWER;
+ public static final SlimefunItemStack AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.SMOKER, "&6Auto Brewer", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
public static final SlimefunItemStack BIO_REACTOR = new SlimefunItemStack("BIO_REACTOR", Material.LIME_TERRACOTTA, "&2Bio Reactor", "", LoreBuilder.machine(MachineTier.AVERAGE, MachineType.GENERATOR), LoreBuilder.powerBuffer(128), LoreBuilder.powerPerSecond(8));
public static final SlimefunItemStack MULTIMETER = new SlimefunItemStack("MULTIMETER", Material.CLOCK, "&eMultimeter", "", "&fMeasures the Amount of stored", "&fEnergy in a Block");
@@ -843,17 +843,5 @@ public final class SlimefunItems {
static {
INFUSED_ELYTRA.addUnsafeEnchantment(Enchantment.MENDING, 1);
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- TABLE_SAW = new SlimefunItemStack("TABLE_SAW", Material.STONECUTTER, "&6Table Saw", "", "&aAllows you to get 8 planks from 1 Log", "&a(Works with all log types)");
- MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.BLAST_FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots");
- AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10));
- AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.SMOKER, "&6Auto Brewer", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
- } else {
- TABLE_SAW = null;
- MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots");
- AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.FURNACE, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10));
- AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.BREWING_STAND, "&6Auto Brewer", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
- }
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java
index b2656d623..2d14d4f21 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java
@@ -89,10 +89,15 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemL
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
-import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VillagerTradingListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WitherListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.AnvilListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.BrewingStandListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CartographyTableListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CauldronListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CraftingTableListener;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.GrindstoneListener;
import io.github.thebusybiscuit.slimefun4.implementation.resources.GEOResourcesSetup;
import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup;
import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup;
@@ -176,9 +181,14 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
command.register();
registry.load(config);
} else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
+ getLogger().log(Level.INFO, "CS-CoreLib was detected!");
long timestamp = System.nanoTime();
PaperLib.suggestPaper(this);
+ if (PaperLib.isPaper()) {
+ getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied.");
+ }
+
// We wanna ensure that the Server uses a compatible version of Minecraft
if (isVersionUnsupported()) {
getServer().getPluginManager().disablePlugin(this);
@@ -270,7 +280,10 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
ticker.start(this);
+
+ getLogger().log(Level.INFO, "Loading Third-Party plugin integrations...");
thirdPartySupportService.start();
+
gitHubService.start(this);
// Hooray!
@@ -445,7 +458,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new DeathpointListener(this);
new ExplosionsListener(this);
new DebugFishListener(this);
- new VanillaMachinesListener(this);
new FireworksListener(this);
new WitherListener(this);
new IronGolemListener(this);
@@ -453,6 +465,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new MobDropListener(this);
new VillagerTradingListener(this);
new ElytraCrashListener(this);
+ new CraftingTableListener(this);
+ new AnvilListener(this);
+ new BrewingStandListener(this);
+ new CauldronListener(this);
+ new GrindstoneListener(this);
+ new CartographyTableListener(this);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
new BeeListener(this);
@@ -469,6 +487,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new AncientAltarListener(this, (AncientAltar) SlimefunItems.ANCIENT_ALTAR.getItem(), (AncientPedestal) SlimefunItems.ANCIENT_PEDESTAL.getItem());
grapplingHookListener.register(this, (GrapplingHook) SlimefunItems.GRAPPLING_HOOK.getItem());
bowListener.register(this);
+ backpackListener.register(this);
// Toggleable Listeners for performance reasons
if (config.getBoolean("items.talismans")) {
@@ -479,10 +498,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new SoulboundListener(this);
}
- if (config.getBoolean("items.backpacks")) {
- backpackListener.register(this);
- }
-
// Handle Slimefun Guide being given on Join
new SlimefunGuideListener(this, config.getBoolean("guide.receive-on-first-join"));
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java
index 4f346f291..d88a295bf 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java
@@ -1,7 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;
-import javax.annotation.Nonnull;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -10,6 +8,9 @@ import java.util.Locale;
import java.util.Optional;
import java.util.logging.Level;
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
@@ -26,7 +27,6 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.recipes.MinecraftRecipe;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
@@ -65,21 +65,15 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36;
+ private static final Sound sound = Sound.ITEM_BOOK_PAGE_TURN;
- private final ItemStack item;
private final int[] recipeSlots = { 3, 4, 5, 12, 13, 14, 21, 22, 23 };
- private final Sound sound;
+ private final ItemStack item;
private final boolean showVanillaRecipes;
- public ChestSlimefunGuide(boolean vanillaRecipes) {
- showVanillaRecipes = vanillaRecipes;
+ public ChestSlimefunGuide(boolean showVanillaRecipes) {
+ this.showVanillaRecipes = showVanillaRecipes;
item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Chest GUI)");
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- sound = Sound.ITEM_BOOK_PAGE_TURN;
- } else {
- sound = Sound.ENTITY_BAT_TAKEOFF;
- }
}
@Override
@@ -132,7 +126,6 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
}
ChestMenu menu = create(p);
-
List categories = getVisibleCategories(p, profile);
int index = 9;
@@ -278,10 +271,10 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
if (isSurvivalMode() && !Slimefun.hasPermission(p, sfitem, false)) {
List message = SlimefunPlugin.getPermissionsService().getLore(sfitem);
- menu.addItem(index, new CustomItem(Material.BARRIER, sfitem.getItemName(), message.toArray(new String[0])));
+ menu.addItem(index, new CustomItem(ChestMenuUtils.getNoPermissionItem(), sfitem.getItemName(), message.toArray(new String[0])));
menu.addMenuClickHandler(index, ChestMenuUtils.getEmptyClickHandler());
} else if (isSurvivalMode() && research != null && !profile.hasUnlocked(research)) {
- menu.addItem(index, new CustomItem(Material.BARRIER, ChatColor.WHITE + ItemUtils.getItemName(sfitem.getItem()), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level(s)"));
+ menu.addItem(index, new CustomItem(ChestMenuUtils.getNotResearchedItem(), ChatColor.WHITE + ItemUtils.getItemName(sfitem.getItem()), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level(s)"));
menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(pl.getUniqueId())) {
if (research.canUnlock(pl)) {
@@ -341,26 +334,14 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
int index = 9;
// Find items and add them
for (SlimefunItem slimefunItem : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
- String itemName = ChatColor.stripColor(slimefunItem.getItemName()).toLowerCase(Locale.ROOT);
-
if (index == 44) {
break;
}
- if (!itemName.isEmpty() && (itemName.equals(searchTerm) || itemName.contains(searchTerm))) {
+ if (isSearchFilterApplicable(slimefunItem, searchTerm)) {
ItemStack itemstack = new CustomItem(slimefunItem.getItem(), meta -> {
- List lore = null;
Category category = slimefunItem.getCategory();
-
- if (category != null) {
- ItemStack categoryItem = category.getItem(p);
-
- if (categoryItem != null && categoryItem.hasItemMeta() && categoryItem.getItemMeta().hasDisplayName()) {
- lore = Arrays.asList("", ChatColor.DARK_GRAY + "\u21E8 " + ChatColor.WHITE + categoryItem.getItemMeta().getDisplayName());
- }
- }
-
- meta.setLore(lore);
+ meta.setLore(Arrays.asList("", ChatColor.DARK_GRAY + "\u21E8 " + ChatColor.WHITE + category.getDisplayName(p)));
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_POTION_EFFECTS);
});
@@ -386,6 +367,12 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
menu.open(p);
}
+ @ParametersAreNonnullByDefault
+ private boolean isSearchFilterApplicable(SlimefunItem slimefunItem, String searchTerm) {
+ String itemName = ChatColor.stripColor(slimefunItem.getItemName()).toLowerCase(Locale.ROOT);
+ return !itemName.isEmpty() && (itemName.equals(searchTerm) || itemName.contains(searchTerm));
+ }
+
@Override
public void displayItem(PlayerProfile profile, ItemStack item, int index, boolean addToHistory) {
Player p = profile.getPlayer();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java
index 61e7a2eaa..732c998a3 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
+import javax.annotation.Nonnull;
+
/**
* This enum holds all the different types a {@link ProgrammableAndroid} can represent.
*
@@ -55,7 +57,7 @@ public enum AndroidType {
*/
NON_FIGHTER;
- boolean isType(AndroidType type) {
+ boolean isType(@Nonnull AndroidType type) {
return type == NONE || type == this || (type == NON_FIGHTER && this != FIGHTER);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java
index 060bb6b81..e46721c84 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java
@@ -10,8 +10,6 @@ import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@@ -57,10 +55,6 @@ public class FarmerAndroid extends ProgrammableAndroid {
private ItemStack getDropFromCrop(Material crop) {
Random random = ThreadLocalRandom.current();
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && crop == Material.SWEET_BERRY_BUSH) {
- return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
- }
-
switch (crop) {
case WHEAT:
return new ItemStack(Material.WHEAT, random.nextInt(2) + 1);
@@ -74,6 +68,8 @@ public class FarmerAndroid extends ProgrammableAndroid {
return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1);
case NETHER_WART:
return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1);
+ case SWEET_BERRY_BUSH:
+ return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
default:
return null;
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java
index d2e9ce0c3..de83525a7 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java
@@ -10,8 +10,6 @@ import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.collections.RandomizedSet;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@@ -37,10 +35,7 @@ public class FisherAndroid extends ProgrammableAndroid {
fishingLoot.add(new ItemStack(Material.STICK), 5);
fishingLoot.add(new ItemStack(Material.ROTTEN_FLESH), 3);
fishingLoot.add(new ItemStack(Material.LEATHER), 2);
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- fishingLoot.add(new ItemStack(Material.BAMBOO), 3);
- }
+ fishingLoot.add(new ItemStack(Material.BAMBOO), 3);
// "loot"
fishingLoot.add(new ItemStack(Material.SADDLE), 1);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java
index 4a2083b05..6c707c979 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java
@@ -8,6 +8,7 @@ import java.util.Map;
import java.util.function.Predicate;
import org.apache.commons.lang.Validate;
+import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Ageable;
@@ -20,126 +21,223 @@ import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
-enum Instruction {
+/**
+ * This enum holds every {@link Instruction} for the {@link ProgrammableAndroid}
+ * added by Slimefun itself.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+public enum Instruction {
- // Start and End Parts
+ /**
+ * This {@link Instruction} is the starting point of a {@link Script}.
+ */
START(AndroidType.NONE, HeadTexture.SCRIPT_START),
+
+ /**
+ * This {@link Instruction} is the end token of a {@link Script}.
+ * Once this {@link Instruction} is reached, the {@link Script} will start again.
+ */
REPEAT(AndroidType.NONE, HeadTexture.SCRIPT_REPEAT),
+
+ /**
+ * This {@link Instruction} will make the {@link ProgrammableAndroid} wait
+ * for one Slimefun tick.
+ */
WAIT(AndroidType.NONE, HeadTexture.SCRIPT_WAIT),
- // Movement
+ /**
+ * This will make the {@link ProgrammableAndroid} go forward.
+ */
GO_FORWARD(AndroidType.NON_FIGHTER, HeadTexture.SCRIPT_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.move(b, face, target);
}),
+ /**
+ * This will make the {@link ProgrammableAndroid} go up.
+ */
GO_UP(AndroidType.NON_FIGHTER, HeadTexture.SCRIPT_UP, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.UP);
android.move(b, face, target);
}),
+ /**
+ * This will make the {@link ProgrammableAndroid} go down.
+ */
GO_DOWN(AndroidType.NON_FIGHTER, HeadTexture.SCRIPT_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.move(b, face, target);
}),
- // Directions
+ /**
+ * This will make the {@link ProgrammableAndroid} rotate to the left side.
+ */
TURN_LEFT(AndroidType.NONE, HeadTexture.SCRIPT_LEFT, (android, b, inv, face) -> {
int mod = -1;
android.rotate(b, face, mod);
}),
+ /**
+ * This will make the {@link ProgrammableAndroid} rotate to the right side.
+ */
TURN_RIGHT(AndroidType.NONE, HeadTexture.SCRIPT_RIGHT, (android, b, inv, face) -> {
int mod = 1;
android.rotate(b, face, mod);
}),
- // Action - Pickaxe
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} above.
+ */
DIG_UP(AndroidType.MINER, HeadTexture.SCRIPT_DIG_UP, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.UP);
android.dig(b, inv, target);
}),
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} ahead.
+ */
DIG_FORWARD(AndroidType.MINER, HeadTexture.SCRIPT_DIG_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.dig(b, inv, target);
}),
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} below.
+ */
DIG_DOWN(AndroidType.MINER, HeadTexture.SCRIPT_DIG_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.dig(b, inv, target);
}),
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} above
+ * and then move itself to that new {@link Location}.
+ */
MOVE_AND_DIG_UP(AndroidType.MINER, HeadTexture.SCRIPT_DIG_UP, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.UP);
android.moveAndDig(b, inv, face, target);
}),
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} ahead
+ * and then move itself to that new {@link Location}.
+ */
MOVE_AND_DIG_FORWARD(AndroidType.MINER, HeadTexture.SCRIPT_DIG_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.moveAndDig(b, inv, face, target);
}),
+ /**
+ * This will make a {@link MinerAndroid} dig the {@link Block} below
+ * and then move itself to that new {@link Location}.
+ */
MOVE_AND_DIG_DOWN(AndroidType.MINER, HeadTexture.SCRIPT_DIG_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.moveAndDig(b, inv, face, target);
}),
- // Action - Sword
+ /**
+ * This will make a {@link ButcherAndroid} attack any {@link LivingEntity}
+ * ahead of them.
+ */
ATTACK_MOBS_ANIMALS(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
Predicate predicate = e -> true;
android.attack(b, face, predicate);
}),
+ /**
+ * This will make a {@link ButcherAndroid} attack any {@link Monster}
+ * ahead of them.
+ */
ATTACK_MOBS(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
Predicate predicate = e -> e instanceof Monster;
android.attack(b, face, predicate);
}),
+ /**
+ * This will make a {@link ButcherAndroid} attack any {@link Animals Animal}
+ * ahead of them.
+ */
ATTACK_ANIMALS(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
Predicate predicate = e -> e instanceof Animals;
android.attack(b, face, predicate);
}),
+ /**
+ * This will make a {@link ButcherAndroid} attack any adult
+ * {@link Animals Animal} ahead of them.
+ */
ATTACK_ANIMALS_ADULT(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
- Predicate predicate = e -> e instanceof Animals && e instanceof Ageable && ((Ageable) e).isAdult();
+ Predicate predicate = e -> e instanceof Animals && ((Ageable) e).isAdult();
android.attack(b, face, predicate);
}),
- // Action - Axe
+ /**
+ * This will make a {@link WoodcutterAndroid} chop down the tree in front of them.
+ */
CHOP_TREE(AndroidType.WOODCUTTER, HeadTexture.SCRIPT_CHOP_TREE),
- // Action - Fishing Rod
+ /**
+ * This {@link Instruction} makes a {@link FisherAndroid} try to catch fish from
+ * the water below.
+ */
CATCH_FISH(AndroidType.FISHERMAN, HeadTexture.SCRIPT_FISH, (android, b, inv, face) -> android.fish(b, inv)),
- // Action - Hoe
+ /**
+ * This {@link Instruction} will make a {@link FarmerAndroid} try to harvest
+ * the {@link Block} in front of them.
+ */
FARM_FORWARD(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.farm(inv, target);
}),
+ /**
+ * This {@link Instruction} will make a {@link FarmerAndroid} try to harvest
+ * the {@link Block} below.
+ */
FARM_DOWN(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.farm(inv, target);
}),
- // Action - ExoticGarden
+ /**
+ * This {@link Instruction} will make a {@link FarmerAndroid} try to harvest
+ * the {@link Block} in front of them.
+ *
+ * This includes plants from ExoticGarden.
+ */
FARM_EXOTIC_FORWARD(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.exoticFarm(inv, target);
}),
+ /**
+ * This {@link Instruction} will make a {@link FarmerAndroid} try to harvest
+ * the {@link Block} below.
+ *
+ * This includes plants from ExoticGarden.
+ */
FARM_EXOTIC_DOWN(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.exoticFarm(inv, target);
}),
- // Action - Interface
+ /**
+ * This {@link Instruction} will force the {@link ProgrammableAndroid} to push their
+ * items into an {@link AndroidInterface} ahead of them.
+ */
INTERFACE_ITEMS(AndroidType.NONE, HeadTexture.SCRIPT_PUSH_ITEMS, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.depositItems(inv, target);
}),
+ /**
+ * This {@link Instruction} will force the {@link ProgrammableAndroid} to pull
+ * fuel from an {@link AndroidInterface} ahead of them.
+ */
INTERFACE_FUEL(AndroidType.NONE, HeadTexture.SCRIPT_PULL_FUEL, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.refuel(inv, target);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
index b57b449e4..07d828f96 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
@@ -58,6 +58,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
+import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@@ -69,6 +70,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
private static final int[] BORDER = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 24, 25, 26, 27, 33, 35, 36, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
private static final int[] OUTPUT_BORDER = { 10, 11, 12, 13, 14, 19, 23, 28, 32, 37, 38, 39, 40, 41 };
private static final String DEFAULT_SCRIPT = "START-TURN_LEFT-REPEAT";
+ private static final int MAX_SCRIPT_LENGTH = 54;
protected final List fuelTypes = new ArrayList<>();
protected final String texture;
@@ -407,19 +409,23 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
} else {
Script script = scripts.get(target);
menu.addItem(index, script.getAsItemStack(this, p), (player, slot, stack, action) -> {
- if (action.isShiftClicked()) {
- if (script.isAuthor(player)) {
- SlimefunPlugin.getLocalization().sendMessage(player, "android.scripts.rating.own", true);
- } else if (script.canRate(player)) {
- script.rate(player, !action.isRightClicked());
- openScriptDownloader(player, b, page);
- } else {
- SlimefunPlugin.getLocalization().sendMessage(player, "android.scripts.rating.already", true);
+ try {
+ if (action.isShiftClicked()) {
+ if (script.isAuthor(player)) {
+ SlimefunPlugin.getLocalization().sendMessage(player, "android.scripts.rating.own", true);
+ } else if (script.canRate(player)) {
+ script.rate(player, !action.isRightClicked());
+ openScriptDownloader(player, b, page);
+ } else {
+ SlimefunPlugin.getLocalization().sendMessage(player, "android.scripts.rating.already", true);
+ }
+ } else if (!action.isRightClicked()) {
+ script.download();
+ setScript(b.getLocation(), script.getSourceCode());
+ openScriptEditor(player, b);
}
- } else if (!action.isRightClicked()) {
- script.download();
- setScript(b.getLocation(), script.getSourceCode());
- openScriptEditor(player, b);
+ } catch (Exception x) {
+ Slimefun.getLogger().log(Level.SEVERE, "An Exception was thrown when a User tried to download a Script!", x);
}
return false;
@@ -534,12 +540,19 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
}
@Nonnull
- protected String getScript(@Nonnull Location l) {
+ public String getScript(@Nonnull Location l) {
+ Validate.notNull(l, "Location for android not specified");
String script = BlockStorage.getLocationInfo(l, "script");
return script != null ? script : DEFAULT_SCRIPT;
}
- protected void setScript(@Nonnull Location l, @Nonnull String script) {
+ public void setScript(@Nonnull Location l, @Nonnull String script) {
+ Validate.notNull(l, "Location for android not specified");
+ Validate.notNull(script, "No script given");
+ Validate.isTrue(script.startsWith(Instruction.START.name() + '-'), "A script must begin with a 'START' token.");
+ Validate.isTrue(script.endsWith('-' + Instruction.REPEAT.name()), "A script must end with a 'REPEAT' token.");
+ Validate.isTrue(PatternUtils.DASH.split(script).length <= MAX_SCRIPT_LENGTH, "Scripts may not have more than " + MAX_SCRIPT_LENGTH + " segments");
+
BlockStorage.addBlockInfo(l, "script", script);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java
index 5d97975f7..7ee370638 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java
@@ -130,18 +130,19 @@ public final class Script {
@Nonnull
ItemStack getAsItemStack(@Nonnull ProgrammableAndroid android, @Nonnull Player p) {
List lore = new LinkedList<>();
- lore.add("&7by &r" + getAuthor());
+ lore.add("&7by &f" + getAuthor());
lore.add("");
- lore.add("&7Downloads: &r" + getDownloads());
+ lore.add("&7Downloads: &f" + getDownloads());
lore.add("&7Rating: " + getScriptRatingPercentage());
lore.add("&a" + getUpvotes() + " \u263A &7| &4\u2639 " + getDownvotes());
lore.add("");
- lore.add("&eLeft Click &rto download this Script");
+ lore.add("&eLeft Click &fto download this Script");
lore.add("&4(This will override your current Script)");
if (canRate(p)) {
- lore.add("&eShift + Left Click &rto leave a positive Rating");
- lore.add("&eShift + Right Click &rto leave a negative Rating");
+ lore.add("");
+ lore.add("&eShift + Left Click &fto leave a positive Rating");
+ lore.add("&eShift + Right Click &fto leave a negative Rating");
}
return new CustomItem(android.getItem(), "&b" + getName(), lore.toArray(new String[0]));
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/Crucible.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/Crucible.java
index ee8f5c6df..73cd1902f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/Crucible.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/Crucible.java
@@ -18,6 +18,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
+import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@@ -72,6 +73,14 @@ public class Crucible extends SimpleSlimefunItem implements Rec
items.add(new ItemStack(Material.LAVA_BUCKET));
}
+ if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
+ items.add(new ItemStack(Material.BLACKSTONE, 8));
+ items.add(new ItemStack(Material.LAVA_BUCKET));
+
+ items.add(new ItemStack(Material.BASALT, 12));
+ items.add(new ItemStack(Material.LAVA_BUCKET));
+ }
+
return items;
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/AbstractEnergyProvider.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/AbstractEnergyProvider.java
index cc16f0db6..b7767796b 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/AbstractEnergyProvider.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/AbstractEnergyProvider.java
@@ -8,6 +8,7 @@ import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
+import org.apache.commons.lang.Validate;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@@ -89,11 +90,12 @@ public abstract class AbstractEnergyProvider extends SlimefunItem implements Inv
}
public void registerFuel(@Nonnull MachineFuel fuel) {
+ Validate.notNull(fuel, "Machine Fuel cannot be null!");
fuelTypes.add(fuel);
}
@Nonnull
- public Set getFuelTypes() {
+ public Set getFuelTypes2() {
return fuelTypes;
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/BioGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/BioGenerator.java
index 18a864221..e1c624ede 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/BioGenerator.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/BioGenerator.java
@@ -48,15 +48,12 @@ public abstract class BioGenerator extends AGenerator {
registerFuel(new MachineFuel(20, new ItemStack(Material.DRIED_KELP_BLOCK)));
registerFuel(new MachineFuel(1, new ItemStack(Material.SEAGRASS)));
registerFuel(new MachineFuel(2, new ItemStack(Material.SEA_PICKLE)));
+ registerFuel(new MachineFuel(1, new ItemStack(Material.BAMBOO)));
+ registerFuel(new MachineFuel(2, new ItemStack(Material.SWEET_BERRIES)));
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- registerFuel(new MachineFuel(1, new ItemStack(Material.BAMBOO)));
- registerFuel(new MachineFuel(2, new ItemStack(Material.SWEET_BERRIES)));
-
- // Small Flowers (formally just dandelions and poppies).
- for (Material m : Tag.SMALL_FLOWERS.getValues()) {
- registerFuel(new MachineFuel(1, new ItemStack(m)));
- }
+ // Small Flowers (formally just dandelions and poppies).
+ for (Material m : Tag.SMALL_FLOWERS.getValues()) {
+ registerFuel(new MachineFuel(1, new ItemStack(m)));
}
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java
index 1f0499a61..886164817 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java
@@ -74,7 +74,7 @@ public abstract class CoalGenerator extends AGenerator {
}
// Signs
- for (Material mat : Tag.SIGNS.getValues()) {
+ for (Material mat : Tag.STANDING_SIGNS.getValues()) {
registerFuel(new MachineFuel(2, new ItemStack(mat)));
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectrifiedCrucible.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectrifiedCrucible.java
index f0d7c128d..e26b0c9ea 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectrifiedCrucible.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectrifiedCrucible.java
@@ -4,6 +4,8 @@ import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.inventory.ItemStack;
+import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@@ -29,6 +31,11 @@ public abstract class ElectrifiedCrucible extends AContainer {
for (Material leaves : Tag.LEAVES.getValues()) {
registerRecipe(10, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(leaves, 16) }, new ItemStack[] { new ItemStack(Material.WATER_BUCKET) });
}
+
+ if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
+ registerRecipe(10, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(Material.BLACKSTONE, 8) }, new ItemStack[] { new ItemStack(Material.LAVA_BUCKET) });
+ registerRecipe(10, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(Material.BASALT, 12) }, new ItemStack[] { new ItemStack(Material.LAVA_BUCKET) });
+ }
}
@Override
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodComposter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodComposter.java
index 8f7988af3..a7ef3c4b8 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodComposter.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodComposter.java
@@ -3,10 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.OrganicFertilizer;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@@ -30,10 +28,7 @@ public abstract class FoodComposter extends AContainer implements RecipeDisplayI
registerRecipe(30, new ItemStack[] { SlimefunItems.APPLE_ORGANIC_FOOD }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.APPLE_FERTILIZER, OrganicFertilizer.OUTPUT) });
registerRecipe(30, new ItemStack[] { SlimefunItems.KELP_ORGANIC_FOOD }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.KELP_FERTILIZER, OrganicFertilizer.OUTPUT) });
registerRecipe(30, new ItemStack[] { SlimefunItems.COCOA_ORGANIC_FOOD }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.COCOA_FERTILIZER, OrganicFertilizer.OUTPUT) });
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- registerRecipe(30, new ItemStack[] { SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.SWEET_BERRIES_FERTILIZER, OrganicFertilizer.OUTPUT) });
- }
+ registerRecipe(30, new ItemStack[] { SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.SWEET_BERRIES_FERTILIZER, OrganicFertilizer.OUTPUT) });
}
@Override
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodFabricator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodFabricator.java
index 03fec44c6..ecc8a3e2a 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodFabricator.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/FoodFabricator.java
@@ -3,9 +3,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.OrganicFood;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@@ -29,10 +27,7 @@ public abstract class FoodFabricator extends AContainer {
registerRecipe(12, new ItemStack[] { SlimefunItems.TIN_CAN, new ItemStack(Material.APPLE) }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.APPLE_ORGANIC_FOOD, OrganicFood.OUTPUT) });
registerRecipe(12, new ItemStack[] { SlimefunItems.TIN_CAN, new ItemStack(Material.DRIED_KELP) }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.KELP_ORGANIC_FOOD, OrganicFood.OUTPUT) });
registerRecipe(12, new ItemStack[] { SlimefunItems.TIN_CAN, new ItemStack(Material.COCOA_BEANS) }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.COCOA_ORGANIC_FOOD, OrganicFood.OUTPUT) });
-
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- registerRecipe(12, new ItemStack[] { SlimefunItems.TIN_CAN, new ItemStack(Material.SWEET_BERRIES) }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD, OrganicFood.OUTPUT) });
- }
+ registerRecipe(12, new ItemStack[] { SlimefunItems.TIN_CAN, new ItemStack(Material.SWEET_BERRIES) }, new ItemStack[] { new SlimefunItemStack(SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD, OrganicFood.OUTPUT) });
}
@Override
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/EnderTalisman.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/EnderTalisman.java
index ee66d564f..296b423c1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/EnderTalisman.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/EnderTalisman.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.NamespacedKey;
import org.bukkit.block.EnderChest;
import org.bukkit.inventory.ItemStack;
@@ -21,12 +23,13 @@ class EnderTalisman extends Talisman {
private static final LockedCategory ENDER_TALISMANS_CATEGORY = new LockedCategory(new NamespacedKey(SlimefunPlugin.instance(), "ender_talismans"), new CustomItem(SlimefunItems.ENDER_TALISMAN, "&7Talismans - &aTier II"), 3, Talisman.TALISMANS_CATEGORY.getKey());
+ @ParametersAreNonnullByDefault
public EnderTalisman(Talisman parent, SlimefunItemStack item) {
super(ENDER_TALISMANS_CATEGORY, item, new ItemStack[] { SlimefunItems.ENDER_LUMP_3, null, SlimefunItems.ENDER_LUMP_3, null, parent.getItem(), null, SlimefunItems.ENDER_LUMP_3, null, SlimefunItems.ENDER_LUMP_3 }, parent.isConsumable(), parent.isEventCancelled(), parent.getMessageSuffix(), parent.getChance(), parent.getEffects());
}
@Override
- public void createEnderTalisman() {
+ void loadEnderTalisman() {
// Let's override that, otherwise we would be creating Ender Talismans
// for every Ender Talisman
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java
index 976941ae9..befa9b567 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java
@@ -7,6 +7,7 @@ import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey;
@@ -48,19 +49,23 @@ public class Talisman extends SlimefunItem {
protected final PotionEffect[] effects;
protected final int chance;
- public Talisman(SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, String messageSuffix, PotionEffect... effects) {
+ @ParametersAreNonnullByDefault
+ public Talisman(SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, @Nullable String messageSuffix, PotionEffect... effects) {
this(item, recipe, consumable, cancelEvent, messageSuffix, 100, effects);
}
- public Talisman(SlimefunItemStack item, ItemStack[] recipe, String messageSuffix, int chance, PotionEffect... effects) {
+ @ParametersAreNonnullByDefault
+ public Talisman(SlimefunItemStack item, ItemStack[] recipe, @Nullable String messageSuffix, int chance, PotionEffect... effects) {
this(item, recipe, true, true, messageSuffix, chance, effects);
}
- public Talisman(SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, String messageSuffix, int chance, PotionEffect... effects) {
+ @ParametersAreNonnullByDefault
+ public Talisman(SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, @Nullable String messageSuffix, int chance, PotionEffect... effects) {
this(TALISMANS_CATEGORY, item, recipe, consumable, cancelEvent, messageSuffix, chance, effects);
}
- protected Talisman(Category category, SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, String messageSuffix, int chance, PotionEffect... effects) {
+ @ParametersAreNonnullByDefault
+ protected Talisman(Category category, SlimefunItemStack item, ItemStack[] recipe, boolean consumable, boolean cancelEvent, @Nullable String messageSuffix, int chance, PotionEffect... effects) {
super(category, item, RecipeType.MAGIC_WORKBENCH, recipe, new CustomItem(item, consumable ? 4 : 1));
this.consumable = consumable;
@@ -85,14 +90,26 @@ public class Talisman extends SlimefunItem {
}
}
+ /**
+ * This returns whether the {@link Talisman} will be consumed upon use.
+ *
+ * @return Whether this {@link Talisman} is consumed on use.
+ */
public boolean isConsumable() {
return consumable;
}
+ /**
+ * This returns the chance of this {@link Talisman} activating.
+ * The chance will be between 1 and 100.
+ *
+ * @return The chance of this {@link Talisman} activating.
+ */
public int getChance() {
return chance;
}
+ @Nonnull
public PotionEffect[] getEffects() {
return effects;
}
@@ -105,6 +122,7 @@ public class Talisman extends SlimefunItem {
return cancel;
}
+ @Nullable
private SlimefunItemStack getEnderVariant() {
return enderTalisman;
}
@@ -118,10 +136,10 @@ public class Talisman extends SlimefunItem {
@Override
public void load() {
super.load();
- createEnderTalisman();
+ loadEnderTalisman();
}
- protected void createEnderTalisman() {
+ void loadEnderTalisman() {
EnderTalisman talisman = (EnderTalisman) SlimefunItem.getByItem(getEnderVariant());
Optional research = Research.getResearch(new NamespacedKey(SlimefunPlugin.instance(), "ender_talismans"));
@@ -130,7 +148,7 @@ public class Talisman extends SlimefunItem {
}
}
- private static boolean hasMessage(Talisman talisman) {
+ private static boolean hasMessage(@Nonnull Talisman talisman) {
return talisman.getMessageSuffix() != null;
}
@@ -165,14 +183,14 @@ public class Talisman extends SlimefunItem {
ItemStack possibleTalisman = retrieveTalismanFromInventory(p.getInventory(), talisman);
if (possibleTalisman != null && Slimefun.hasUnlocked(p, talisman, true)) {
- activateTalisman(e, p, p.getInventory(), talisman);
+ activateTalisman(e, p, p.getInventory(), talisman, possibleTalisman);
return possibleTalisman;
}
possibleTalisman = retrieveTalismanFromInventory(p.getEnderChest(), talisman);
if (possibleTalisman != null && Slimefun.hasUnlocked(p, talisman, true)) {
- activateTalisman(e, p, p.getEnderChest(), talisman);
+ activateTalisman(e, p, p.getEnderChest(), talisman, possibleTalisman);
return possibleTalisman;
}
@@ -182,6 +200,7 @@ public class Talisman extends SlimefunItem {
@Nullable
private static ItemStack retrieveTalismanFromInventory(@Nonnull Inventory inv, @Nonnull Talisman talisman) {
ItemStack[] contents = inv.getContents();
+
for (int i = 0; i < contents.length; i++) {
ItemStack item = contents[i];
@@ -193,50 +212,47 @@ public class Talisman extends SlimefunItem {
return null;
}
- private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman) {
- consumeItem(inv, talisman);
+ @ParametersAreNonnullByDefault
+ private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem) {
+ consumeItem(inv, talisman, talismanItem);
applyTalismanEffects(p, talisman);
cancelEvent(e, talisman);
sendMessage(p, talisman);
}
+ @ParametersAreNonnullByDefault
private static void applyTalismanEffects(Player p, Talisman talisman) {
for (PotionEffect effect : talisman.getEffects()) {
p.addPotionEffect(effect);
}
}
+ @ParametersAreNonnullByDefault
private static void cancelEvent(Event e, Talisman talisman) {
if (e instanceof Cancellable && talisman.isEventCancelled()) {
((Cancellable) e).setCancelled(true);
}
}
+ @ParametersAreNonnullByDefault
private static void sendMessage(Player p, Talisman talisman) {
if (hasMessage(talisman)) {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.talisman." + talisman.getMessageSuffix(), true);
}
}
- private static void consumeItem(Inventory inv, Talisman talisman) {
+ @ParametersAreNonnullByDefault
+ private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) {
if (talisman.isConsumable()) {
- ItemStack[] contents = inv.getContents();
- for (int i = 0; i < contents.length; i++) {
- ItemStack item = contents[i];
-
- if (SlimefunUtils.isItemSimilar(item, talisman.getItem(), true, false)) {
- ItemUtils.consumeItem(item, false);
- return;
- }
- }
+ ItemUtils.consumeItem(talismanItem, false);
}
}
- private static Player getPlayerByEventType(Event e) {
+ @Nullable
+ private static Player getPlayerByEventType(@Nonnull Event e) {
if (e instanceof PlayerDeathEvent) {
return ((PlayerDeathEvent) e).getEntity();
- }
- else if (e instanceof EntityDeathEvent) {
+ } else if (e instanceof EntityDeathEvent) {
return ((EntityDeathEvent) e).getEntity().getKiller();
} else if (e instanceof BlockBreakEvent) {
return ((BlockBreakEvent) e).getPlayer();
@@ -253,7 +269,7 @@ public class Talisman extends SlimefunItem {
return null;
}
- private static boolean pass(Player p, SlimefunItem talisman) {
+ private static boolean pass(@Nonnull Player p, @Nonnull SlimefunItem talisman) {
for (PotionEffect effect : ((Talisman) talisman).getEffects()) {
if (effect != null && p.hasPotionEffect(effect.getType())) {
return false;
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/misc/StrangeNetherGoo.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/misc/StrangeNetherGoo.java
index a1b0ab966..f5f79532f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/misc/StrangeNetherGoo.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/misc/StrangeNetherGoo.java
@@ -1,14 +1,25 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.misc;
+import javax.annotation.Nonnull;
+import java.util.Optional;
+
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.GameMode;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.entity.Piglin;
+import org.bukkit.entity.Sheep;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
-import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.PiglinBarterDrop;
+import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.VillagerRune;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@@ -16,9 +27,6 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
-import javax.annotation.Nonnull;
-import java.util.Optional;
-
/**
* This {@link SlimefunItem} can only be obtained via bartering with a {@link Piglin}, its
* only current uses is the recipe for crafting the {@link VillagerRune}.
@@ -37,6 +45,7 @@ public class StrangeNetherGoo extends SimpleSlimefunItem impleme
super(category, item, recipeType, recipe);
addItemSetting(chance);
+ addItemHandler(onRightClickEntity());
}
@Override
@@ -56,4 +65,27 @@ public class StrangeNetherGoo extends SimpleSlimefunItem impleme
};
}
+ private EntityInteractHandler onRightClickEntity() {
+ return (e, item, hand) -> {
+ if (e.getRightClicked() instanceof Sheep) {
+ Sheep s = (Sheep) e.getRightClicked();
+
+ if (s.getCustomName() != null) {
+ e.setCancelled(true);
+ return;
+ }
+
+ if (e.getPlayer().getGameMode() != GameMode.CREATIVE) {
+ ItemUtils.consumeItem(item, false);
+ }
+
+ // Give Sheep color, name and effect
+ s.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 60, 2));
+ s.setColor(DyeColor.PURPLE);
+ s.setCustomName(ChatColor.DARK_PURPLE + "Tainted Sheep");
+ e.setCancelled(true);
+
+ }
+ };
+ }
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java
index 1cb865b36..608a0e2f5 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java
@@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks;
import java.util.List;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
@@ -14,7 +16,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
-import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
@@ -23,7 +24,7 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
-public class ArmorForge extends MultiBlockMachine {
+public class ArmorForge extends BackpackCrafter {
public ArmorForge(Category category, SlimefunItemStack item) {
super(category, item, new ItemStack[] { null, null, null, null, new ItemStack(Material.ANVIL), null, null, new CustomItem(Material.DISPENSER, "Dispenser (Facing up)"), null }, BlockFace.SELF);
@@ -31,8 +32,8 @@ public class ArmorForge extends MultiBlockMachine {
@Override
public void onInteract(Player p, Block b) {
- Block dispBlock = b.getRelative(BlockFace.DOWN);
- BlockState state = PaperLib.getBlockState(dispBlock, false).getState();
+ Block dispenser = b.getRelative(BlockFace.DOWN);
+ BlockState state = PaperLib.getBlockState(dispenser, false).getState();
if (state instanceof Dispenser) {
Dispenser disp = (Dispenser) state;
@@ -44,13 +45,7 @@ public class ArmorForge extends MultiBlockMachine {
ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone();
if (Slimefun.hasUnlocked(p, output, true)) {
- Inventory outputInv = findOutputInventory(output, dispBlock, inv);
-
- if (outputInv != null) {
- craft(p, output, inv, outputInv);
- } else {
- SlimefunPlugin.getLocalization().sendMessage(p, "machines.full-inventory", true);
- }
+ craft(p, output, inv, dispenser);
}
return;
@@ -71,26 +66,35 @@ public class ArmorForge extends MultiBlockMachine {
return true;
}
- private void craft(Player p, ItemStack output, Inventory inv, Inventory outputInv) {
- for (int j = 0; j < 9; j++) {
- ItemStack item = inv.getContents()[j];
+ @ParametersAreNonnullByDefault
+ private void craft(Player p, ItemStack output, Inventory inv, Block dispenser) {
+ Inventory fakeInv = createVirtualInventory(inv);
+ Inventory outputInv = findOutputInventory(output, dispenser, inv, fakeInv);
- if (item != null && item.getType() != Material.AIR) {
- ItemUtils.consumeItem(item, true);
- }
- }
+ if (outputInv != null) {
+ for (int j = 0; j < 9; j++) {
+ ItemStack item = inv.getContents()[j];
- for (int j = 0; j < 4; j++) {
- int current = j;
-
- SlimefunPlugin.runSync(() -> {
- if (current < 3) {
- p.getWorld().playSound(p.getLocation(), Sound.BLOCK_ANVIL_USE, 1F, 2F);
- } else {
- p.getWorld().playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1F, 1F);
- outputInv.addItem(output);
+ if (item != null && item.getType() != Material.AIR) {
+ ItemUtils.consumeItem(item, true);
}
- }, j * 20L);
+ }
+
+ for (int j = 0; j < 4; j++) {
+ int current = j;
+
+ SlimefunPlugin.runSync(() -> {
+ if (current < 3) {
+ p.getWorld().playSound(p.getLocation(), Sound.BLOCK_ANVIL_USE, 1F, 2F);
+ } else {
+ p.getWorld().playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1F, 1F);
+ outputInv.addItem(output);
+ }
+ }, j * 20L);
+ }
+
+ } else {
+ SlimefunPlugin.getLocalization().sendMessage(p, "machines.full-inventory", true);
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/BackpackCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/BackpackCrafter.java
index 1a7615221..baf52187a 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/BackpackCrafter.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/BackpackCrafter.java
@@ -32,6 +32,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*
* @see EnhancedCraftingTable
* @see MagicWorkbench
+ * @see ArmorForge
*
*/
abstract class BackpackCrafter extends MultiBlockMachine {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java
index 4395387c8..e3173af17 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java
@@ -15,7 +15,6 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@@ -27,8 +26,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class PressureChamber extends MultiBlockMachine {
public PressureChamber(Category category, SlimefunItemStack item) {
- super(category, item, new ItemStack[] { SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) ? new ItemStack(Material.SMOOTH_STONE_SLAB) : new ItemStack(Material.STONE_SLAB), new CustomItem(Material.DISPENSER, "Dispenser (Facing down)"), SlimefunPlugin.getMinecraftVersion()
- .isAtLeast(MinecraftVersion.MINECRAFT_1_14) ? new ItemStack(Material.SMOOTH_STONE_SLAB) : new ItemStack(Material.STONE_SLAB), new ItemStack(Material.PISTON), new ItemStack(Material.GLASS), new ItemStack(Material.PISTON), new ItemStack(Material.PISTON), new ItemStack(Material.CAULDRON), new ItemStack(Material.PISTON) }, BlockFace.UP);
+ super(category, item, new ItemStack[] { new ItemStack(Material.SMOOTH_STONE_SLAB), new CustomItem(Material.DISPENSER, "Dispenser (Facing down)"), new ItemStack(Material.SMOOTH_STONE_SLAB), new ItemStack(Material.PISTON), new ItemStack(Material.GLASS), new ItemStack(Material.PISTON), new ItemStack(Material.PISTON), new ItemStack(Material.CAULDRON), new ItemStack(Material.PISTON) }, BlockFace.UP);
}
@Override
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java
index c0dc2775d..157b26954 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java
@@ -52,7 +52,7 @@ public class IndustrialMiner extends MultiBlockMachine {
private final ItemSetting canMineAncientDebris = new ItemSetting<>("can-mine-ancient-debris", false);
public IndustrialMiner(Category category, SlimefunItemStack item, Material baseMaterial, boolean silkTouch, int range) {
- super(category, item, new ItemStack[] { null, null, null, new CustomItem(Material.PISTON, "Piston (facing up)"), new ItemStack(Material.CHEST), new CustomItem(Material.PISTON, "Piston (facing up)"), new ItemStack(baseMaterial), new ItemStack(SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) ? Material.BLAST_FURNACE : Material.FURNACE), new ItemStack(baseMaterial) }, BlockFace.UP);
+ super(category, item, new ItemStack[] { null, null, null, new CustomItem(Material.PISTON, "Piston (facing up)"), new ItemStack(Material.CHEST), new CustomItem(Material.PISTON, "Piston (facing up)"), new ItemStack(baseMaterial), new ItemStack(Material.BLAST_FURNACE), new ItemStack(baseMaterial) }, BlockFace.UP);
this.range = range;
this.silkTouch = silkTouch;
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
index d452896f3..33d3f9cc5 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
@@ -55,7 +55,7 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla
Player p = e.getPlayer();
Block b = e.getBlock();
- b.getWorld().createExplosion(b.getLocation(), 0.0F);
+ b.getWorld().createExplosion(b.getLocation(), 0);
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
List blocks = findBlocks(b);
@@ -122,8 +122,9 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla
private void breakBlock(Player p, ItemStack item, Block b, int fortune, List drops) {
SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK);
+ Material material = b.getType();
- b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
+ b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, material);
SlimefunItem sfItem = BlockStorage.check(b);
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
@@ -132,10 +133,10 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla
if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) {
drops.add(BlockStorage.retrieve(b));
}
- } else if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.SHULKER_BOX || b.getType().name().endsWith("_SHULKER_BOX")) {
+ } else if (material == Material.PLAYER_HEAD || SlimefunTag.SHULKER_BOXES.isTagged(material)) {
b.breakNaturally(item);
} else {
- boolean applyFortune = b.getType().name().endsWith("_ORE") && b.getType() != Material.IRON_ORE && b.getType() != Material.GOLD_ORE;
+ boolean applyFortune = SlimefunTag.FORTUNE_COMPATIBLE_ORES.isTagged(material);
for (ItemStack drop : b.getDrops(getItem())) {
// For some reason this check is necessary with Paper
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java
index 023a8df4c..815cb6c6e 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java
@@ -39,6 +39,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
* and {@link BlockBreakEvent}.
*
* @author TheBusyBiscuit
+ * @author Linox
*
* @see BlockPlaceHandler
* @see BlockBreakHandler
@@ -51,17 +52,22 @@ public class BlockListener implements Listener {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
- @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
- public void onBlockPlace(BlockPlaceEvent e) {
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onBlockPlaceExisting(BlockPlaceEvent e) {
+ // This prevents Players from placing a block where another block already exists
+ // While this can cause ghost blocks it also prevents them from replacing grass
+ // or saplings etc...
if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true);
- return;
}
+ }
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBlockPlace(BlockPlaceEvent e) {
ItemStack item = e.getItemInHand();
-
SlimefunItem sfItem = SlimefunItem.getByItem(item);
- if (sfItem != null && Slimefun.isEnabled(e.getPlayer(), sfItem, true) && !(sfItem instanceof NotPlaceable)) {
+
+ if (sfItem != null && !(sfItem instanceof NotPlaceable) && Slimefun.isEnabled(e.getPlayer(), sfItem, true)) {
if (!Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) {
e.setCancelled(true);
} else {
@@ -75,8 +81,13 @@ public class BlockListener implements Listener {
}
}
- @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
+ if (SlimefunPlugin.getThirdPartySupportService().isEventFaked(e)) {
+ // This is a "fake" event, we can ignore it.
+ return;
+ }
+
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock());
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
@@ -94,6 +105,7 @@ public class BlockListener implements Listener {
dropItems(e, drops);
}
+ @ParametersAreNonnullByDefault
private void callToolHandler(BlockBreakEvent e, ItemStack item, int fortune, List drops) {
SlimefunItem tool = SlimefunItem.getByItem(item);
@@ -106,6 +118,7 @@ public class BlockListener implements Listener {
}
}
+ @ParametersAreNonnullByDefault
private void callBlockHandler(BlockBreakEvent e, ItemStack item, int fortune, List drops) {
SlimefunItem sfItem = BlockStorage.check(e.getBlock());
@@ -183,16 +196,19 @@ public class BlockListener implements Listener {
}
private int getBonusDropsWithFortune(@Nullable ItemStack item, @Nonnull Block b) {
- int fortune = 1;
+ int amount = 1;
- if (item != null && item.getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS) && !item.getEnchantments().containsKey(Enchantment.SILK_TOUCH)) {
- Random random = ThreadLocalRandom.current();
+ if (item != null) {
int fortuneLevel = item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS);
- fortune = Math.max(1, random.nextInt(fortuneLevel + 2) - 1);
- fortune = (b.getType() == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1) * (fortune + 1);
+ if (fortuneLevel > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
+ Random random = ThreadLocalRandom.current();
+
+ amount = Math.max(1, random.nextInt(fortuneLevel + 2) - 1);
+ amount = (b.getType() == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1) * (amount + 1);
+ }
}
- return fortune;
+ return amount;
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java
index 777b7c141..9d24ff2f5 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java
@@ -39,15 +39,19 @@ public class SlimefunBootsListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onDamage(EntityDamageEvent e) {
- if (e.getEntity() instanceof Player) {
- if (e.getCause() == DamageCause.FALL) {
- onFallDamage(e);
- } else if (e instanceof EntityDamageByEntityEvent) {
- EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) e;
+ if (e.getEntity() instanceof Player && e.getCause() == DamageCause.FALL) {
+ onFallDamage(e);
+ }
+ }
- if (event.getDamager() instanceof EnderPearl) {
- onEnderPearlDamage(e);
- }
+ @EventHandler
+ public void onEnderPearlDamage(EntityDamageByEntityEvent e) {
+ if (e.getDamager() instanceof EnderPearl && e.getEntity() instanceof Player) {
+ Player p = (Player) e.getEntity();
+ SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots());
+
+ if (boots != null && boots.getId().equals("ENDER_BOOTS") && Slimefun.hasUnlocked(p, boots, true)) {
+ e.setCancelled(true);
}
}
}
@@ -71,15 +75,6 @@ public class SlimefunBootsListener implements Listener {
}
}
- private void onEnderPearlDamage(@Nonnull EntityDamageEvent e) {
- Player p = (Player) e.getEntity();
- SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots());
-
- if (boots != null && boots.getId().equals("ENDER_BOOTS") && Slimefun.hasUnlocked(p, boots, true)) {
- e.setCancelled(true);
- }
- }
-
@EventHandler
public void onTrample(PlayerInteractEvent e) {
if (e.getAction() == Action.PHYSICAL) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VanillaMachinesListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VanillaMachinesListener.java
deleted file mode 100644
index e4e5b49ee..000000000
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VanillaMachinesListener.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package io.github.thebusybiscuit.slimefun4.implementation.listeners;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.bukkit.block.BrewingStand;
-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.CraftItemEvent;
-import org.bukkit.event.inventory.InventoryAction;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.event.inventory.InventoryType;
-import org.bukkit.event.inventory.PrepareItemCraftEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-
-import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
-import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
-import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
-import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
-
-/**
- * This {@link Listener} prevents any {@link SlimefunItem} from being used in a vanilla
- * machine like the workbench, grindstone, brewing stand or an anvil.
- *
- * @author TheBusyBiscuit
- * @author NathanAdhitya
- * @author Steve
- * @author VoidAngel
- *
- */
-public class VanillaMachinesListener implements Listener {
-
- public VanillaMachinesListener(@Nonnull SlimefunPlugin plugin) {
- plugin.getServer().getPluginManager().registerEvents(this, plugin);
- }
-
- @EventHandler(ignoreCancelled = true)
- public void onGrindstone(InventoryClickEvent e) {
- // The Grindstone was only ever added in MC 1.14
- if (!SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- return;
- }
-
- if (e.getRawSlot() == 2 && e.getWhoClicked() instanceof Player && e.getInventory().getType() == InventoryType.GRINDSTONE) {
- ItemStack item1 = e.getInventory().getContents()[0];
- ItemStack item2 = e.getInventory().getContents()[1];
-
- if (checkForUnallowedItems(item1, item2)) {
- e.setResult(Result.DENY);
- }
- }
-
- }
-
- @EventHandler
- public void onCraft(CraftItemEvent e) {
- for (ItemStack item : e.getInventory().getContents()) {
- SlimefunItem sfItem = SlimefunItem.getByItem(item);
-
- if (sfItem != null && !sfItem.isUseableInWorkbench()) {
- e.setResult(Result.DENY);
- SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "workbench.not-enhanced", true);
- break;
- }
- }
- }
-
- @EventHandler
- public void onPrepareCraft(PrepareItemCraftEvent e) {
- if (e.getInventory().getResult() != null) {
- for (ItemStack item : e.getInventory().getContents()) {
- SlimefunItem sfItem = SlimefunItem.getByItem(item);
-
- if (sfItem != null && !sfItem.isUseableInWorkbench()) {
- e.getInventory().setResult(null);
- break;
- }
- }
- }
- }
-
- @EventHandler(ignoreCancelled = true)
- public void onAnvil(InventoryClickEvent e) {
- if (e.getRawSlot() == 2 && e.getInventory().getType() == InventoryType.ANVIL && e.getWhoClicked() instanceof Player) {
- ItemStack item1 = e.getInventory().getContents()[0];
- ItemStack item2 = e.getInventory().getContents()[1];
-
- if (checkForUnallowedItems(item1, item2)) {
- e.setResult(Result.DENY);
- SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "anvil.not-working", true);
- }
- }
- }
-
- @EventHandler(ignoreCancelled = true)
- public void onCartographyTable(InventoryClickEvent e) {
- // The Cartography Table was only ever added in MC 1.14
- if (!SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- return;
- }
-
- if (e.getRawSlot() == 2 && e.getInventory().getType() == InventoryType.CARTOGRAPHY && e.getWhoClicked() instanceof Player) {
- ItemStack item1 = e.getInventory().getContents()[0];
- ItemStack item2 = e.getInventory().getContents()[1];
-
- if (checkForUnallowedItems(item1, item2)) {
- e.setResult(Result.DENY);
- SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "cartography_table.not-working", true);
- }
- }
- }
-
- @EventHandler(ignoreCancelled = true)
- public void onPreBrew(InventoryClickEvent e) {
- Inventory clickedInventory = e.getClickedInventory();
- Inventory topInventory = e.getView().getTopInventory();
-
- if (clickedInventory != null && topInventory.getType() == InventoryType.BREWING && topInventory.getHolder() instanceof BrewingStand) {
- if (e.getAction() == InventoryAction.HOTBAR_SWAP) {
- e.setCancelled(true);
- return;
- }
-
- if (clickedInventory.getType() == InventoryType.BREWING) {
- e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor())));
- } else {
- e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCurrentItem())));
- }
-
- if (e.getResult() == Result.DENY) {
- SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "brewing_stand.not-working", true);
- }
- }
- }
-
- private boolean checkForUnallowedItems(@Nullable ItemStack item1, @Nullable ItemStack item2) {
- if (SlimefunGuide.isGuideItem(item1) || SlimefunGuide.isGuideItem(item2)) {
- return true;
- } else {
- SlimefunItem sfItem1 = SlimefunItem.getByItem(item1);
- SlimefunItem sfItem2 = SlimefunItem.getByItem(item2);
-
- if (isUnallowed(sfItem1) || isUnallowed(sfItem2)) {
- return true;
- }
- }
-
- return false;
- }
-
- private boolean isUnallowed(@Nullable SlimefunItem item) {
- return item != null && !(item instanceof VanillaItem) && !item.isDisabled();
- }
-}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java
new file mode 100644
index 000000000..4df3a82eb
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java
@@ -0,0 +1,43 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+import org.bukkit.block.BrewingStand;
+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.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * {@link BrewingStand}.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+public class AnvilListener implements SlimefunCraftingListener {
+
+ public AnvilListener(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onAnvil(InventoryClickEvent e) {
+ if (e.getRawSlot() == 2 && e.getInventory().getType() == InventoryType.ANVIL && e.getWhoClicked() instanceof Player) {
+ ItemStack item1 = e.getInventory().getContents()[0];
+ ItemStack item2 = e.getInventory().getContents()[1];
+
+ if (hasUnallowedItems(item1, item2)) {
+ e.setResult(Result.DENY);
+ SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "anvil.not-working", true);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/BrewingStandListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/BrewingStandListener.java
new file mode 100644
index 000000000..60a4594af
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/BrewingStandListener.java
@@ -0,0 +1,55 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+import org.bukkit.block.BrewingStand;
+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 me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * {@link BrewingStand}.
+ *
+ * @author VoidAngel
+ * @author SoSeDiK
+ *
+ */
+public class BrewingStandListener implements SlimefunCraftingListener {
+
+ public BrewingStandListener(@Nonnull 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.BREWING && topInventory.getHolder() instanceof BrewingStand) {
+ if (e.getAction() == InventoryAction.HOTBAR_SWAP) {
+ e.setCancelled(true);
+ return;
+ }
+
+ if (clickedInventory.getType() == InventoryType.BREWING) {
+ e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCursor())));
+ } else {
+ e.setCancelled(isUnallowed(SlimefunItem.getByItem(e.getCurrentItem())));
+ }
+
+ if (e.getResult() == Result.DENY) {
+ SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "brewing_stand.not-working", true);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CartographyTableListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CartographyTableListener.java
new file mode 100644
index 000000000..9586fdeb2
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CartographyTableListener.java
@@ -0,0 +1,42 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+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.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * cartography table.
+ *
+ * @author poma123
+ *
+ */
+public class CartographyTableListener implements SlimefunCraftingListener {
+
+ public CartographyTableListener(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onCartographyTable(InventoryClickEvent e) {
+ if (e.getRawSlot() == 2 && e.getInventory().getType() == InventoryType.CARTOGRAPHY && e.getWhoClicked() instanceof Player) {
+ ItemStack item1 = e.getInventory().getContents()[0];
+ ItemStack item2 = e.getInventory().getContents()[1];
+
+ if (hasUnallowedItems(item1, item2)) {
+ e.setResult(Result.DENY);
+ SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "cartography_table.not-working", true);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CauldronListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CauldronListener.java
new file mode 100644
index 000000000..8fd51fc8a
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CauldronListener.java
@@ -0,0 +1,52 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * Cauldron.
+ * This is mainly used to prevent the discoloring of leather armor.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+public class CauldronListener implements SlimefunCraftingListener {
+
+ public CauldronListener(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
+ public void onCauldronUse(PlayerInteractEvent e) {
+ if (e.getAction() == Action.RIGHT_CLICK_BLOCK) {
+ Block block = e.getClickedBlock();
+
+ if (block.getType() == Material.CAULDRON) {
+ ItemStack item = e.getItem();
+
+ if (item != null && SlimefunTag.LEATHER_ARMOR.isTagged(item.getType())) {
+ SlimefunItem sfItem = SlimefunItem.getByItem(item);
+
+ if (isUnallowed(sfItem)) {
+ e.setCancelled(true);
+ SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "cauldron.no-discoloring");
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CraftingTableListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CraftingTableListener.java
new file mode 100644
index 000000000..e18b64d11
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/CraftingTableListener.java
@@ -0,0 +1,56 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+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.CraftItemEvent;
+import org.bukkit.event.inventory.PrepareItemCraftEvent;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * crafting table.
+ *
+ * @author TheBusyBiscuit
+ *
+ */
+public class CraftingTableListener implements SlimefunCraftingListener {
+
+ public CraftingTableListener(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler
+ public void onCraft(CraftItemEvent e) {
+ for (ItemStack item : e.getInventory().getContents()) {
+ SlimefunItem sfItem = SlimefunItem.getByItem(item);
+
+ if (sfItem != null && !sfItem.isUseableInWorkbench()) {
+ e.setResult(Result.DENY);
+ SlimefunPlugin.getLocalization().sendMessage((Player) e.getWhoClicked(), "workbench.not-enhanced", true);
+ break;
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPrepareCraft(PrepareItemCraftEvent e) {
+ if (e.getInventory().getResult() != null) {
+ for (ItemStack item : e.getInventory().getContents()) {
+ SlimefunItem sfItem = SlimefunItem.getByItem(item);
+
+ if (sfItem != null && !sfItem.isUseableInWorkbench()) {
+ e.getInventory().setResult(null);
+ break;
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/GrindstoneListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/GrindstoneListener.java
new file mode 100644
index 000000000..36db7e6eb
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/GrindstoneListener.java
@@ -0,0 +1,42 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nonnull;
+
+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.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+/**
+ * This {@link Listener} prevents any {@link SlimefunItem} from being used in a
+ * cartography table.
+ *
+ * @author NathanAdhitya
+ *
+ */
+public class GrindstoneListener implements SlimefunCraftingListener {
+
+ public GrindstoneListener(@Nonnull SlimefunPlugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onGrindstone(InventoryClickEvent e) {
+ if (e.getRawSlot() == 2 && e.getWhoClicked() instanceof Player && e.getInventory().getType() == InventoryType.GRINDSTONE) {
+ ItemStack item1 = e.getInventory().getContents()[0];
+ ItemStack item2 = e.getInventory().getContents()[1];
+
+ if (hasUnallowedItems(item1, item2)) {
+ e.setResult(Result.DENY);
+ }
+ }
+
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SlimefunCraftingListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SlimefunCraftingListener.java
new file mode 100644
index 000000000..6fdba5ab0
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SlimefunCraftingListener.java
@@ -0,0 +1,42 @@
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
+
+import javax.annotation.Nullable;
+
+import org.bukkit.event.Listener;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+interface SlimefunCraftingListener extends Listener {
+
+ default boolean hasUnallowedItems(@Nullable ItemStack item1, @Nullable ItemStack item2) {
+ if (SlimefunGuide.isGuideItem(item1) || SlimefunGuide.isGuideItem(item2)) {
+ return true;
+ } else {
+ SlimefunItem sfItem1 = SlimefunItem.getByItem(item1);
+ SlimefunItem sfItem2 = SlimefunItem.getByItem(item2);
+
+ if (isUnallowed(sfItem1) || isUnallowed(sfItem2)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ default boolean isUnallowed(@Nullable ItemStack item) {
+ if (item == null) {
+ return false;
+ }
+
+ SlimefunItem sfItem = SlimefunItem.getByItem(item);
+ return !(sfItem instanceof VanillaItem) && !sfItem.isDisabled();
+ }
+
+ default boolean isUnallowed(@Nullable SlimefunItem item) {
+ return item != null && !(item instanceof VanillaItem) && !item.isDisabled();
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/package-info.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/package-info.java
new file mode 100644
index 000000000..8c8f08ecc
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package holds every {@link org.bukkit.event.Listener} which is responsible for preventing that a
+ * {@link me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem} is used in an unallowed crafting operation
+ */
+package io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting;
\ No newline at end of file
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
index 723d8a548..e65701e5c 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
@@ -207,27 +207,8 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*
*/
public final class SlimefunItemSetup {
-
- private static final Material RED_DYE;
- private static final Material YELLOW_DYE;
- private static final Material BLACK_DYE;
- private static final Material GREEN_DYE;
-
+
private static boolean registeredItems = false;
-
- static {
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- RED_DYE = Material.RED_DYE;
- YELLOW_DYE = Material.YELLOW_DYE;
- BLACK_DYE = Material.BLACK_DYE;
- GREEN_DYE = Material.GREEN_DYE;
- } else {
- RED_DYE = Material.valueOf("ROSE_RED");
- YELLOW_DYE = Material.valueOf("DANDELION_YELLOW");
- BLACK_DYE = Material.valueOf("INK_SAC");
- GREEN_DYE = Material.valueOf("CACTUS_GREEN");
- }
- }
private SlimefunItemSetup() {}
@@ -238,7 +219,8 @@ public final class SlimefunItemSetup {
registeredItems = true;
DefaultCategories categories = new DefaultCategories();
-
+
+ // @formatter:off (We will need to refactor this one day)
new SlimefunItem(categories.weapons, SlimefunItems.GRANDMAS_WALKING_STICK, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, new ItemStack(Material.OAK_LOG), null, null, new ItemStack(Material.OAK_LOG), null, null, new ItemStack(Material.OAK_LOG), null})
.register(plugin);
@@ -797,21 +779,19 @@ public final class SlimefunItemSetup {
new ItemStack[] {null, null, SlimefunItems.LAVA_CRYSTAL, null, SlimefunItems.STAFF_ELEMENTAL, null, SlimefunItems.STAFF_ELEMENTAL, null, null})
.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new StormStaff(categories.magicalGadgets, SlimefunItems.STAFF_STORM, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {SlimefunItems.LIGHTNING_RUNE, SlimefunItems.ENDER_LUMP_3, SlimefunItems.LIGHTNING_RUNE, SlimefunItems.STAFF_WATER, SlimefunItems.MAGIC_SUGAR, SlimefunItems.STAFF_WIND, SlimefunItems.LIGHTNING_RUNE, SlimefunItems.ENDER_LUMP_3, SlimefunItems.LIGHTNING_RUNE})
- .register(plugin);
-
- ItemStack weaknessPotion = new ItemStack(Material.POTION);
- PotionMeta meta = (PotionMeta) weaknessPotion.getItemMeta();
- meta.setBasePotionData(new PotionData(PotionType.WEAKNESS, false, false));
- weaknessPotion.setItemMeta(meta);
-
- new MagicalZombiePills(categories.magicalGadgets, SlimefunItems.MAGICAL_ZOMBIE_PILLS, RecipeType.MAGIC_WORKBENCH,
- new ItemStack[] {new ItemStack(Material.GOLD_INGOT), SlimefunItems.MAGIC_LUMP_2, new ItemStack(Material.GOLD_INGOT), new ItemStack(Material.APPLE), weaknessPotion, new ItemStack(Material.APPLE), new ItemStack(Material.GOLD_INGOT), SlimefunItems.MAGIC_LUMP_2, new ItemStack(Material.GOLD_INGOT)},
- new SlimefunItemStack(SlimefunItems.MAGICAL_ZOMBIE_PILLS, 2))
- .register(plugin);
- }
+ new StormStaff(categories.magicalGadgets, SlimefunItems.STAFF_STORM, RecipeType.ANCIENT_ALTAR,
+ new ItemStack[] {SlimefunItems.LIGHTNING_RUNE, SlimefunItems.ENDER_LUMP_3, SlimefunItems.LIGHTNING_RUNE, SlimefunItems.STAFF_WATER, SlimefunItems.MAGIC_SUGAR, SlimefunItems.STAFF_WIND, SlimefunItems.LIGHTNING_RUNE, SlimefunItems.ENDER_LUMP_3, SlimefunItems.LIGHTNING_RUNE})
+ .register(plugin);
+
+ ItemStack weaknessPotion = new ItemStack(Material.POTION);
+ PotionMeta meta = (PotionMeta) weaknessPotion.getItemMeta();
+ meta.setBasePotionData(new PotionData(PotionType.WEAKNESS, false, false));
+ weaknessPotion.setItemMeta(meta);
+
+ new MagicalZombiePills(categories.magicalGadgets, SlimefunItems.MAGICAL_ZOMBIE_PILLS, RecipeType.MAGIC_WORKBENCH,
+ new ItemStack[] {new ItemStack(Material.GOLD_INGOT), SlimefunItems.MAGIC_LUMP_2, new ItemStack(Material.GOLD_INGOT), new ItemStack(Material.APPLE), weaknessPotion, new ItemStack(Material.APPLE), new ItemStack(Material.GOLD_INGOT), SlimefunItems.MAGIC_LUMP_2, new ItemStack(Material.GOLD_INGOT)},
+ new SlimefunItemStack(SlimefunItems.MAGICAL_ZOMBIE_PILLS, 2))
+ .register(plugin);
new SmeltersPickaxe(categories.tools, SlimefunItems.SMELTERS_PICKAXE, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.LAVA_CRYSTAL, SlimefunItems.LAVA_CRYSTAL, SlimefunItems.LAVA_CRYSTAL, null, SlimefunItems.FERROSILICON, null, null, SlimefunItems.FERROSILICON, null})
@@ -1036,9 +1016,7 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.HARDENED_METAL_INGOT, SlimefunItems.HARDENED_METAL_INGOT, SlimefunItems.HARDENED_METAL_INGOT, null, SlimefunItems.FERROSILICON, null, null, SlimefunItems.FERROSILICON, null})
.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new TableSaw(categories.basicMachines, SlimefunItems.TABLE_SAW).register(plugin);
- }
+ new TableSaw(categories.basicMachines, SlimefunItems.TABLE_SAW).register(plugin);
new SlimefunArmorPiece(categories.magicalArmor, SlimefunItems.SLIME_HELMET_STEEL, RecipeType.ARMOR_FORGE,
new ItemStack[] {new ItemStack(Material.SLIME_BALL), SlimefunItems.STEEL_PLATE, new ItemStack(Material.SLIME_BALL), new ItemStack(Material.SLIME_BALL), null, new ItemStack(Material.SLIME_BALL), null, null, null}, null)
@@ -1125,7 +1103,7 @@ public final class SlimefunItemSetup {
new RestoredBackpack(categories.usefulItems).register(plugin);
- new SlimefunItem(categories.technicalComponents, SlimefunItems.MAGNET, RecipeType.SMELTERY,
+ new UnplaceableBlock(categories.technicalComponents, SlimefunItems.MAGNET, RecipeType.SMELTERY,
new ItemStack[] {SlimefunItems.NICKEL_INGOT, SlimefunItems.ALUMINUM_DUST, SlimefunItems.IRON_DUST, SlimefunItems.COBALT_INGOT, null, null, null, null, null})
.register(plugin);
@@ -1268,11 +1246,9 @@ public final class SlimefunItemSetup {
new ItemStack[] {new ItemStack(Material.PUMPKIN), null, null, null, null, null, null, null, null})
.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new Juice(categories.food, SlimefunItems.SWEET_BERRY_JUICE, RecipeType.JUICER,
- new ItemStack[] {new ItemStack(Material.SWEET_BERRIES), null, null, null, null, null, null, null, null})
- .register(plugin);
- }
+ new Juice(categories.food, SlimefunItems.SWEET_BERRY_JUICE, RecipeType.JUICER,
+ new ItemStack[] {new ItemStack(Material.SWEET_BERRIES), null, null, null, null, null, null, null, null})
+ .register(plugin);
new Juice(categories.food, SlimefunItems.GOLDEN_APPLE_JUICE, RecipeType.JUICER,
new ItemStack[] {new ItemStack(Material.GOLDEN_APPLE), null, null, null, null, null, null, null, null})
@@ -1338,15 +1314,15 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.CARBONADO, SlimefunItems.BASIC_CIRCUIT_BOARD, SlimefunItems.CARBONADO, SlimefunItems.HEATING_COIL, SlimefunItems.REINFORCED_FURNACE, SlimefunItems.HEATING_COIL, SlimefunItems.CARBONADO, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.CARBONADO})
.register(plugin);
- new SlimefunItem(categories.technicalComponents, SlimefunItems.ELECTRO_MAGNET, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new UnplaceableBlock(categories.technicalComponents, SlimefunItems.ELECTRO_MAGNET, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.NICKEL_INGOT, SlimefunItems.MAGNET, SlimefunItems.COBALT_INGOT, null, SlimefunItems.BATTERY, null, null, null, null})
.register(plugin);
- new SlimefunItem(categories.technicalComponents, SlimefunItems.ELECTRIC_MOTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new UnplaceableBlock(categories.technicalComponents, SlimefunItems.ELECTRIC_MOTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, null, SlimefunItems.ELECTRO_MAGNET, null, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE})
.register(plugin);
- new SlimefunItem(categories.technicalComponents, SlimefunItems.HEATING_COIL, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new UnplaceableBlock(categories.technicalComponents, SlimefunItems.HEATING_COIL, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE, SlimefunItems.COPPER_WIRE})
.register(plugin);
@@ -1490,7 +1466,7 @@ public final class SlimefunItemSetup {
new SlimefunItemStack(SlimefunItems.HARDENED_GLASS, 16))
.register(plugin);
- new SlimefunItem(categories.technicalComponents, SlimefunItems.COOLING_UNIT, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new UnplaceableBlock(categories.technicalComponents, SlimefunItems.COOLING_UNIT, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {new ItemStack(Material.ICE), new ItemStack(Material.ICE), new ItemStack(Material.ICE), SlimefunItems.ALUMINUM_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.ALUMINUM_INGOT, new ItemStack(Material.ICE), new ItemStack(Material.ICE), new ItemStack(Material.ICE)})
.register(plugin);
@@ -1999,11 +1975,9 @@ public final class SlimefunItemSetup {
}.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new AutoDrier(categories.electricity, SlimefunItems.AUTO_DRIER, RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[]{null, null, null, SlimefunItems.HEATING_COIL, new ItemStack(Material.SMOKER), SlimefunItems.HEATING_COIL, null, new ItemStack(Material.CAMPFIRE), null})
- .register(plugin);
- }
+ new AutoDrier(categories.electricity, SlimefunItems.AUTO_DRIER, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new ItemStack[]{null, null, null, SlimefunItems.HEATING_COIL, new ItemStack(Material.SMOKER), SlimefunItems.HEATING_COIL, null, new ItemStack(Material.CAMPFIRE), null})
+ .register(plugin);
new AutoBrewer(categories.electricity, SlimefunItems.AUTO_BREWER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, SlimefunItems.HEATING_COIL, null, SlimefunItems.REINFORCED_PLATE, new ItemStack(Material.BREWING_STAND), SlimefunItems.REINFORCED_PLATE, null, SlimefunItems.ELECTRIC_MOTOR, null}) {
@@ -2292,7 +2266,7 @@ public final class SlimefunItemSetup {
.register(plugin);
new SlimefunItem(categories.magicalResources, SlimefunItems.RAINBOW_RUNE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.MAGIC_LUMP_3, new ItemStack(Material.CYAN_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.ENDER_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(YELLOW_DYE), SlimefunItems.ENDER_LUMP_3, new ItemStack(Material.MAGENTA_DYE)})
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.MAGIC_LUMP_3, new ItemStack(Material.CYAN_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.ENDER_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.YELLOW_DYE), SlimefunItems.ENDER_LUMP_3, new ItemStack(Material.MAGENTA_DYE)})
.register(plugin);
new SoulboundRune(categories.magicalResources, SlimefunItems.SOULBOUND_RUNE, RecipeType.ANCIENT_ALTAR,
@@ -2361,96 +2335,96 @@ public final class SlimefunItemSetup {
// Christmas
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_WOOL_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_WOOL_XMAS, 2), new RainbowTickHandler(Material.RED_WOOL, Material.GREEN_WOOL))
.register(plugin);
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_GLASS_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_XMAS, 2), new RainbowTickHandler(Material.RED_STAINED_GLASS, Material.GREEN_STAINED_GLASS))
.register(plugin);
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_GLASS_PANE_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_PANE_XMAS, 2), new RainbowTickHandler(Material.RED_STAINED_GLASS_PANE, Material.GREEN_STAINED_GLASS_PANE))
.register(plugin);
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_CLAY_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CLAY_XMAS, 2), new RainbowTickHandler(Material.RED_TERRACOTTA, Material.GREEN_TERRACOTTA))
.register(plugin);
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_CONCRETE_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CONCRETE_XMAS, 2), new RainbowTickHandler(Material.RED_CONCRETE, Material.GREEN_CONCRETE))
.register(plugin);
new RainbowBlock(categories.christmas, SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_XMAS, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(GREEN_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.GREEN_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.GREEN_DYE), SlimefunItems.CHRISTMAS_COOKIE, new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_XMAS, 2), new RainbowTickHandler(Material.RED_GLAZED_TERRACOTTA, Material.GREEN_GLAZED_TERRACOTTA))
.register(plugin);
// Valentines Day
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_WOOL_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_WOOL_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_WOOL, Material.PINK_WOOL))
.register(plugin);
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_GLASS_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_STAINED_GLASS, Material.PINK_STAINED_GLASS))
.register(plugin);
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_GLASS_PANE_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_PANE_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_STAINED_GLASS_PANE, Material.PINK_STAINED_GLASS_PANE))
.register(plugin);
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_CLAY_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CLAY_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_TERRACOTTA, Material.PINK_TERRACOTTA))
.register(plugin);
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_CONCRETE_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CONCRETE_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_CONCRETE, Material.PINK_CONCRETE))
.register(plugin);
new RainbowBlock(categories.valentinesDay, SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_VALENTINE, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(RED_DYE)},
+ new ItemStack[] {new ItemStack(Material.RED_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.PINK_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.PINK_DYE), new ItemStack(Material.POPPY), new ItemStack(Material.RED_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_VALENTINE, 2), new RainbowTickHandler(Material.MAGENTA_GLAZED_TERRACOTTA, Material.PINK_GLAZED_TERRACOTTA))
.register(plugin);
// Halloween
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_WOOL_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_WOOL_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_WOOL, Material.BLACK_WOOL))
.register(plugin);
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_GLASS_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_STAINED_GLASS, Material.BLACK_STAINED_GLASS))
.register(plugin);
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_GLASS_PANE_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_PANE_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_STAINED_GLASS_PANE, Material.BLACK_STAINED_GLASS_PANE))
.register(plugin);
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_CLAY_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CLAY_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_TERRACOTTA, Material.BLACK_TERRACOTTA))
.register(plugin);
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_CONCRETE_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CONCRETE_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_CONCRETE, Material.BLACK_CONCRETE))
.register(plugin);
new RainbowBlock(categories.halloween, SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_HALLOWEEN, RecipeType.ANCIENT_ALTAR,
- new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(BLACK_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
+ new ItemStack[] {new ItemStack(Material.ORANGE_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.BLACK_DYE), new ItemStack(Material.PUMPKIN), new ItemStack(Material.ORANGE_DYE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLAZED_TERRACOTTA_HALLOWEEN, 2), new RainbowTickHandler(Material.ORANGE_GLAZED_TERRACOTTA, Material.BLACK_GLAZED_TERRACOTTA))
.register(plugin);
@@ -2688,10 +2662,8 @@ public final class SlimefunItemSetup {
new OrganicFood(categories.misc, SlimefunItems.APPLE_ORGANIC_FOOD, Material.APPLE)
.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new OrganicFood(categories.misc, SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD, Material.SWEET_BERRIES)
- .register(plugin);
- }
+ new OrganicFood(categories.misc, SlimefunItems.SWEET_BERRIES_ORGANIC_FOOD, Material.SWEET_BERRIES)
+ .register(plugin);
new OrganicFood(categories.misc, SlimefunItems.KELP_ORGANIC_FOOD, Material.DRIED_KELP)
.register(plugin);
@@ -2906,7 +2878,7 @@ public final class SlimefunItemSetup {
}.register(plugin);
- new SlimefunItem(categories.cargo, SlimefunItems.CARGO_MOTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new UnplaceableBlock(categories.cargo, SlimefunItems.CARGO_MOTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.HARDENED_GLASS, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.HARDENED_GLASS, SlimefunItems.SILVER_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.SILVER_INGOT, SlimefunItems.HARDENED_GLASS, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.HARDENED_GLASS},
new SlimefunItemStack(SlimefunItems.CARGO_MOTOR, 4))
.register(plugin);
@@ -3069,11 +3041,9 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.BLISTERING_INGOT_3, new ItemStack(Material.NETHER_STAR), SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.WITHER_PROOF_OBSIDIAN, SlimefunItems.ANDROID_MEMORY_CORE, SlimefunItems.WITHER_PROOF_OBSIDIAN, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.REINFORCED_ALLOY_INGOT, SlimefunItems.CARBONADO_EDGED_CAPACITOR})
.register(plugin);
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- new TapeMeasure(categories.usefulItems, SlimefunItems.TAPE_MEASURE, RecipeType.ENHANCED_CRAFTING_TABLE,
- new ItemStack[] {SlimefunItems.SILICON, new ItemStack(Material.YELLOW_DYE), SlimefunItems.SILICON, new ItemStack(Material.YELLOW_DYE), new ItemStack(Material.STRING), new ItemStack(Material.YELLOW_DYE), SlimefunItems.GILDED_IRON, new ItemStack(Material.YELLOW_DYE), SlimefunItems.SILICON})
- .register(plugin);
- }
+ new TapeMeasure(categories.usefulItems, SlimefunItems.TAPE_MEASURE, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new ItemStack[] {SlimefunItems.SILICON, new ItemStack(Material.YELLOW_DYE), SlimefunItems.SILICON, new ItemStack(Material.YELLOW_DYE), new ItemStack(Material.STRING), new ItemStack(Material.YELLOW_DYE), SlimefunItems.GILDED_IRON, new ItemStack(Material.YELLOW_DYE), SlimefunItems.SILICON})
+ .register(plugin);
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
new StrangeNetherGoo(categories.magicalResources, SlimefunItems.STRANGE_NETHER_GOO, RecipeType.BARTER_DROP,
@@ -3089,6 +3059,8 @@ public final class SlimefunItemSetup {
new ElytraCap(categories.magicalArmor, SlimefunItems.ELYTRA_CAP, RecipeType.ARMOR_FORGE,
new ItemStack[]{new ItemStack(Material.SLIME_BALL), new ItemStack(Material.SLIME_BALL), new ItemStack(Material.SLIME_BALL), SlimefunItems.ELYTRA_SCALE, SlimefunItems.ELYTRA_SCALE, SlimefunItems.ELYTRA_SCALE, new ItemStack(Material.SLIME_BALL), new ItemStack(Material.LEATHER_HELMET), new ItemStack(Material.SLIME_BALL)})
.register(plugin);
+
+ // @formatter:on
}
private static void registerArmorSet(Category category, ItemStack baseComponent, ItemStack[] items, String idSyntax, boolean vanilla, PotionEffect[][] effects, SlimefunAddon addon) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChestMenuUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChestMenuUtils.java
index 7f566db35..0cb2ea26f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChestMenuUtils.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChestMenuUtils.java
@@ -29,6 +29,9 @@ public final class ChestMenuUtils {
private static final ItemStack INPUT_SLOT = new SlimefunItemStack("_UI_INPUT_SLOT", Material.CYAN_STAINED_GLASS_PANE, " ");
private static final ItemStack OUTPUT_SLOT = new SlimefunItemStack("_UI_OUTPUT_SLOT", Material.ORANGE_STAINED_GLASS_PANE, " ");
+ private static final ItemStack NO_PERMISSION = new SlimefunItemStack("_UI_NO_PERMISSION", Material.BARRIER, "No Permission");
+ private static final ItemStack NOT_RESEARCHED = new SlimefunItemStack("_UI_NOT_RESEARCHED", Material.BARRIER, "Not researched");
+
private static final ItemStack BACK_BUTTON = new SlimefunItemStack("_UI_BACK", Material.ENCHANTED_BOOK, "&7\u21E6 Back", meta -> meta.addItemFlags(ItemFlag.HIDE_ENCHANTS));
private static final ItemStack MENU_BUTTON = new SlimefunItemStack("_UI_MENU", Material.COMPARATOR, "&eSettings / Info", "", "&7\u21E8 Click to see more");
private static final ItemStack SEARCH_BUTTON = new SlimefunItemStack("_UI_SEARCH", Material.NAME_TAG, "&bSearch");
@@ -46,6 +49,16 @@ public final class ChestMenuUtils {
return UI_BACKGROUND;
}
+ @Nonnull
+ public static ItemStack getNoPermissionItem() {
+ return NO_PERMISSION;
+ }
+
+ @Nonnull
+ public static ItemStack getNotResearchedItem() {
+ return NOT_RESEARCHED;
+ }
+
@Nonnull
public static ItemStack getInputSlotTexture() {
return INPUT_SLOT;
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterials.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterials.java
index 274f0ed09..7b4f8de31 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterials.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterials.java
@@ -4,6 +4,9 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import javax.annotation.Nonnull;
+
+import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
@@ -24,11 +27,13 @@ public final class ColoredMaterials {
* constructor to be private.
*/
private ColoredMaterials() {}
+
+ // @formatter:off (We want this to stay formatted like this)
/**
* This {@link List} contains all wool colors ordered by their appearance ingame.
*/
- public static final List WOOL = Collections.unmodifiableList(Arrays.asList(
+ public static final List WOOL = asList(new Material[] {
Material.WHITE_WOOL,
Material.ORANGE_WOOL,
Material.MAGENTA_WOOL,
@@ -45,12 +50,12 @@ public final class ColoredMaterials {
Material.GREEN_WOOL,
Material.RED_WOOL,
Material.BLACK_WOOL
- ));
+ });
/**
* This {@link List} contains all stained glass colors ordered by their appearance ingame.
*/
- public static final List STAINED_GLASS = Collections.unmodifiableList(Arrays.asList(
+ public static final List STAINED_GLASS = asList(new Material[] {
Material.WHITE_STAINED_GLASS,
Material.ORANGE_STAINED_GLASS,
Material.MAGENTA_STAINED_GLASS,
@@ -67,12 +72,12 @@ public final class ColoredMaterials {
Material.GREEN_STAINED_GLASS,
Material.RED_STAINED_GLASS,
Material.BLACK_STAINED_GLASS
- ));
+ });
/**
* This {@link List} contains all stained glass pane colors ordered by their appearance ingame.
*/
- public static final List STAINED_GLASS_PANE = Collections.unmodifiableList(Arrays.asList(
+ public static final List STAINED_GLASS_PANE = asList(new Material[] {
Material.WHITE_STAINED_GLASS_PANE,
Material.ORANGE_STAINED_GLASS_PANE,
Material.MAGENTA_STAINED_GLASS_PANE,
@@ -89,12 +94,12 @@ public final class ColoredMaterials {
Material.GREEN_STAINED_GLASS_PANE,
Material.RED_STAINED_GLASS_PANE,
Material.BLACK_STAINED_GLASS_PANE
- ));
+ });
/**
* This {@link List} contains all terracotta colors ordered by their appearance ingame.
*/
- public static final List TERRACOTTA = Collections.unmodifiableList(Arrays.asList(
+ public static final List TERRACOTTA = asList(new Material[] {
Material.WHITE_TERRACOTTA,
Material.ORANGE_TERRACOTTA,
Material.MAGENTA_TERRACOTTA,
@@ -111,12 +116,12 @@ public final class ColoredMaterials {
Material.GREEN_TERRACOTTA,
Material.RED_TERRACOTTA,
Material.BLACK_TERRACOTTA
- ));
+ });
/**
* This {@link List} contains all glazed terracotta colors ordered by their appearance ingame.
*/
- public static final List GLAZED_TERRACOTTA = Collections.unmodifiableList(Arrays.asList(
+ public static final List GLAZED_TERRACOTTA = asList(new Material[] {
Material.WHITE_GLAZED_TERRACOTTA,
Material.ORANGE_GLAZED_TERRACOTTA,
Material.MAGENTA_GLAZED_TERRACOTTA,
@@ -133,12 +138,12 @@ public final class ColoredMaterials {
Material.GREEN_GLAZED_TERRACOTTA,
Material.RED_GLAZED_TERRACOTTA,
Material.BLACK_GLAZED_TERRACOTTA
- ));
+ });
/**
* This {@link List} contains all concrete colors ordered by their appearance ingame.
*/
- public static final List CONCRETE = Collections.unmodifiableList(Arrays.asList(
+ public static final List CONCRETE = asList(new Material[] {
Material.WHITE_CONCRETE,
Material.ORANGE_CONCRETE,
Material.MAGENTA_CONCRETE,
@@ -155,6 +160,16 @@ public final class ColoredMaterials {
Material.GREEN_CONCRETE,
Material.RED_CONCRETE,
Material.BLACK_CONCRETE
- ));
+ });
+
+ // @formatter:on
+
+ @Nonnull
+ private static List asList(@Nonnull Material[] materials) {
+ Validate.noNullElements(materials, "The List cannot contain any null elements");
+ Validate.isTrue(materials.length == 16, "Expected 16, received: " + materials.length + ". Did you miss a color?");
+
+ return Collections.unmodifiableList(Arrays.asList(materials));
+ }
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java
index ea095a5d7..ee8a849d0 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java
@@ -108,7 +108,8 @@ public enum HeadTexture {
CARGO_ARROW_RIGHT("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516"),
ADD_NEW_LANGUAGE("3edd20be93520949e6ce789dc4f43efaeb28c717ee6bfcbbe02780142f716"),
IRON_GOLEM("89091d79ea0f59ef7ef94d7bba6e5f17f2f7d4572c44f90f76c4819a714"),
- PIGLIN_HEAD("2882af1294a74023e6919a31d1a027310f2e142afb4667d230d155e7f21dbb41");
+ PIGLIN_HEAD("2882af1294a74023e6919a31d1a027310f2e142afb4667d230d155e7f21dbb41"),
+ NECROTIC_SKULL("7953b6c68448e7e6b6bf8fb273d7203acd8e1be19e81481ead51f45de59a8");
public static final HeadTexture[] valuesCache = values();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java
index a84293946..d752b5ec8 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java
@@ -1,6 +1,7 @@
package io.github.thebusybiscuit.slimefun4.utils;
import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.time.Duration;
import java.time.LocalDateTime;
@@ -12,16 +13,51 @@ import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
+/**
+ * This class contains various utilities related to numbers and number formatting.
+ *
+ * @author TheBusyBiscuit
+ * @author Walshy
+ *
+ */
public final class NumberUtils {
- private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##");
+ /**
+ * This is our {@link DecimalFormat} for decimal values.
+ */
+ private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.ROOT));
+ /**
+ * We do not want any instance of this to be created.
+ */
private NumberUtils() {}
- public static String formatBigNumber(int i) {
- return NumberFormat.getNumberInstance(Locale.US).format(i);
+ /**
+ * This method formats a given {@link Integer} to be displayed nicely with
+ * decimal digit grouping.
+ * {@code 1000000} for example will return {@code "1,000,000"} as a {@link String}.
+ * It uses the american (US) {@link Locale} for this transformation.
+ *
+ * @param number
+ * Your {@link Integer}
+ *
+ * @return The formatted String
+ */
+ @Nonnull
+ public static String formatBigNumber(int number) {
+ return NumberFormat.getNumberInstance(Locale.US).format(number);
}
+ /**
+ * This method transforms a String representation of a {@link LocalDateTime}
+ * from GitHub's API back into a {@link LocalDateTime} object
+ *
+ * @param date
+ * The formatted String version of a date from GitHub
+ *
+ * @return The {@link LocalDateTime} for the given input
+ */
+ @Nonnull
public static LocalDateTime parseGitHubDate(@Nonnull String date) {
Validate.notNull(date, "Provided date was null");
return LocalDateTime.parse(date.substring(0, date.length() - 1));
@@ -37,6 +73,7 @@ public final class NumberUtils {
*
* @return A representative {@link ChatColor}
*/
+ @Nonnull
public static ChatColor getColorFromPercentage(float percentage) {
if (percentage < 16.0F) {
return ChatColor.DARK_RED;
@@ -53,13 +90,51 @@ public final class NumberUtils {
}
}
+ /**
+ * This returns the elapsed time since the given {@link LocalDateTime}.
+ * The output will be nicely formatted based on the elapsed hours or days since the
+ * given {@link LocalDateTime}.
+ *
+ * If a {@link LocalDateTime} from yesterday was passed it will return {@code "1d"}.
+ * One hour later it will read {@code "1d 1h"}. For values smaller than an hour {@code "< 1h"}
+ * will be returned instead.
+ *
+ * @param date
+ * The {@link LocalDateTime}.
+ *
+ * @return The elapsed time as a {@link String}
+ */
+ @Nonnull
public static String getElapsedTime(@Nonnull LocalDateTime date) {
- Validate.notNull(date, "Provided date was null");
- long hours = Duration.between(date, LocalDateTime.now()).toHours();
+ return getElapsedTime(LocalDateTime.now(), date);
+ }
+
+ /**
+ * This returns the elapsed time between the two given {@link LocalDateTime LocalDateTimes}.
+ * The output will be nicely formatted based on the elapsed hours or days between the
+ * given {@link LocalDateTime LocalDateTime}.
+ *
+ * If a {@link LocalDateTime} from today and yesterday (exactly 24h apart) was passed it
+ * will return {@code "1d"}.
+ * One hour later it will read {@code "1d 1h"}. For values smaller than an hour {@code "< 1h"}
+ * will be returned instead.
+ *
+ * @param start
+ * The starting {@link LocalDateTime}.
+ * @param end
+ * The ending {@link LocalDateTime}.
+ *
+ * @return The elapsed time as a {@link String}
+ */
+ @Nonnull
+ public static String getElapsedTime(@Nonnull LocalDateTime start, @Nonnull LocalDateTime end) {
+ Validate.notNull(start, "Provided start was null");
+ Validate.notNull(end, "Provided end was null");
+ long hours = Duration.between(start, end).toHours();
if (hours == 0) {
return "< 1h";
- } else if ((hours / 24) == 0) {
+ } else if (hours / 24 == 0) {
return (hours % 24) + "h";
} else if (hours % 24 == 0) {
return (hours / 24) + "d";
@@ -68,10 +143,12 @@ public final class NumberUtils {
}
}
+ @Nonnull
public static String getTimeLeft(int seconds) {
String timeleft = "";
int minutes = (int) (seconds / 60L);
+
if (minutes > 0) {
timeleft += minutes + "m ";
}
@@ -80,14 +157,27 @@ public final class NumberUtils {
return timeleft + seconds + "s";
}
- public static int getInt(String str, int defaultValue) {
+ /**
+ * This method parses a {@link String} into an {@link Integer}.
+ * If the {@link String} could not be parsed correctly, the provided
+ * default value will be returned instead.
+ *
+ * @param str
+ * The {@link String} to parse
+ * @param defaultValue
+ * The default value for when the {@link String} could not be parsed
+ *
+ * @return The resulting {@link Integer}
+ */
+ public static int getInt(@Nonnull String str, int defaultValue) {
if (PatternUtils.NUMERIC.matcher(str).matches()) {
return Integer.parseInt(str);
+ } else {
+ return defaultValue;
}
-
- return defaultValue;
}
+ @Nonnull
public static String getAsMillis(long nanoseconds) {
if (nanoseconds == 0) {
return "0ms";
@@ -129,6 +219,8 @@ public final class NumberUtils {
* The value to clamp
* @param max
* The maximum value
+ *
+ * @return The clamped value
*/
public static int clamp(int min, int value, int max) {
if (value < min) {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java
index 8c90ef203..05046d5d8 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java
@@ -121,7 +121,7 @@ public final class SlimefunUtils {
}
private static boolean hasSoulboundFlag(@Nullable ItemMeta meta) {
- if (meta != null && SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
+ if (meta != null) {
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(SOULBOUND_KEY, PersistentDataType.BYTE)) {
@@ -154,16 +154,14 @@ public final class SlimefunUtils {
boolean isSoulbound = isSoulbound(item);
ItemMeta meta = item.getItemMeta();
- if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
- PersistentDataContainer container = meta.getPersistentDataContainer();
+ PersistentDataContainer container = meta.getPersistentDataContainer();
- if (makeSoulbound && !isSoulbound) {
- container.set(SOULBOUND_KEY, PersistentDataType.BYTE, (byte) 1);
- }
+ if (makeSoulbound && !isSoulbound) {
+ container.set(SOULBOUND_KEY, PersistentDataType.BYTE, (byte) 1);
+ }
- if (!makeSoulbound && isSoulbound) {
- container.remove(SOULBOUND_KEY);
- }
+ if (!makeSoulbound && isSoulbound) {
+ container.remove(SOULBOUND_KEY);
}
List lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java
index 98e0340b5..289314298 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java
@@ -35,9 +35,9 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.tools.SmeltersPic
* extensions of the default Minecraft tags.
* The actual tag files are located in the {@literal /src/main/resources/tags} directory
* and follow Minecraft's tags.json format.
- *
+ *
* @author TheBusyBiscuit
- *
+ *
* @see TagParser
*
*/
@@ -48,6 +48,11 @@ public enum SlimefunTag implements Tag {
*/
ORES,
+ /**
+ * All minecraft ores that can be affected by fortune.
+ */
+ FORTUNE_COMPATIBLE_ORES,
+
/**
* All Shulker boxes, normal and colored.
*/
@@ -63,6 +68,11 @@ public enum SlimefunTag implements Tag {
*/
MUSHROOMS,
+ /**
+ * All leather armor materials
+ */
+ LEATHER_ARMOR,
+
/**
* Every glass variant, includes both blocks and panes.
* Also stained glass and stained glass panes.
@@ -99,12 +109,28 @@ public enum SlimefunTag implements Tag {
*/
STONE_VARIANTS,
+ /**
+ * All dirt variants. Dirt, coarse dirt, grass, mycelium.
+ * This also includes farmland and grass paths.
+ */
+ DIRT_VARIANTS,
+
/**
* All variants of concrete powder.
* Can you believe there is no tag for this already?
*/
CONCRETE_POWDERS,
+ /**
+ * All the types of pressure plates.
+ */
+ PRESSURE_PLATES,
+
+ /**
+ * All tall flowers because minecraft doesn't have a tag for this
+ */
+ TALL_FLOWERS,
+
/**
* Materials which are sensitive to break.
* Things like Saplings or Pressure plates which break as well when you break
@@ -203,7 +229,7 @@ public enum SlimefunTag implements Tag {
/**
* This method reloads this {@link SlimefunTag} from our resources directory.
- *
+ *
* @throws TagMisconfigurationException
* This is thrown whenever a {@link SlimefunTag} could not be parsed properly
*/
@@ -220,11 +246,11 @@ public enum SlimefunTag implements Tag {
/**
* This method reloads every single {@link SlimefunTag} from the resources directory.
* It is equivalent to running {@link #reload()} on every single {@link SlimefunTag} manually.
- *
+ *
* Do keep in mind though that any misconfigured {@link SlimefunTag} will abort the entire
* method and throw a {@link TagMisconfigurationException}. So one faulty {@link SlimefunTag}
* will stop the reloading process.
- *
+ *
* @throws TagMisconfigurationException
* This is thrown if one of the {@link SlimefunTag SlimefunTags} could not be parsed correctly
*/
@@ -277,9 +303,9 @@ public enum SlimefunTag implements Tag {
/**
* This returns a {@link Set} of {@link Tag Tags} which are children of this {@link SlimefunTag},
* these can be other {@link SlimefunTag SlimefunTags} or regular {@link Tag Tags}.
- *
+ *
* The returned {@link Set} is immutable
- *
+ *
* @return An immutable {@link Set} of all sub tags.
*/
@Nonnull
@@ -289,7 +315,7 @@ public enum SlimefunTag implements Tag {
/**
* This method returns an Array representation for this {@link SlimefunTag}.
- *
+ *
* @return A {@link Material} array for this {@link Tag}
*/
@Nonnull
@@ -299,7 +325,7 @@ public enum SlimefunTag implements Tag {
/**
* This returns a {@link Stream} of {@link Material Materials} for this {@link SlimefunTag}.
- *
+ *
* @return A {@link Stream} of {@link Material Materials}
*/
@Nonnull
@@ -315,7 +341,7 @@ public enum SlimefunTag implements Tag {
*
* @param value
* The value which you would like to look up.
- *
+ *
* @return The {@link SlimefunTag} or null if it does not exist.
*/
@Nullable
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java
index c69a682ec..8c788e94f 100644
--- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java
+++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java
@@ -134,6 +134,7 @@ public class Category implements Keyed {
*
* @param p
* The Player to create this {@link ItemStack} for
+ *
* @return A localized display item for this {@link Category}
*/
@Nonnull
@@ -166,6 +167,26 @@ public class Category implements Keyed {
return ChatColor.stripColor(item.getItemMeta().getDisplayName());
}
+ /**
+ * This returns the localized display name of this {@link Category} for the given {@link Player}.
+ * The method will fall back to {@link #getUnlocalizedName()} if no translation was found.
+ *
+ * @param p
+ * The {@link Player} who to translate the name for
+ *
+ * @return The localized name of this {@link Category}
+ */
+ @Nonnull
+ public String getDisplayName(@Nonnull Player p) {
+ String localized = SlimefunPlugin.getLocalization().getCategoryName(p, getKey());
+
+ if (localized != null) {
+ return localized;
+ } else {
+ return getUnlocalizedName();
+ }
+ }
+
/**
* Returns all instances of {@link SlimefunItem} bound to this {@link Category}.
*
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java
index daf180de3..b6e36dcd8 100644
--- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java
+++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java
@@ -5,9 +5,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
+import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@@ -238,31 +241,30 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
BlockMenu inv = BlockStorage.getInventory(b);
if (isProcessing(b)) {
- int timeleft = progress.get(b);
- if (timeleft > 0) {
- ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
+ if (takeCharge(b.getLocation())) {
- if (isChargeable()) {
- if (getCharge(b.getLocation()) < getEnergyConsumption()) {
- return;
+ int timeleft = progress.get(b);
+
+ if (timeleft > 0) {
+ ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
+
+ progress.put(b, timeleft - 1);
+ } else {
+
+ inv.replaceExistingItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "));
+
+ for (ItemStack output : processing.get(b).getOutput()) {
+ inv.pushItem(output.clone(), getOutputSlots());
}
- removeCharge(b.getLocation(), getEnergyConsumption());
+ Bukkit.getPluginManager().callEvent(new AsyncMachineProcessCompleteEvent(b.getLocation(), AContainer.this, getProcessing(b)));
+
+ progress.remove(b);
+ processing.remove(b);
}
- progress.put(b, timeleft - 1);
- } else {
- inv.replaceExistingItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "));
-
- for (ItemStack output : processing.get(b).getOutput()) {
- inv.pushItem(output.clone(), getOutputSlots());
- }
-
- Bukkit.getPluginManager().callEvent(new AsyncMachineProcessCompleteEvent(b.getLocation(), AContainer.this, getProcessing(b)));
-
- progress.remove(b);
- processing.remove(b);
}
+
} else {
MachineRecipe next = findNextRecipe(inv);
@@ -273,6 +275,26 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
}
}
+ /**
+ * This method will remove charge from a location if it is chargeable.
+ *
+ * @param l
+ * location to try to remove charge from
+ * @return Whether charge was taken if its chargeable
+ */
+ protected boolean takeCharge(@Nonnull Location l) {
+ Validate.notNull(l, "Can't attempt to take charge from a null location!");
+
+ if (isChargeable()) {
+ if (getCharge(l) < getEnergyConsumption()) {
+ return false;
+ }
+
+ removeCharge(l, getEnergyConsumption());
+ }
+ return true;
+ }
+
protected MachineRecipe findNextRecipe(BlockMenu inv) {
Map inventory = new HashMap<>();
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java
index 8de896dc1..de0c283a3 100644
--- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java
+++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java
@@ -19,7 +19,7 @@ import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
* @deprecated This interface is not designed to be used by addons.
*
*/
-@Deprecated
+// @Deprecated - commented out because we are not ready to send out warnings yet
public interface InventoryBlock {
/**
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index bad81f55d..c9090a91c 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -40,7 +40,6 @@ networks:
items:
talismans: true
- backpacks: true
soulbound: true
metrics:
diff --git a/src/main/resources/languages/categories_he.yml b/src/main/resources/languages/categories_he.yml
index 70c1547a9..492b733a6 100644
--- a/src/main/resources/languages/categories_he.yml
+++ b/src/main/resources/languages/categories_he.yml
@@ -23,3 +23,4 @@ slimefun:
easter: חג הפסחא (אפריל)
birthday: יום הולדתו של TheBusyBiscuit (26 באוקטובר)
halloween: ליל כל הקדושים (31 באוקטובר)
+ androids: רובוטים ניתנים לתכנות
diff --git a/src/main/resources/languages/messages_en.yml b/src/main/resources/languages/messages_en.yml
index 99df15b23..6962c5e67 100644
--- a/src/main/resources/languages/messages_en.yml
+++ b/src/main/resources/languages/messages_en.yml
@@ -265,6 +265,7 @@ machines:
anvil:
not-working: '&4You cannot use Slimefun items in an anvil!'
+ mcmmo-salvaging: '&4You cannot salvage Slimefun items!'
brewing_stand:
not-working: '&4You cannot use Slimefun items in a brewing stand!'
@@ -282,6 +283,9 @@ backpack:
workbench:
not-enhanced: '&4You cannot use Slimefun items in a normal workbench'
+cauldron:
+ no-discoloring: '&4You cannot discolor Slimefun Armor'
+
gps:
deathpoint: '&4Deathpoint &7%date%'
waypoint:
diff --git a/src/main/resources/languages/messages_fr.yml b/src/main/resources/languages/messages_fr.yml
index 80d93db36..797238f77 100644
--- a/src/main/resources/languages/messages_fr.yml
+++ b/src/main/resources/languages/messages_fr.yml
@@ -255,6 +255,7 @@ machines:
anvil:
not-working: "&4Vous ne pouvez pas utiliser des objets Slimefun dans une enclume
!"
+ mcmmo-salvaging: "&4Vous ne pouvez pas recycler des objets Slimefun !"
backpack:
already-open: "&cDésolé, ce Backpack est ouvert quelque part ailleurs !"
no-stack: "&cVous ne pouvez pas stack les Backpacks"
@@ -340,6 +341,7 @@ languages:
zh-CN: Chinois (Chine)
el: Grec
he: Hébreu
+ pt: Portugais (Portugal)
ar: Arabe
af: Afrikaans
da: Danois
@@ -351,7 +353,6 @@ languages:
fa: Persan
th: Thaï
ro: Roumain
- pt: Portugais (Portugal)
pt-BR: Portugais (Brésil)
bg: Bulgare
ko: Coréen
@@ -369,5 +370,7 @@ villagers:
cartography_table:
not-working: "&4Vous ne pouvez pas utiliser d'objets Slimefun dans une table de
cartographie !"
+cauldron:
+ no-discoloring: "&4Vous ne pouvez pas décolorer une armure Slimefun"
miner:
no-ores: "&eDésolé, je n'ai pas pu trouver de minerai à proximité !"
diff --git a/src/main/resources/languages/messages_hu.yml b/src/main/resources/languages/messages_hu.yml
index 8320c757b..5bfa56bdd 100644
--- a/src/main/resources/languages/messages_hu.yml
+++ b/src/main/resources/languages/messages_hu.yml
@@ -244,6 +244,7 @@ machines:
finished: Az Industrial Miner-ed kész! Összesen %ores% ércet szerzett!
anvil:
not-working: "&4Nem használhatsz Slimefun tárgyakat az üllőben!"
+ mcmmo-salvaging: "&4Nem hasznosíthatsz újra Slimefun tárgyakat!"
backpack:
already-open: "&cSajnáljuk, ez a hátizsák valahol máshol már nyitva van!"
no-stack: "&cNem halmozhatsz hátizsákokat"
@@ -306,7 +307,7 @@ android:
rating:
own: "&4Nem értékelheted a saját szkriptedet!"
already: "&4Ezt a szkriptet már értékelted!"
- editor: Szkript Szerkesztő
+ editor: Szkript szerkesztő
languages:
default: Szerver-alapértelmezett
en: Angol
@@ -328,7 +329,6 @@ languages:
zh-CN: Kínai (Kína)
el: Görög
he: Héber
- pt-BR: Portugál (Brazília)
ar: Arab
af: Afrikaans
da: Dán
@@ -341,6 +341,7 @@ languages:
th: Thai
ro: Román
pt: Portugál (Portugália)
+ pt-BR: Portugál (Brazília)
bg: Bolgár
ko: Koreai
tr: Török
@@ -355,5 +356,7 @@ villagers:
no-trading: "&4Nem cserélhetsz Slimefun tárgyakat falusiakkal!"
cartography_table:
not-working: "&4Nem használhatsz Slimefun tárgyakat térképasztalban."
+cauldron:
+ no-discoloring: "&4Nem színteleníthetsz Slimefun páncélt!"
miner:
no-ores: "&eSajnálom, nem találtam semmilyen ércet a közelben!"
diff --git a/src/main/resources/languages/messages_ja.yml b/src/main/resources/languages/messages_ja.yml
index ec99efcc2..c34c65548 100644
--- a/src/main/resources/languages/messages_ja.yml
+++ b/src/main/resources/languages/messages_ja.yml
@@ -228,6 +228,7 @@ machines:
finished: "&eIndustrial Minerの稼働完了!合計で%ores%個の鉱石を入手しました!"
anvil:
not-working: "&4Slimefunアイテムは金床を利用できません!"
+ mcmmo-salvaging: "&4Slimefunアイテムはサルベージできません!"
backpack:
already-open: "&cこのバックパックはどこかで使用中です!"
no-stack: "&cバックパックはスタックされていると使用できません!"
@@ -312,7 +313,6 @@ languages:
el: ギリシャ語
he: ヘブライ語
pt: ポルトガル語(ポルトガル)
- pt-BR: ポルトガル語(ブラジル)
ar: アラビア語
af: アフリカーンス語
da: デンマーク語
@@ -324,6 +324,7 @@ languages:
fa: ペルシア語
th: タイ語
ro: ルーマニア語
+ pt-BR: ポルトガル語(ブラジル)
bg: ブルガリア語
ko: 韓国語
tr: トルコ語
@@ -338,5 +339,7 @@ villagers:
no-trading: "&4Slimefunアイテムは村人との取引に使用できません!"
cartography_table:
not-working: "&4Slimefunアイテムは製図台を使用できません!"
+cauldron:
+ no-discoloring: "&4Slimefunアイテムの脱色はできません"
miner:
no-ores: "&e周辺には鉱石が見つかりませんでした!"
diff --git a/src/main/resources/languages/messages_ru.yml b/src/main/resources/languages/messages_ru.yml
index f1989d92a..addbf80bb 100644
--- a/src/main/resources/languages/messages_ru.yml
+++ b/src/main/resources/languages/messages_ru.yml
@@ -20,6 +20,10 @@ commands:
player-never-joined: "&4Игрок с таким ником не найден!"
backpack-does-not-exist: "&4Указанный рюкзак не существует!"
restored-backpack-given: "&aРюкзак был восстановлен и добавлен в Ваш инвентарь!"
+ charge:
+ description: Заряжает предмет, который Вы держите
+ charge-success: Предмет заряжен!
+ not-rechargeable: Этот предмет не может быть заряжен!
guide:
search:
message: "&bЧто бы Вы хотели найти?"
@@ -83,6 +87,7 @@ guide:
miner: Ресурсы, добываемые этим шахтёром
generator: Доступные виды топлива
gold-pan: Ресурсы, которые Вы можете получить
+ climbing-pick: Поверхности для карабканья
back:
title: Назад
guide: Вернуться к руководству Slimefun
@@ -129,6 +134,7 @@ messages:
whirlwind: "&a&oВаш талисман отразил снаряд"
wizard: "&a&oТалисман повысил уровень зачарования «Удача», но мог также ухудшить
другие зачарования"
+ caveman: "&a&oВаш талисман выдал Вам «Спешку»"
soulbound-rune:
fail: "&cВы можете привязать к себе только один предмет за раз."
success: "&aВы успешно привязали этот предмет к себе! Он останется при Вас после
@@ -177,6 +183,10 @@ messages:
multi-tool:
mode-change: "&bРежим «%device%» изменён на: &9%mode%"
not-shears: "&cМультиинструмент не может быть использован в качестве ножниц!"
+ climbing-pick:
+ dual-wielding: "&4Вы должны держать кирку для скалолазания в обеих руках!"
+ wrong-material: "&cВы не можете карабкаться по этой поверхности. Проверьте руководство
+ Slimefun для большей информации!"
mode-change: "&b%device% | Режим изменён на: &9%mode%"
machines:
pattern-not-found: "&eК сожалению, не удалось распознать этот рецепт. Пожалуйста,
@@ -320,6 +330,7 @@ languages:
zh-CN: Китайский (Китай)
el: Греческий
he: Иврит
+ pt: Португальский (Португалия)
pt-BR: Португальский (Бразилия)
ar: Арабский
af: Бурский
@@ -332,7 +343,6 @@ languages:
fa: Персидский
th: Тайский
ro: Румынский
- pt: Португальский (Португалия)
bg: Болгарский
ko: Корейский
tr: Турецкий
@@ -345,5 +355,7 @@ brewing_stand:
not-working: "&4Вы не можете использовать Slimefun предметы в варочной стойке!"
villagers:
no-trading: "&4Вы не можете торговаться с крестьянами Slimefun предметами!"
+cartography_table:
+ not-working: "&4Вы не можете использовать Slimefun предметы в столе картографа!"
miner:
no-ores: "&eК сожалению, не удалось найти какую-либо руду поблизости!"
diff --git a/src/main/resources/languages/messages_tl.yml b/src/main/resources/languages/messages_tl.yml
index fa284c8f7..cb9531d74 100644
--- a/src/main/resources/languages/messages_tl.yml
+++ b/src/main/resources/languages/messages_tl.yml
@@ -21,6 +21,10 @@ commands:
backpack-does-not-exist: "&4Ang tinukoy na backpack ay hindi umiiral!"
restored-backpack-given: "&aAng iyong backpack ay naibalik at naidagdag sa iyong
imbentaryo!"
+ charge:
+ description: I-chacharge ang item ng iyong hinahawakan.
+ charge-success: Na-charge na ang item!
+ not-rechargeable: Hindi puedeng i-charge ang item na ito.
guide:
search:
message: "&bAno ang hinahanap mo?"
@@ -53,6 +57,7 @@ guide:
addons: Ang mga Addons para sa Slimefun4
bugs: Mga Bug Reports
source: Ang Source Code
+ versions: Mga na-install na versions
credits:
commit: Commit
commits: Mga Commits
@@ -62,6 +67,12 @@ guide:
resourcepack: "&cResourcepack Artist"
translator: "&9Translator"
profile-link: I-click ito upang bisitahin ang kanilang profile sa GitHub.
+ open: Pindutin ito upang makita ang aming mga nag-ambag
+ description:
+ - "&7Ang Slimefun ay isang proyekto na bukas na mapagkukunan"
+ - "&7at pinapanatili ng isang malaking pamayanan ng mga tao."
+ - "&7Mga hanggang &e%contributors% &7na mga tao ang tumutulong sa"
+ - "&7Slimefun sa buong lahat ng mga taong ito."
pages:
previous: Nakaraang pahina.
next: Susunod na pahina.
@@ -74,6 +85,7 @@ guide:
miner: Mga mapagkukunan na maaari mong makuha sa Miner na ito.
generator: Magagamit na mga uri ng gasolina.
gold-pan: Mga mapagkukunan na maaari mong makuha.
+ climbing-pick: Mga ibabaw na maaari mong akyatin
back:
title: Balik
guide: Bumalik sa Slimefun Guide
@@ -175,6 +187,11 @@ messages:
multi-tool:
mode-change: "&b%device% napalitan ang mode sa: &9%mode%"
not-shears: "&cBawal gamitin ang Multi-Tool bilang shears!"
+ climbing-pick:
+ dual-wielding: "&4Kailangan mong hawakan ang Climbing Picks ng dalawang kamay
+ upang magamit ito!"
+ wrong-material: "&cHindi ka maaaring umakyat sa ibabaw na ito. Suriin ang iyong
+ Slimefun Guide para sa karagdagang impormasyon!"
mode-change: "&b%device% mode ay pinalitan ng: &9%mode%"
machines:
pattern-not-found: "&ePasensiya na, hindi ko maintindihan ang Recipe na ito. Pakilagay
@@ -239,6 +256,7 @@ machines:
%ores% ore(s)!"
anvil:
not-working: "&4Hindi puwedeng gamitin ang mga Slimefun Aytem sa isang Anvil!"
+ mcmmo-salvaging: "&4Bawal i-salvage ang mga Slimefun items!"
backpack:
already-open: "&cSorry, ang backpack na ito ay nakabukas na sa ibang lugar!"
no-stack: "&cHindi puwedeng i-stack ang mga Backpack."
@@ -349,3 +367,7 @@ 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!"
+cartography_table:
+ not-working: "&4Hindi mo puedeng gamitin ang mga Slimefun items sa cartography table!"
+cauldron:
+ no-discoloring: "&4Hindi mo puedeng i-discolor ang Slimefun Armor."
diff --git a/src/main/resources/languages/messages_zh-CN.yml b/src/main/resources/languages/messages_zh-CN.yml
index b0b631128..34134c21d 100644
--- a/src/main/resources/languages/messages_zh-CN.yml
+++ b/src/main/resources/languages/messages_zh-CN.yml
@@ -20,6 +20,10 @@ commands:
player-never-joined: "&4找不到叫这个名字的玩家!"
backpack-does-not-exist: "&4你指定的背包不存在!"
restored-backpack-given: "&a你的背包已被恢复并且已经放入了你的物品栏!"
+ charge:
+ description: 为你手持的物品充电
+ charge-success: 充电完成!
+ not-rechargeable: 这个物品不能充电!
guide:
search:
message: "&b你想要搜索什么?"
@@ -127,6 +131,7 @@ messages:
knight: "&a&o你的护身符给予了你 5 秒的生命恢复"
whirlwind: "&a&o你的护身符反弹了所有的弹射物"
wizard: "&a&o你的护身符使一个附魔的等级提高了, 同时其他附魔等级将会下降"
+ caveman: "&a&o你的护身符给予了你急迫效果"
soulbound-rune:
fail: "&c一次只能灵魂绑定一个物品."
success: "&a物品绑定成功! 在你死亡后此物品将不会掉落."
@@ -223,6 +228,7 @@ machines:
finished: "&e你的工业矿机采矿已完成! 总共开采了 %ores% 个矿石!"
anvil:
not-working: "&4你不能在铁砧里使用 Slimefun 的物品"
+ mcmmo-salvaging: "&4你不能分解 Slimefun 物品!"
backpack:
already-open: "&c抱歉, 这个背包已在别处打开了!"
no-stack: "&c你不能同时手持两个背包"
@@ -331,5 +337,9 @@ brewing_stand:
not-working: "&4你不能在酿造台中使用 Slimefun 物品!"
villagers:
no-trading: "&4你不能用 Slimefun 的物品和村民交易!"
+cartography_table:
+ not-working: "&4你不能在制图台中使用 Slimefun 物品!"
+cauldron:
+ no-discoloring: "&4你不能用炼药锅清洗 Slimefun 物品上的颜色"
miner:
no-ores: "&e抱歉, 周围找不到矿石了!"
diff --git a/src/main/resources/languages/researches_hu.yml b/src/main/resources/languages/researches_hu.yml
index 2715e2184..f1bf8cedc 100644
--- a/src/main/resources/languages/researches_hu.yml
+++ b/src/main/resources/languages/researches_hu.yml
@@ -246,3 +246,4 @@ slimefun:
caveman_talisman: Az Ősember talizmánja
even_higher_tier_capacitors: 3. szintű kondenzátorok
elytra_cap: Ütközésvédelem
+ energy_connectors: Vezetékes csatlakozás
diff --git a/src/main/resources/languages/researches_ja.yml b/src/main/resources/languages/researches_ja.yml
index 7b2c59fda..27fccbf1a 100644
--- a/src/main/resources/languages/researches_ja.yml
+++ b/src/main/resources/languages/researches_ja.yml
@@ -246,3 +246,4 @@ slimefun:
caveman_talisman: 洞窟暮らしのタリスマン
even_higher_tier_capacitors: キャパシタⅢ
elytra_cap: 衝撃緩和装備
+ energy_connectors: 有線接続
diff --git a/src/main/resources/languages/researches_ru.yml b/src/main/resources/languages/researches_ru.yml
index ee494c173..991111a09 100644
--- a/src/main/resources/languages/researches_ru.yml
+++ b/src/main/resources/languages/researches_ru.yml
@@ -240,3 +240,10 @@ slimefun:
lead_clothing: Свинцовое обмундирование
tape_measure: Рулетка
iron_golem_assembler: Образователь железных големов
+ climbing_pick: Покоритель поверхностей
+ shulker_shell: Синтетические шалкеры
+ villager_rune: Сбрасывание торговли
+ caveman_talisman: Талисман шахтёра
+ even_higher_tier_capacitors: Большой накопитель энергии
+ elytra_cap: Противоударная экипировка
+ energy_connectors: Проводные соединения
diff --git a/src/main/resources/languages/researches_tl.yml b/src/main/resources/languages/researches_tl.yml
index a3d68ee89..de6c28d36 100644
--- a/src/main/resources/languages/researches_tl.yml
+++ b/src/main/resources/languages/researches_tl.yml
@@ -240,3 +240,10 @@ slimefun:
lead_clothing: Lead Clothing
tape_measure: Tape Measure
iron_golem_assembler: Automated Iron Golems
+ climbing_pick: Block Raider
+ shulker_shell: Synthetic Shulkers
+ villager_rune: Reset Villager Trades
+ caveman_talisman: Talisman of the Caveman
+ even_higher_tier_capacitors: Tier 3 Capacitors
+ elytra_cap: Crash Gear
+ energy_connectors: Wired Connections
diff --git a/src/main/resources/languages/researches_tr.yml b/src/main/resources/languages/researches_tr.yml
index cb141f0e2..3c68ccd73 100644
--- a/src/main/resources/languages/researches_tr.yml
+++ b/src/main/resources/languages/researches_tr.yml
@@ -246,3 +246,4 @@ slimefun:
caveman_talisman: Mağara Adamı Tılsımı
even_higher_tier_capacitors: Seviye 3 Kapasitörler
elytra_cap: İniş Takımı
+ energy_connectors: Kablolu Bağlantı
diff --git a/src/main/resources/languages/researches_zh-CN.yml b/src/main/resources/languages/researches_zh-CN.yml
index b0db0509e..3b2187c3a 100644
--- a/src/main/resources/languages/researches_zh-CN.yml
+++ b/src/main/resources/languages/researches_zh-CN.yml
@@ -243,3 +243,6 @@ slimefun:
climbing_pick: 古块丽影
shulker_shell: 人造潜影贝
villager_rune: 防奸商神器
+ caveman_talisman: 穴居人护身符
+ even_higher_tier_capacitors: 三级电容器
+ energy_connectors: 有线连接
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index f0aaf77fd..04a127c8a 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -5,9 +5,9 @@ description: Slimefun basically turns your entire Server into a FTB modpack with
website: https://github.com/Slimefun
main: io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin
-softdepend: [CS-CoreLib, PlaceholderAPI, WorldEdit, EmeraldEnchants]
+softdepend: [CS-CoreLib, PlaceholderAPI, WorldEdit, EmeraldEnchants, mcMMO]
-api-version: '1.13'
+api-version: '1.14'
commands:
slimefun:
diff --git a/src/main/resources/tags/block_placer_ignored_materials.json b/src/main/resources/tags/block_placer_ignored_materials.json
index a41e8050e..0e84d9d81 100644
--- a/src/main/resources/tags/block_placer_ignored_materials.json
+++ b/src/main/resources/tags/block_placer_ignored_materials.json
@@ -1,24 +1,62 @@
{
"values" : [
"#slimefun:sensitive_materials",
+ "#slimefun:tall_flowers",
"#slimefun:mushrooms",
- {
- "id" : "#minecraft:tall_flowers",
- "required" : false
- },
- {
- "id" : "#minecraft:beds",
- "required" : false
- },
- {
- "id" : "#minecraft:doors",
- "required" : false
- },
+ "#minecraft:beds",
+ "#minecraft:buttons",
+ "#minecraft:signs",
+ "#minecraft:doors",
+ "#minecraft:rails",
+ "#minecraft:small_flowers",
+ "#minecraft:coral_blocks",
+ "#minecraft:corals",
+ "#minecraft:carpets",
+ "#minecraft:banners",
"minecraft:sugar_cane",
+ "minecraft:cactus",
+ "minecraft:bamboo",
+ "minecraft:vine",
+ "minecraft:ladder",
+ "minecraft:chorus_plant",
+ "minecraft:chorus_flower",
+ "minecraft:snow",
+ "minecraft:lever",
+ "minecraft:repeater",
+ "minecraft:tripwire_hook",
"minecraft:lily_pad",
"minecraft:dead_bush",
+ "minecraft:fern",
+ "minecraft:grass",
+ "minecraft:sea_pickle",
+ "minecraft:nether_wart",
+ "minecraft:seagrass",
+ "minecraft:tall_seagrass",
+ "minecraft:kelp",
+ "minecraft:bell",
+ "minecraft:lantern",
{
- "id" : "minecraft:bamboo",
+ "id" : "minecraft:soul_lantern",
+ "required" : false
+ },
+ {
+ "id" : "minecraft:nether_sprouts",
+ "required" : false
+ },
+ {
+ "id" : "minecraft:crimson_roots",
+ "required": false
+ },
+ {
+ "id" : "minecraft:twisting_vines",
+ "required" : false
+ },
+ {
+ "id" : "minecraft:warped_roots",
+ "required" : false
+ },
+ {
+ "id" : "minecraft:weeping_vines",
"required" : false
}
]
diff --git a/src/main/resources/tags/crop_growth_accelerator_blocks.json b/src/main/resources/tags/crop_growth_accelerator_blocks.json
index 97af19e67..e0be360b6 100644
--- a/src/main/resources/tags/crop_growth_accelerator_blocks.json
+++ b/src/main/resources/tags/crop_growth_accelerator_blocks.json
@@ -12,9 +12,6 @@
"minecraft:pumpkin_stem",
"minecraft:nether_wart",
"minecraft:cocoa",
- {
- "id" : "minecraft:sweet_berry_bush",
- "required" : false
- }
+ "minecraft:sweet_berry_bush"
]
}
diff --git a/src/main/resources/tags/dirt_variants.json b/src/main/resources/tags/dirt_variants.json
new file mode 100644
index 000000000..d551913f7
--- /dev/null
+++ b/src/main/resources/tags/dirt_variants.json
@@ -0,0 +1,11 @@
+{
+ "values" : [
+ "minecraft:dirt",
+ "minecraft:coarse_dirt",
+ "minecraft:grass_block",
+ "minecraft:grass_path",
+ "minecraft:farmland",
+ "minecraft:podzol",
+ "minecraft:mycelium"
+ ]
+}
diff --git a/src/main/resources/tags/explosive_shovel_blocks.json b/src/main/resources/tags/explosive_shovel_blocks.json
index da0f980ff..17ceed4e0 100644
--- a/src/main/resources/tags/explosive_shovel_blocks.json
+++ b/src/main/resources/tags/explosive_shovel_blocks.json
@@ -1,10 +1,8 @@
{
"values" : [
"#minecraft:sand",
- "#minecraft:dirt_like",
"#slimefun:concrete_powders",
- "minecraft:farmland",
- "minecraft:grass_path",
+ "#slimefun:dirt_variants",
"minecraft:snow",
"minecraft:snow_block",
"minecraft:gravel",
diff --git a/src/main/resources/tags/fortune_compatible_ores.json b/src/main/resources/tags/fortune_compatible_ores.json
new file mode 100644
index 000000000..bdf61d641
--- /dev/null
+++ b/src/main/resources/tags/fortune_compatible_ores.json
@@ -0,0 +1,10 @@
+{
+ "values" : [
+ "minecraft:coal_ore",
+ "minecraft:lapis_ore",
+ "minecraft:diamond_ore",
+ "minecraft:redstone_ore",
+ "minecraft:emerald_ore",
+ "minecraft:nether_quartz_ore"
+ ]
+}
diff --git a/src/main/resources/tags/leather_armor.json b/src/main/resources/tags/leather_armor.json
new file mode 100644
index 000000000..9001f3385
--- /dev/null
+++ b/src/main/resources/tags/leather_armor.json
@@ -0,0 +1,8 @@
+{
+ "values" : [
+ "minecraft:leather_helmet",
+ "minecraft:leather_chestplate",
+ "minecraft:leather_leggings",
+ "minecraft:leather_boots"
+ ]
+}
diff --git a/src/main/resources/tags/ores.json b/src/main/resources/tags/ores.json
index b4c76a1a4..fd4c45729 100644
--- a/src/main/resources/tags/ores.json
+++ b/src/main/resources/tags/ores.json
@@ -6,11 +6,6 @@
},
"minecraft:gold_ore",
"minecraft:iron_ore",
- "minecraft:coal_ore",
- "minecraft:lapis_ore",
- "minecraft:diamond_ore",
- "minecraft:redstone_ore",
- "minecraft:emerald_ore",
- "minecraft:nether_quartz_ore"
+ "#slimefun:fortune_compatible_ores"
]
}
diff --git a/src/main/resources/tags/pressure_plates.json b/src/main/resources/tags/pressure_plates.json
new file mode 100644
index 000000000..b8bdb7667
--- /dev/null
+++ b/src/main/resources/tags/pressure_plates.json
@@ -0,0 +1,12 @@
+{
+ "values" : [
+ "#minecraft:wooden_pressure_plates",
+ "minecraft:stone_pressure_plate",
+ "minecraft:light_weighted_pressure_plate",
+ "minecraft:heavy_weighted_pressure_plate",
+ {
+ "id" : "minecraft:polished_blackstone_pressure_plate",
+ "required" : false
+ }
+ ]
+}
diff --git a/src/main/resources/tags/sensitive_materials.json b/src/main/resources/tags/sensitive_materials.json
index bd782e1e6..daae5c94f 100644
--- a/src/main/resources/tags/sensitive_materials.json
+++ b/src/main/resources/tags/sensitive_materials.json
@@ -1,11 +1,8 @@
{
"values" : [
"#minecraft:saplings",
- "#minecraft:wooden_pressure_plates",
"#slimefun:torches",
- "minecraft:stone_pressure_plate",
- "minecraft:light_weighted_pressure_plate",
- "minecraft:heavy_weighted_pressure_plate",
+ "#slimefun:pressure_plates",
"minecraft:cake"
]
}
diff --git a/src/main/resources/tags/tall_flowers.json b/src/main/resources/tags/tall_flowers.json
new file mode 100644
index 000000000..61958b5de
--- /dev/null
+++ b/src/main/resources/tags/tall_flowers.json
@@ -0,0 +1,10 @@
+{
+ "values" : [
+ "minecraft:lilac",
+ "minecraft:rose_bush",
+ "minecraft:peony",
+ "minecraft:tall_grass",
+ "minecraft:large_fern",
+ "minecraft:sunflower"
+ ]
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestAnvilListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestAnvilListener.java
new file mode 100644
index 000000000..ba3784350
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestAnvilListener.java
@@ -0,0 +1,80 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.AnvilListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+public class TestAnvilListener {
+
+ private static SlimefunPlugin plugin;
+ private static AnvilListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new AnvilListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private InventoryClickEvent mockAnvilEvent(ItemStack item) {
+ Player player = server.addPlayer();
+ Inventory inv = TestUtilities.mockInventory(InventoryType.ANVIL, item, null, new ItemStack(Material.IRON_CHESTPLATE));
+ InventoryView view = player.openInventory(inv);
+ InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
+
+ listener.onAnvil(event);
+ return event;
+ }
+
+ @Test
+ public void testAnvilWithoutSlimefunItems() {
+ InventoryClickEvent event = mockAnvilEvent(new ItemStack(Material.IRON_SWORD));
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+ @Test
+ public void testAnvilWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCKED_IRON_SWORD", new CustomItem(Material.IRON_SWORD, "&6Mock"));
+ item.register(plugin);
+
+ InventoryClickEvent event = mockAnvilEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+ @Test
+ public void testAnvilWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.IRON_SWORD, true);
+ item.register(plugin);
+
+ InventoryClickEvent event = mockAnvilEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestBrewingStandListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestBrewingStandListener.java
new file mode 100644
index 000000000..708261165
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestBrewingStandListener.java
@@ -0,0 +1,84 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.bukkit.Material;
+import org.bukkit.block.BrewingStand;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.BrewingStandListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+public class TestBrewingStandListener {
+
+ private static SlimefunPlugin plugin;
+ private static BrewingStandListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new BrewingStandListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private InventoryClickEvent mockBrewingEvent(ItemStack item) {
+ Player player = server.addPlayer();
+ Inventory inv = TestUtilities.mockInventory(InventoryType.BREWING);
+ Mockito.when(inv.getHolder()).thenReturn(Mockito.mock(BrewingStand.class));
+ Mockito.when(inv.getSize()).thenReturn(5);
+
+ InventoryView view = player.openInventory(inv);
+ view.setCursor(item);
+ InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 1, ClickType.LEFT, InventoryAction.PICKUP_ONE);
+ listener.onPreBrew(event);
+ return event;
+ }
+
+ @Test
+ public void testBrewingWithoutSlimefunItems() {
+ InventoryClickEvent event = mockBrewingEvent(new ItemStack(Material.BLAZE_POWDER));
+ Assertions.assertEquals(Result.ALLOW, event.getResult());
+ }
+
+ @Test
+ public void testBrewingWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_POWDER", new CustomItem(Material.BLAZE_POWDER, "&6Magic Mock Powder"));
+ item.register(plugin);
+
+ InventoryClickEvent event = mockBrewingEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+ @Test
+ public void testBrewingWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.BLAZE_POWDER, true);
+ item.register(plugin);
+
+ InventoryClickEvent event = mockBrewingEvent(item.getItem());
+ Assertions.assertEquals(Result.ALLOW, event.getResult());
+ }
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCartographyTableListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCartographyTableListener.java
new file mode 100644
index 000000000..d32e217b7
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCartographyTableListener.java
@@ -0,0 +1,74 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CartographyTableListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+public class TestCartographyTableListener {
+
+ private static SlimefunPlugin plugin;
+ private static CartographyTableListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new CartographyTableListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private InventoryClickEvent mockCartographyTableEvent(ItemStack item) {
+ Player player = server.addPlayer();
+ Inventory inv = TestUtilities.mockInventory(InventoryType.CARTOGRAPHY, new ItemStack(Material.FILLED_MAP), item, new ItemStack(Material.FILLED_MAP));
+ InventoryView view = player.openInventory(inv);
+ InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
+
+ listener.onCartographyTable(event);
+ return event;
+ }
+
+ @Test
+ public void testCartographyTableWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCKED_PAPER", new CustomItem(Material.PAPER, "&6Mock"));
+ item.register(plugin);
+
+ InventoryClickEvent event = mockCartographyTableEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+ @Test
+ public void testCartographyTableWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.PAPER, true);
+ item.register(plugin);
+
+ InventoryClickEvent event = mockCartographyTableEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCauldronListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCauldronListener.java
new file mode 100644
index 000000000..dbe1ad358
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCauldronListener.java
@@ -0,0 +1,106 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import be.seeseemelk.mockbukkit.block.BlockMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CauldronListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+class TestCauldronListener {
+
+ private static SlimefunPlugin plugin;
+ private static CauldronListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new CauldronListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private PlayerInteractEvent mockCauldronEvent(ItemStack item) {
+ Player player = server.addPlayer();
+ Block block = new BlockMock(Material.CAULDRON);
+ PlayerInteractEvent event = new PlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, item, block, BlockFace.UP, EquipmentSlot.HAND);
+
+ listener.onCauldronUse(event);
+ return event;
+ }
+
+ @Test
+ @DisplayName("Test Cauldron handling null")
+ void testCauldronWithNull() {
+ PlayerInteractEvent event = mockCauldronEvent(null);
+ Assertions.assertEquals(Result.DEFAULT, event.useItemInHand());
+ }
+
+ @Test
+ @DisplayName("Test Cauldron working as normal with unrelated items")
+ void testCauldronWithNormalItem() {
+ PlayerInteractEvent event = mockCauldronEvent(new ItemStack(Material.GOLD_BLOCK));
+ Assertions.assertEquals(Result.DEFAULT, event.useItemInHand());
+ }
+
+ @Test
+ @DisplayName("Test Cauldron working as normal with normal leather armor")
+ void testCauldronWithNormalLeatherArmor() {
+ PlayerInteractEvent event = mockCauldronEvent(new ItemStack(Material.LEATHER_BOOTS));
+ Assertions.assertEquals(Result.DEFAULT, event.useItemInHand());
+ }
+
+ @Test
+ @DisplayName("Test Cauldron working as normal with non-leather slimefun items")
+ void testCauldronWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CAULDRON_TEST_MOCK", new CustomItem(Material.GOLDEN_APPLE, "&6Mock"));
+ item.register(plugin);
+
+ PlayerInteractEvent event = mockCauldronEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.useItemInHand());
+ }
+
+ @Test
+ @DisplayName("Test Cauldron being cancelled with slimefun leather armor")
+ void testCauldronWithSlimefunLeatherArmor() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CAULDRON_TEST_MOCK_LEATHER", new CustomItem(Material.LEATHER_BOOTS, "&6Mock"));
+ item.register(plugin);
+
+ PlayerInteractEvent event = mockCauldronEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.useItemInHand());
+ }
+
+ @Test
+ @DisplayName("Test Cauldron working as normal with vanilla slimefun leather armor")
+ void testCauldronWithVanillaLeatherArmor() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.LEATHER_CHESTPLATE, true);
+ item.register(plugin);
+
+ PlayerInteractEvent event = mockCauldronEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.useItemInHand());
+ }
+
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCraftingTableListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCraftingTableListener.java
new file mode 100644
index 000000000..03f543411
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestCraftingTableListener.java
@@ -0,0 +1,149 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.apache.commons.lang.mutable.MutableObject;
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.CraftItemEvent;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.event.inventory.PrepareItemCraftEvent;
+import org.bukkit.inventory.CraftingInventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.Recipe;
+import org.bukkit.inventory.ShapedRecipe;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CraftingTableListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+public class TestCraftingTableListener {
+
+ private static SlimefunPlugin plugin;
+ private static CraftingTableListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new CraftingTableListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private CraftItemEvent mockCraftingEvent(ItemStack item) {
+ Recipe recipe = new ShapedRecipe(new NamespacedKey(plugin, "test_recipe"), new ItemStack(Material.EMERALD));
+ Player player = server.addPlayer();
+
+ CraftingInventory inv = Mockito.mock(CraftingInventory.class);
+ Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { item, null, null, null, null, null, null, null, null });
+
+ InventoryView view = player.openInventory(inv);
+ CraftItemEvent event = new CraftItemEvent(recipe, view, SlotType.RESULT, 9, ClickType.LEFT, InventoryAction.PICKUP_ALL);
+
+ listener.onCraft(event);
+ return event;
+ }
+
+ private PrepareItemCraftEvent mockPreCraftingEvent(ItemStack item) {
+ Player player = server.addPlayer();
+
+ CraftingInventory inv = Mockito.mock(CraftingInventory.class);
+ MutableObject result = new MutableObject(new ItemStack(Material.EMERALD));
+
+ Mockito.doAnswer(invocation -> {
+ ItemStack argument = invocation.getArgument(0);
+ result.setValue(argument);
+ return null;
+ }).when(inv).setResult(Mockito.any());
+
+ Mockito.when(inv.getResult()).thenAnswer(invocation -> result.getValue());
+ Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { null, null, item, null, null, null, null, null, null });
+
+ InventoryView view = player.openInventory(inv);
+ PrepareItemCraftEvent event = new PrepareItemCraftEvent(inv, view, false);
+
+ listener.onPrepareCraft(event);
+ return event;
+ }
+
+ @Test
+ public void testCraftEventWithoutSlimefunItems() {
+ CraftItemEvent event = mockCraftingEvent(new ItemStack(Material.DIAMOND));
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+ @Test
+ public void testCraftEventWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_DIAMOND", new CustomItem(Material.DIAMOND, "&cMock Diamond"));
+ item.register(plugin);
+
+ CraftItemEvent event = mockCraftingEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+ @Test
+ public void testCraftEventWithChangingSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CHANGING_ITEM", new CustomItem(Material.DIAMOND, "&dChanging Diamond"));
+ item.register(plugin);
+
+ item.setUseableInWorkbench(true);
+ CraftItemEvent event = mockCraftingEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+
+ item.setUseableInWorkbench(false);
+ CraftItemEvent event2 = mockCraftingEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event2.getResult());
+ }
+
+ @Test
+ public void testCraftEventWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.DIAMOND, true);
+ item.register(plugin);
+
+ CraftItemEvent event = mockCraftingEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+ @Test
+ public void testPreCraftEventWithoutSlimefunItems() {
+ PrepareItemCraftEvent event = mockPreCraftingEvent(new ItemStack(Material.DIAMOND));
+ Assertions.assertNotNull(event.getInventory().getResult());
+ }
+
+ @Test
+ public void testPreCraftEventWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_DIAMOND2", new CustomItem(Material.DIAMOND, "&cMock Diamond"));
+ item.register(plugin);
+
+ PrepareItemCraftEvent event = mockPreCraftingEvent(item.getItem());
+ Assertions.assertNull(event.getInventory().getResult());
+ }
+
+ @Test
+ public void testPreCraftEventWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.GOLD_INGOT, true);
+ item.register(plugin);
+
+ PrepareItemCraftEvent event = mockPreCraftingEvent(item.getItem());
+ Assertions.assertNotNull(event.getInventory().getResult());
+ }
+
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestGrindstoneListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestGrindstoneListener.java
new file mode 100644
index 000000000..19a74a5dc
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestGrindstoneListener.java
@@ -0,0 +1,91 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import be.seeseemelk.mockbukkit.MockBukkit;
+import be.seeseemelk.mockbukkit.ServerMock;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
+import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
+import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.GrindstoneListener;
+import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
+import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
+
+public class TestGrindstoneListener {
+
+ private static SlimefunPlugin plugin;
+ private static GrindstoneListener listener;
+ private static ServerMock server;
+
+ @BeforeAll
+ public static void load() {
+ server = MockBukkit.mock();
+ plugin = MockBukkit.load(SlimefunPlugin.class);
+ listener = new GrindstoneListener(plugin);
+ }
+
+ @AfterAll
+ public static void unload() {
+ MockBukkit.unmock();
+ }
+
+ private InventoryClickEvent mockGrindStoneEvent(ItemStack item) {
+ Player player = server.addPlayer();
+ Inventory inv = TestUtilities.mockInventory(InventoryType.GRINDSTONE, item, null);
+ InventoryView view = player.openInventory(inv);
+ InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
+
+ listener.onGrindstone(event);
+ return event;
+ }
+
+ @Test
+ public void testGrindStoneWithoutSlimefunItems() {
+ InventoryClickEvent event = mockGrindStoneEvent(new ItemStack(Material.ENCHANTED_BOOK));
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+ @Test
+ public void testGrindStoneWithSlimefunItem() {
+ SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "ENCHANTED_MOCK_BOOK", new CustomItem(Material.ENCHANTED_BOOK, "&6Mock"));
+ item.register(plugin);
+
+ InventoryClickEvent event = mockGrindStoneEvent(item.getItem());
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+ @Test
+ public void testGrindStoneWithVanillaItem() {
+ VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.ENCHANTED_BOOK, true);
+ item.register(plugin);
+
+ InventoryClickEvent event = mockGrindStoneEvent(item.getItem());
+ Assertions.assertEquals(Result.DEFAULT, event.getResult());
+ }
+
+ @ParameterizedTest
+ @EnumSource(SlimefunGuideLayout.class)
+ public void testGrindStoneWithSlimefunGuide(SlimefunGuideLayout layout) {
+ InventoryClickEvent event = mockGrindStoneEvent(SlimefunGuide.getItem(layout));
+ Assertions.assertEquals(Result.DENY, event.getResult());
+ }
+
+}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestItemPickupListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestItemPickupListener.java
index 7ee7b04f8..55e58b067 100644
--- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestItemPickupListener.java
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestItemPickupListener.java
@@ -19,7 +19,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.ItemEntityMock;
-import be.seeseemelk.mockbukkit.inventory.ChestInventoryMock;
+import be.seeseemelk.mockbukkit.inventory.HopperInventoryMock;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
@@ -63,7 +63,7 @@ class TestItemPickupListener {
@ParameterizedTest
@ValueSource(booleans = { true, false })
void testNoPickupFlagForInventories(boolean flag) {
- Inventory inventory = new ChestInventoryMock(null, 5);
+ Inventory inventory = new HopperInventoryMock(null);
Item item = new ItemEntityMock(server, UUID.randomUUID(), new ItemStack(Material.COMPASS));
if (flag) {
@@ -107,7 +107,7 @@ class TestItemPickupListener {
@ParameterizedTest
@ValueSource(booleans = { true, false })
void testAltarProbeForInventories(boolean flag) {
- Inventory inventory = new ChestInventoryMock(null, 5);
+ Inventory inventory = new HopperInventoryMock(null);
ItemStack stack;
if (flag) {
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestVanillaMachinesListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestVanillaMachinesListener.java
deleted file mode 100644
index b87f39a25..000000000
--- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/listeners/TestVanillaMachinesListener.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
-
-import org.apache.commons.lang.mutable.MutableObject;
-import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
-import org.bukkit.block.BrewingStand;
-import org.bukkit.entity.Player;
-import org.bukkit.event.Event.Result;
-import org.bukkit.event.inventory.ClickType;
-import org.bukkit.event.inventory.CraftItemEvent;
-import org.bukkit.event.inventory.InventoryAction;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.event.inventory.InventoryType;
-import org.bukkit.event.inventory.InventoryType.SlotType;
-import org.bukkit.event.inventory.PrepareItemCraftEvent;
-import org.bukkit.inventory.CraftingInventory;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.InventoryView;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.Recipe;
-import org.bukkit.inventory.ShapedRecipe;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.mockito.Mockito;
-
-import be.seeseemelk.mockbukkit.MockBukkit;
-import be.seeseemelk.mockbukkit.ServerMock;
-import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
-import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
-import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
-import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
-import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener;
-import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
-import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
-
-public class TestVanillaMachinesListener {
-
- private static SlimefunPlugin plugin;
- private static VanillaMachinesListener listener;
- private static ServerMock server;
-
- @BeforeAll
- public static void load() {
- server = MockBukkit.mock();
- plugin = MockBukkit.load(SlimefunPlugin.class);
- listener = new VanillaMachinesListener(plugin);
- }
-
- @AfterAll
- public static void unload() {
- MockBukkit.unmock();
- }
-
- private InventoryClickEvent mockGrindStoneEvent(ItemStack item) {
- Player player = server.addPlayer();
- Inventory inv = TestUtilities.mockInventory(InventoryType.GRINDSTONE, item, null);
- InventoryView view = player.openInventory(inv);
- InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
-
- listener.onGrindstone(event);
- return event;
- }
-
- private InventoryClickEvent mockAnvilEvent(ItemStack item) {
- Player player = server.addPlayer();
- Inventory inv = TestUtilities.mockInventory(InventoryType.ANVIL, item, null, new ItemStack(Material.IRON_CHESTPLATE));
- InventoryView view = player.openInventory(inv);
- InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
-
- listener.onAnvil(event);
- return event;
- }
-
- private InventoryClickEvent mockCartographyTableEvent(ItemStack item) {
- Player player = server.addPlayer();
- Inventory inv = TestUtilities.mockInventory(InventoryType.CARTOGRAPHY, new ItemStack(Material.FILLED_MAP), item, new ItemStack(Material.FILLED_MAP));
- InventoryView view = player.openInventory(inv);
- InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE);
-
- listener.onCartographyTable(event);
- return event;
- }
-
- private InventoryClickEvent mockBrewingEvent(ItemStack item) {
- Player player = server.addPlayer();
- Inventory inv = TestUtilities.mockInventory(InventoryType.BREWING);
- Mockito.when(inv.getHolder()).thenReturn(Mockito.mock(BrewingStand.class));
- Mockito.when(inv.getSize()).thenReturn(5);
-
- InventoryView view = player.openInventory(inv);
- view.setCursor(item);
- InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 1, ClickType.LEFT, InventoryAction.PICKUP_ONE);
- listener.onPreBrew(event);
- return event;
- }
-
- private CraftItemEvent mockCraftingEvent(ItemStack item) {
- Recipe recipe = new ShapedRecipe(new NamespacedKey(plugin, "test_recipe"), new ItemStack(Material.EMERALD));
- Player player = server.addPlayer();
-
- CraftingInventory inv = Mockito.mock(CraftingInventory.class);
- Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { item, null, null, null, null, null, null, null, null });
-
- InventoryView view = player.openInventory(inv);
- CraftItemEvent event = new CraftItemEvent(recipe, view, SlotType.RESULT, 9, ClickType.LEFT, InventoryAction.PICKUP_ALL);
-
- listener.onCraft(event);
- return event;
- }
-
- private PrepareItemCraftEvent mockPreCraftingEvent(ItemStack item) {
- Player player = server.addPlayer();
-
- CraftingInventory inv = Mockito.mock(CraftingInventory.class);
- MutableObject result = new MutableObject(new ItemStack(Material.EMERALD));
-
- Mockito.doAnswer(invocation -> {
- ItemStack argument = invocation.getArgument(0);
- result.setValue(argument);
- return null;
- }).when(inv).setResult(Mockito.any());
-
- Mockito.when(inv.getResult()).thenAnswer(invocation -> result.getValue());
- Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { null, null, item, null, null, null, null, null, null });
-
- InventoryView view = player.openInventory(inv);
- PrepareItemCraftEvent event = new PrepareItemCraftEvent(inv, view, false);
-
- listener.onPrepareCraft(event);
- return event;
- }
-
- @Test
- public void testGrindStoneWithoutSlimefunItems() {
- InventoryClickEvent event = mockGrindStoneEvent(new ItemStack(Material.ENCHANTED_BOOK));
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testGrindStoneWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "ENCHANTED_MOCK_BOOK", new CustomItem(Material.ENCHANTED_BOOK, "&6Mock"));
- item.register(plugin);
-
- InventoryClickEvent event = mockGrindStoneEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testGrindStoneWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.ENCHANTED_BOOK, true);
- item.register(plugin);
-
- InventoryClickEvent event = mockGrindStoneEvent(item.getItem());
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @ParameterizedTest
- @EnumSource(SlimefunGuideLayout.class)
- public void testGrindStoneWithSlimefunGuide(SlimefunGuideLayout layout) {
- InventoryClickEvent event = mockGrindStoneEvent(SlimefunGuide.getItem(layout));
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testCraftEventWithoutSlimefunItems() {
- CraftItemEvent event = mockCraftingEvent(new ItemStack(Material.DIAMOND));
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testCraftEventWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_DIAMOND", new CustomItem(Material.DIAMOND, "&cMock Diamond"));
- item.register(plugin);
-
- CraftItemEvent event = mockCraftingEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testCraftEventWithChangingSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CHANGING_ITEM", new CustomItem(Material.DIAMOND, "&dChanging Diamond"));
- item.register(plugin);
-
- item.setUseableInWorkbench(true);
- CraftItemEvent event = mockCraftingEvent(item.getItem());
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
-
- item.setUseableInWorkbench(false);
- CraftItemEvent event2 = mockCraftingEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event2.getResult());
- }
-
- @Test
- public void testCraftEventWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.DIAMOND, true);
- item.register(plugin);
-
- CraftItemEvent event = mockCraftingEvent(item.getItem());
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testPreCraftEventWithoutSlimefunItems() {
- PrepareItemCraftEvent event = mockPreCraftingEvent(new ItemStack(Material.DIAMOND));
- Assertions.assertNotNull(event.getInventory().getResult());
- }
-
- @Test
- public void testPreCraftEventWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_DIAMOND2", new CustomItem(Material.DIAMOND, "&cMock Diamond"));
- item.register(plugin);
-
- PrepareItemCraftEvent event = mockPreCraftingEvent(item.getItem());
- Assertions.assertNull(event.getInventory().getResult());
- }
-
- @Test
- public void testPreCraftEventWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.GOLD_INGOT, true);
- item.register(plugin);
-
- PrepareItemCraftEvent event = mockPreCraftingEvent(item.getItem());
- Assertions.assertNotNull(event.getInventory().getResult());
- }
-
- @Test
- public void testAnvilWithoutSlimefunItems() {
- InventoryClickEvent event = mockAnvilEvent(new ItemStack(Material.IRON_SWORD));
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testAnvilWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCKED_IRON_SWORD", new CustomItem(Material.IRON_SWORD, "&6Mock"));
- item.register(plugin);
-
- InventoryClickEvent event = mockAnvilEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testAnvilWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.IRON_SWORD, true);
- item.register(plugin);
-
- InventoryClickEvent event = mockAnvilEvent(item.getItem());
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testCartographyTableWithoutSlimefunItems() {
- InventoryClickEvent event = mockCartographyTableEvent(new ItemStack(Material.PAPER));
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testCartographyTableWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCKED_PAPER", new CustomItem(Material.PAPER, "&6Mock"));
- item.register(plugin);
-
- InventoryClickEvent event = mockCartographyTableEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testCartographyTableWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.PAPER, true);
- item.register(plugin);
-
- InventoryClickEvent event = mockCartographyTableEvent(item.getItem());
- Assertions.assertEquals(Result.DEFAULT, event.getResult());
- }
-
- @Test
- public void testBrewingWithoutSlimefunItems() {
- InventoryClickEvent event = mockBrewingEvent(new ItemStack(Material.BLAZE_POWDER));
- Assertions.assertEquals(Result.ALLOW, event.getResult());
- }
-
- @Test
- public void testBrewingWithSlimefunItem() {
- SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "MOCK_POWDER", new CustomItem(Material.BLAZE_POWDER, "&6Magic Mock Powder"));
- item.register(plugin);
-
- InventoryClickEvent event = mockBrewingEvent(item.getItem());
- Assertions.assertEquals(Result.DENY, event.getResult());
- }
-
- @Test
- public void testBrewingWithVanillaItem() {
- VanillaItem item = TestUtilities.mockVanillaItem(plugin, Material.BLAZE_POWDER, true);
- item.register(plugin);
-
- InventoryClickEvent event = mockBrewingEvent(item.getItem());
- Assertions.assertEquals(Result.ALLOW, event.getResult());
- }
-}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/tags/TestSlimefunTags.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/tags/TestSlimefunTags.java
index 7c2a6f51f..139c5c998 100644
--- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/tags/TestSlimefunTags.java
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/tags/TestSlimefunTags.java
@@ -63,6 +63,7 @@ class TestSlimefunTags {
// Inclusion through a Slimefun Tag
Assertions.assertTrue(SlimefunTag.SENSITIVE_MATERIALS.isTagged(Material.TORCH));
+ Assertions.assertTrue(SlimefunTag.SENSITIVE_MATERIALS.isTagged(Material.OAK_PRESSURE_PLATE));
}
@Test
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestMinecraftVersion.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestMinecraftVersion.java
index 35664ada5..1bdb43a44 100644
--- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestMinecraftVersion.java
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestMinecraftVersion.java
@@ -11,10 +11,10 @@ class TestMinecraftVersion {
@Test
@DisplayName("Test if Minecraft versions match themselves")
void testMatches() {
- Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_13.matches("v1_13_R1"));
Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_14.matches("v1_14_R2"));
+ Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_15.matches("v1_15_R1"));
- Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_13.matches("v1_14_R2"));
+ Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_15.matches("v1_14_R2"));
Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_14.matches("1.14.x"));
Assertions.assertThrows(IllegalArgumentException.class, () -> MinecraftVersion.MINECRAFT_1_14.matches(null));
}
@@ -22,18 +22,18 @@ class TestMinecraftVersion {
@Test
@DisplayName("Test if Minecraft versions are ordered correctly (#atLeast)")
void testAtLeast() {
- Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_15.isAtLeast(MinecraftVersion.MINECRAFT_1_13));
+ Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_16.isAtLeast(MinecraftVersion.MINECRAFT_1_14));
Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_15.isAtLeast(MinecraftVersion.MINECRAFT_1_14));
Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_15.isAtLeast(MinecraftVersion.MINECRAFT_1_15));
- Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_13.isAtLeast(MinecraftVersion.MINECRAFT_1_14));
+ Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_15.isAtLeast(MinecraftVersion.MINECRAFT_1_16));
}
@Test
@DisplayName("Test correct behaviour for MinecraftVersion.UNKNOWN.isAtleast(...)")
void testAtLeastUnknown() {
// Unknown should always fall back to false
- Assertions.assertFalse(MinecraftVersion.UNKNOWN.isAtLeast(MinecraftVersion.MINECRAFT_1_13));
+ Assertions.assertFalse(MinecraftVersion.UNKNOWN.isAtLeast(MinecraftVersion.MINECRAFT_1_14));
Assertions.assertFalse(MinecraftVersion.UNKNOWN.isAtLeast(MinecraftVersion.MINECRAFT_1_15));
Assertions.assertThrows(IllegalArgumentException.class, () -> MinecraftVersion.MINECRAFT_1_14.isAtLeast(null));
@@ -42,19 +42,18 @@ class TestMinecraftVersion {
@Test
@DisplayName("Test if Minecraft versions are ordered correctly (#isBefore)")
void testIsBefore() {
- Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_13.isBefore(MinecraftVersion.MINECRAFT_1_14));
- Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_13.isBefore(MinecraftVersion.MINECRAFT_1_15));
Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_14.isBefore(MinecraftVersion.MINECRAFT_1_15));
+ Assertions.assertTrue(MinecraftVersion.MINECRAFT_1_14.isBefore(MinecraftVersion.MINECRAFT_1_16));
Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_15.isBefore(MinecraftVersion.MINECRAFT_1_15));
- Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_15.isBefore(MinecraftVersion.MINECRAFT_1_13));
+ Assertions.assertFalse(MinecraftVersion.MINECRAFT_1_15.isBefore(MinecraftVersion.MINECRAFT_1_14));
}
@Test
@DisplayName("Test correct behaviour for MinecraftVersion.UNKNOWN.isBefore(...)")
void testIsBeforeUnknown() {
// Unknown should always fall back to true
- Assertions.assertTrue(MinecraftVersion.UNKNOWN.isBefore(MinecraftVersion.MINECRAFT_1_13));
+ Assertions.assertTrue(MinecraftVersion.UNKNOWN.isBefore(MinecraftVersion.MINECRAFT_1_14));
Assertions.assertTrue(MinecraftVersion.UNKNOWN.isBefore(MinecraftVersion.MINECRAFT_1_15));
Assertions.assertThrows(IllegalArgumentException.class, () -> MinecraftVersion.MINECRAFT_1_14.isBefore(null));
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestNumberUtils.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestNumberUtils.java
new file mode 100644
index 000000000..6b33de558
--- /dev/null
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestNumberUtils.java
@@ -0,0 +1,78 @@
+package io.github.thebusybiscuit.slimefun4.testing.tests.utils;
+
+import java.time.LocalDateTime;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
+
+class TestNumberUtils {
+
+ @Test
+ @DisplayName("Test NumberUtils.clamp(...)")
+ void testHumanize() {
+ // Below minimum
+ Assertions.assertEquals(2, NumberUtils.clamp(2, 0, 5));
+
+ // Normal
+ Assertions.assertEquals(3, NumberUtils.clamp(0, 3, 5));
+
+ // Above maximum
+ Assertions.assertEquals(20, NumberUtils.clamp(1, 100, 20));
+ }
+
+ @Test
+ @DisplayName("Test elapsed time string")
+ void testElapsedTime() {
+ LocalDateTime start = LocalDateTime.now();
+
+ LocalDateTime a = start.plusDays(1);
+ Assertions.assertEquals("1d", NumberUtils.getElapsedTime(start, a));
+
+ LocalDateTime b = start.plusHours(25);
+ Assertions.assertEquals("1d 1h", NumberUtils.getElapsedTime(start, b));
+
+ LocalDateTime c = start.plusHours(1);
+ Assertions.assertEquals("1h", NumberUtils.getElapsedTime(start, c));
+
+ LocalDateTime d = start.plusMinutes(12);
+ Assertions.assertEquals("< 1h", NumberUtils.getElapsedTime(start, d));
+ }
+
+ @Test
+ @DisplayName("Test Integer parsing")
+ void testIntegerParsing() {
+ Assertions.assertEquals(6, NumberUtils.getInt("6", 0));
+ Assertions.assertEquals(12, NumberUtils.getInt("I am a String", 12));
+ }
+
+ @Test
+ @DisplayName("Test nullable Long")
+ void testNullableLong() {
+ Assertions.assertEquals(10, NumberUtils.getLong(10L, 20L));
+ Assertions.assertEquals(20, NumberUtils.getLong(null, 20L));
+ }
+
+ @Test
+ @DisplayName("Test nullable Int")
+ void testNullableInt() {
+ Assertions.assertEquals(10, NumberUtils.getInt(10, 20));
+ Assertions.assertEquals(20, NumberUtils.getInt((Integer) null, 20));
+ }
+
+ @Test
+ @DisplayName("Test nullable Float")
+ void testNullableFloat() {
+ Assertions.assertEquals(10, NumberUtils.getFloat(10F, 20F));
+ Assertions.assertEquals(20, NumberUtils.getFloat(null, 20F));
+ }
+
+ @Test
+ @DisplayName("Test decimal rounding")
+ void testRounding() {
+ Assertions.assertEquals("5.25", NumberUtils.roundDecimalNumber(5.249999999999));
+ }
+
+}