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

Merge branch 'master' into feature/auto-crafters

This commit is contained in:
TheBusyBiscuit 2021-02-10 18:34:34 +01:00 committed by GitHub
commit 2754703f9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 298 additions and 148 deletions

View File

@ -24,6 +24,7 @@ jobs:
chore: '🧹 Chores' chore: '🧹 Chores'
performance: '💡 Performance Optimization' performance: '💡 Performance Optimization'
api: '🔧 API' api: '🔧 API'
compatibility: '🤝 Compatibility'
- uses: thollander/actions-comment-pull-request@1.0.1 - uses: thollander/actions-comment-pull-request@1.0.1
name: Leave a comment about the applied label name: Leave a comment about the applied label
@ -49,6 +50,7 @@ jobs:
`chore/**` | 🧹 Chores `chore/**` | 🧹 Chores
`api/**` | 🔧 API `api/**` | 🔧 API
`performance/**` | 💡 Performance Optimization `performance/**` | 💡 Performance Optimization
`compatibility/**` | 🤝 Compatibility
<hr> <hr>
If your changes do not fall into any of these categories, don't worry. If your changes do not fall into any of these categories, don't worry.
You can just ignore this message in that case! 👀 You can just ignore this message in that case! 👀

View File

@ -36,7 +36,13 @@
#### Fixes #### Fixes
* Fixed #2794 * Fixed #2794
* Fixed #2793 * Fixed #2793
* Fixed #2809
* Fixed a small exception which gets thrown when Slimefun is disabled due to an invalid environment * Fixed a small exception which gets thrown when Slimefun is disabled due to an invalid environment
* Fixed #2810
* Fixed #2804
* Fixed #2817
* Fixed exceptions with inventories not being printed using the logger of the addon that caused it
* Fixed #2818
* Fixed #1161 * Fixed #1161
## Release Candidate 20 (30 Jan 2021) ## Release Candidate 20 (30 Jan 2021)

View File

@ -436,7 +436,7 @@
<dependency> <dependency>
<groupId>com.github.LoneDev6</groupId> <groupId>com.github.LoneDev6</groupId>
<artifactId>itemsadder-api</artifactId> <artifactId>itemsadder-api</artifactId>
<version>2.1.25</version> <version>2.1.35</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -157,7 +157,8 @@ public class LockedCategory extends Category {
for (Category category : parents) { for (Category category : parents) {
for (SlimefunItem item : category.getItems()) { for (SlimefunItem item : category.getItems()) {
if (!item.canUse(p, false)) { // Check if the Player has researched every item (if the item is enabled)
if (!item.isDisabledIn(p.getWorld()) && item.hasResearch() && !profile.hasUnlocked(item.getResearch())) {
return false; return false;
} }
} }

View File

@ -131,11 +131,23 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
*/ */
public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
/**
* Our static instance of {@link SlimefunPlugin}.
* Make sure to clean this up in {@link #onDisable()} !
*/
private static SlimefunPlugin instance; private static SlimefunPlugin instance;
/**
* Keep track of which {@link MinecraftVersion} we are on.
*/
private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN; private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN;
/**
* Keep track of whether this is a fresh install or a regular boot up.
*/
private boolean isNewlyInstalled = false; private boolean isNewlyInstalled = false;
// Various things we need
private final SlimefunRegistry registry = new SlimefunRegistry(); private final SlimefunRegistry registry = new SlimefunRegistry();
private final SlimefunCommand command = new SlimefunCommand(this); private final SlimefunCommand command = new SlimefunCommand(this);
private final TickerTask ticker = new TickerTask(); private final TickerTask ticker = new TickerTask();
@ -154,10 +166,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this); private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this);
private final HologramsService hologramsService = new HologramsService(this); private final HologramsService hologramsService = new HologramsService(this);
// Some other things we need
private final IntegrationsManager integrations = new IntegrationsManager(this); private final IntegrationsManager integrations = new IntegrationsManager(this);
private final SlimefunProfiler profiler = new SlimefunProfiler(); private final SlimefunProfiler profiler = new SlimefunProfiler();
private final GPSNetwork gpsNetwork = new GPSNetwork(this); private final GPSNetwork gpsNetwork = new GPSNetwork(this);
// Even more things we need
private NetworkManager networkManager; private NetworkManager networkManager;
private LocalizationService local; private LocalizationService local;
@ -234,6 +248,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private void onPluginStart() { private void onPluginStart() {
long timestamp = System.nanoTime(); long timestamp = System.nanoTime();
// Check if Paper (<3) is installed
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied."); getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied.");
} else { } else {
@ -259,6 +274,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
int networkSize = config.getInt("networks.max-size"); int networkSize = config.getInt("networks.max-size");
// Make sure that the network size is a valid input
if (networkSize < 1) { if (networkSize < 1) {
getLogger().log(Level.WARNING, "Your 'networks.max-size' setting is misconfigured! It must be at least 1, it was set to: {0}", networkSize); getLogger().log(Level.WARNING, "Your 'networks.max-size' setting is misconfigured! It must be at least 1, it was set to: {0}", networkSize);
networkSize = 1; networkSize = 1;
@ -660,7 +676,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
* This (re)loads every {@link SlimefunTag}. * This (re)loads every {@link SlimefunTag}.
*/ */
private void loadTags() { private void loadTags() {
for (SlimefunTag tag : SlimefunTag.valuesCache) { for (SlimefunTag tag : SlimefunTag.values()) {
try { try {
// Only reload "empty" (or unloaded) Tags // Only reload "empty" (or unloaded) Tags
if (tag.isEmpty()) { if (tag.isEmpty()) {

View File

@ -267,7 +267,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
SlimefunItem sfitem = category.getItems().get(target); SlimefunItem sfitem = category.getItems().get(target);
if (Slimefun.isEnabled(p, sfitem, false)) { if (!sfitem.isDisabledIn(p.getWorld())) {
displaySlimefunItem(menu, category, p, profile, sfitem, page, index); displaySlimefunItem(menu, category, p, profile, sfitem, page, index);
index++; index++;
} }

View File

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

View File

@ -9,6 +9,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -143,23 +144,35 @@ public class Talisman extends SlimefunItem {
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItemStack stack) { public static boolean trigger(Event e, SlimefunItemStack stack) {
return checkFor(e, stack.getItem()); return trigger(e, stack.getItem(), true);
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItem item) { public static boolean trigger(Event e, SlimefunItemStack stack, boolean sendMessage) {
return trigger(e, stack.getItem(), sendMessage);
}
@ParametersAreNonnullByDefault
public static boolean trigger(Event e, SlimefunItem item) {
return trigger(e, item, true);
}
@ParametersAreNonnullByDefault
public static boolean trigger(Event e, SlimefunItem item, boolean sendMessage) {
if (!(item instanceof Talisman)) { if (!(item instanceof Talisman)) {
return false; return false;
} }
Talisman talisman = (Talisman) item; Talisman talisman = (Talisman) item;
if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) { if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) {
return false; return false;
} }
Player p = getPlayerByEventType(e); Player p = getPlayerByEventType(e);
if (p == null || !pass(p, talisman)) {
if (p == null || !talisman.canEffectsBeApplied(p)) {
return false; return false;
} }
@ -167,7 +180,7 @@ public class Talisman extends SlimefunItem {
if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) { if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) {
if (talisman.canUse(p, true)) { if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getInventory(), talisman, talismanItem); activateTalisman(e, p, p.getInventory(), talisman, talismanItem, sendMessage);
return true; return true;
} else { } else {
return false; return false;
@ -177,7 +190,7 @@ public class Talisman extends SlimefunItem {
if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) { if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) {
if (talisman.canUse(p, true)) { if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman); activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage);
return true; return true;
} else { } else {
return false; return false;
@ -189,11 +202,14 @@ public class Talisman extends SlimefunItem {
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem) { private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem, boolean sendMessage) {
consumeItem(inv, talisman, talismanItem); consumeItem(inv, talisman, talismanItem);
applyTalismanEffects(p, talisman); applyTalismanEffects(p, talisman);
cancelEvent(e, talisman); cancelEvent(e, talisman);
talisman.sendMessage(p);
if (sendMessage) {
talisman.sendMessage(p);
}
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@ -242,19 +258,45 @@ public class Talisman extends SlimefunItem {
return suffix; return suffix;
} }
@ParametersAreNonnullByDefault /**
private void sendMessage(Player p) { * This method sends the given {@link Player} the message of this {@link Talisman}.
if (!isSilent()) { * Dependent on the selected config setting, the message will be sent via the actionbar
String messageKey = "messages.talisman." + getMessageSuffix(); * or in the chat window.
*
* @param p
* The {@link Player} who shall receive the message
*/
public void sendMessage(@Nonnull Player p) {
Validate.notNull(p, "The Player must not be null.");
if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) { // Check if this Talisman has a message
SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false); if (!isSilent()) {
} else { try {
SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true); String messageKey = "messages.talisman." + getMessageSuffix();
if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) {
// Use the actionbar
SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false);
} else {
// Send the message via chat
SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true);
}
} catch (Exception x) {
error("An Exception was thrown while trying to send a Talisman message", x);
} }
} }
} }
private boolean canEffectsBeApplied(@Nonnull Player p) {
for (PotionEffect effect : getEffects()) {
if (effect != null && p.hasPotionEffect(effect.getType())) {
return false;
}
}
return true;
}
@Nullable @Nullable
private static Player getPlayerByEventType(@Nonnull Event e) { private static Player getPlayerByEventType(@Nonnull Event e) {
if (e instanceof EntityDeathEvent) { if (e instanceof EntityDeathEvent) {
@ -274,14 +316,4 @@ public class Talisman extends SlimefunItem {
return null; return null;
} }
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;
}
}
return true;
}
} }

View File

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

View File

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

View File

@ -120,11 +120,10 @@ public class SlimefunItemInteractListener implements Listener {
boolean interactable = sfItem.callItemHandler(BlockUseHandler.class, handler -> handler.onRightClick(event)); boolean interactable = sfItem.callItemHandler(BlockUseHandler.class, handler -> handler.onRightClick(event));
if (!interactable) { if (!interactable) {
String id = optional.get().getId();
Player p = event.getPlayer(); Player p = event.getPlayer();
if (BlockMenuPreset.isInventory(id)) { if (BlockMenuPreset.isInventory(sfItem.getId())) {
openInventory(p, id, event.getInteractEvent().getClickedBlock(), event); openInventory(p, sfItem, event.getInteractEvent().getClickedBlock(), event);
return false; return false;
} }
} }
@ -134,27 +133,31 @@ public class SlimefunItemInteractListener implements Listener {
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
private void openInventory(Player p, String id, Block clickedBlock, PlayerRightClickEvent event) { private void openInventory(Player p, SlimefunItem item, Block clickedBlock, PlayerRightClickEvent event) {
if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { try {
event.getInteractEvent().setCancelled(true); if (!p.isSneaking() || event.getItem().getType() == Material.AIR) {
event.getInteractEvent().setCancelled(true);
if (BlockStorage.hasUniversalInventory(id)) { if (BlockStorage.hasUniversalInventory(item.getId())) {
UniversalBlockMenu menu = BlockStorage.getUniversalInventory(id); UniversalBlockMenu menu = BlockStorage.getUniversalInventory(item.getId());
if (menu.canOpen(clickedBlock, p)) { if (menu.canOpen(clickedBlock, p)) {
menu.open(p); menu.open(p);
} else { } else {
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
} }
} else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) { } else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) {
BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation()); BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation());
if (menu.canOpen(clickedBlock, p)) { if (menu.canOpen(clickedBlock, p)) {
menu.open(p); menu.open(p);
} else { } else {
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
}
} }
} }
} catch (Exception | LinkageError x) {
item.error("An Exception was caught while trying to open the Inventory", x);
} }
} }

View File

@ -1,12 +1,15 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners; package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import java.util.ArrayList;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import java.util.Collection;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import java.util.List;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman; import java.util.Map;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; import java.util.Random;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment; import java.util.concurrent.ThreadLocalRandom;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@ -38,14 +41,13 @@ import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import javax.annotation.Nonnull; import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import javax.annotation.ParametersAreNonnullByDefault; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import java.util.ArrayList; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import java.util.Collection; import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
import java.util.List; import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
import java.util.Map; import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import java.util.Random; import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import java.util.concurrent.ThreadLocalRandom;
public class TalismanListener implements Listener { public class TalismanListener implements Listener {
@ -59,24 +61,24 @@ public class TalismanListener implements Listener {
public void onDamageGet(EntityDamageEvent e) { public void onDamageGet(EntityDamageEvent e) {
if (e.getEntity() instanceof Player) { if (e.getEntity() instanceof Player) {
if (e.getCause() == DamageCause.LAVA) { if (e.getCause() == DamageCause.LAVA) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA); Talisman.trigger(e, SlimefunItems.TALISMAN_LAVA);
} }
if (e.getCause() == DamageCause.DROWNING) { if (e.getCause() == DamageCause.DROWNING) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER); Talisman.trigger(e, SlimefunItems.TALISMAN_WATER);
} }
if (e.getCause() == DamageCause.FALL) { if (e.getCause() == DamageCause.FALL) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL); Talisman.trigger(e, SlimefunItems.TALISMAN_ANGEL);
} }
if (e.getCause() == DamageCause.FIRE) { if (e.getCause() == DamageCause.FIRE) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE); Talisman.trigger(e, SlimefunItems.TALISMAN_FIRE);
} }
if (e.getCause() == DamageCause.ENTITY_ATTACK) { if (e.getCause() == DamageCause.ENTITY_ATTACK) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT); Talisman.trigger(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR); Talisman.trigger(e, SlimefunItems.TALISMAN_WARRIOR);
} }
if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) { if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) {
@ -89,7 +91,7 @@ public class TalismanListener implements Listener {
if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) { if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) {
Projectile projectile = (Projectile) e.getDamager(); Projectile projectile = (Projectile) e.getDamager();
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) { if (Talisman.trigger(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
Player p = (Player) e.getEntity(); Player p = (Player) e.getEntity();
returnProjectile(p, projectile); returnProjectile(p, projectile);
} }
@ -141,7 +143,7 @@ public class TalismanListener implements Listener {
// We are also excluding entities which can pickup items, this is not perfect // We are also excluding entities which can pickup items, this is not perfect
// but it at least prevents dupes by tossing items to zombies // but it at least prevents dupes by tossing items to zombies
if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) { if (!entity.getCanPickupItems() && Talisman.trigger(e, SlimefunItems.TALISMAN_HUNTER)) {
Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops()); Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops());
for (ItemStack drop : extraDrops) { for (ItemStack drop : extraDrops) {
@ -190,7 +192,7 @@ public class TalismanListener implements Listener {
@EventHandler @EventHandler
public void onItemBreak(PlayerItemBreakEvent e) { public void onItemBreak(PlayerItemBreakEvent e) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) { if (Talisman.trigger(e, SlimefunItems.TALISMAN_ANVIL)) {
PlayerInventory inv = e.getPlayer().getInventory(); PlayerInventory inv = e.getPlayer().getInventory();
int slot = inv.getHeldItemSlot(); int slot = inv.getHeldItemSlot();
@ -223,7 +225,7 @@ public class TalismanListener implements Listener {
@EventHandler @EventHandler
public void onSprint(PlayerToggleSprintEvent e) { public void onSprint(PlayerToggleSprintEvent e) {
if (e.isSprinting()) { if (e.isSprinting()) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_TRAVELLER); Talisman.trigger(e, SlimefunItems.TALISMAN_TRAVELLER);
} }
} }
@ -236,7 +238,7 @@ public class TalismanListener implements Listener {
MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem(); MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem();
TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet()); TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet());
if (enchantment != null && Talisman.checkFor(e, SlimefunItems.TALISMAN_MAGICIAN)) { if (enchantment != null && Talisman.trigger(e, SlimefunItems.TALISMAN_MAGICIAN)) {
/* /*
* Fix #2679 * Fix #2679
* By default, the Bukkit API doesn't allow us to give enchantment books extra enchantments. * By default, the Bukkit API doesn't allow us to give enchantment books extra enchantments.
@ -249,7 +251,7 @@ public class TalismanListener implements Listener {
} }
// Wizard Talisman // Wizard Talisman
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) { if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.trigger(e, SlimefunItems.TALISMAN_WIZARD)) {
// Randomly lower some enchantments // Randomly lower some enchantments
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) { for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
if (entry.getValue() > 1 && random.nextInt(100) < 40) { if (entry.getValue() > 1 && random.nextInt(100) < 40) {
@ -264,7 +266,8 @@ public class TalismanListener implements Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onExperienceReceive(PlayerExpChangeEvent e) { public void onExperienceReceive(PlayerExpChangeEvent e) {
if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) { // Check if the experience change was positive.
if (e.getAmount() > 0 && Talisman.trigger(e, SlimefunItems.TALISMAN_WISE)) {
// Double-XP // Double-XP
e.setAmount(e.getAmount() * 2); e.setAmount(e.getAmount() * 2);
} }
@ -272,21 +275,27 @@ public class TalismanListener implements Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onBlockDropItems(BlockDropItemEvent e) { public void onBlockDropItems(BlockDropItemEvent e) {
// We only want to double ores ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
Material type = e.getBlockState().getType();
if (type.name().endsWith("_ORE")) {
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { // We are going to ignore Silk Touch here
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
Material type = e.getBlockState().getType();
// We only want to double ores
if (SlimefunTag.MINER_TALISMAN_TRIGGERS.isTagged(type)) {
Collection<Item> drops = e.getItems(); Collection<Item> drops = e.getItems();
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) { if (Talisman.trigger(e, SlimefunItems.TALISMAN_MINER, false)) {
int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS)); int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
// Keep track of whether we actually doubled the drops or not
boolean doubledDrops = false; boolean doubledDrops = false;
// Loop through all dropped items
for (Item drop : drops) { for (Item drop : drops) {
ItemStack droppedItem = drop.getItemStack(); ItemStack droppedItem = drop.getItemStack();
// We do not want to dupe blocks
if (!droppedItem.getType().isBlock()) { if (!droppedItem.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount()); int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount());
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount)); e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount));
@ -294,8 +303,14 @@ public class TalismanListener implements Listener {
} }
} }
// Fixes #2077
if (doubledDrops) { if (doubledDrops) {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.miner", true); Talisman talisman = SlimefunItems.TALISMAN_MINER.getItem(Talisman.class);
// Fixes #2818
if (talisman != null) {
talisman.sendMessage(e.getPlayer());
}
} }
} }
} }
@ -305,7 +320,7 @@ public class TalismanListener implements Listener {
@EventHandler @EventHandler
public void onBlockBreak(BlockBreakEvent e) { public void onBlockBreak(BlockBreakEvent e) {
if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) { if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN); Talisman.trigger(e, SlimefunItems.TALISMAN_CAVEMAN);
} }
} }

View File

@ -22,6 +22,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationExce
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.accelerators.CropGrowthAccelerator; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.accelerators.CropGrowthAccelerator;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel;
@ -190,6 +191,11 @@ public enum SlimefunTag implements Tag<Material> {
*/ */
INDUSTRIAL_MINER_ORES, INDUSTRIAL_MINER_ORES,
/**
* All materials (ores) which can be doubled using a Miner {@link Talisman}.
*/
MINER_TALISMAN_TRIGGERS,
/** /**
* All materials (crops) which the {@link CropGrowthAccelerator} will recognize. * All materials (crops) which the {@link CropGrowthAccelerator} will recognize.
*/ */
@ -216,8 +222,16 @@ public enum SlimefunTag implements Tag<Material> {
*/ */
CAVEMAN_TALISMAN_TRIGGERS; CAVEMAN_TALISMAN_TRIGGERS;
/**
* Lookup table for tag names.
*/
private static final Map<String, SlimefunTag> nameLookup = new HashMap<>(); private static final Map<String, SlimefunTag> nameLookup = new HashMap<>();
public static final SlimefunTag[] valuesCache = values();
/**
* Speed up lookups by caching the values instead of creating a new array
* on every method call.
*/
private static final SlimefunTag[] valuesCache = values();
static { static {
for (SlimefunTag tag : valuesCache) { for (SlimefunTag tag : valuesCache) {

View File

@ -26,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.core.categories.SeasonalCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* Represents a category, which structure multiple {@link SlimefunItem} in the {@link SlimefunGuide}. * Represents a category, which structure multiple {@link SlimefunItem} in the {@link SlimefunGuide}.
@ -258,7 +257,7 @@ public class Category implements Keyed {
*/ */
public boolean isHidden(@Nonnull Player p) { public boolean isHidden(@Nonnull Player p) {
for (SlimefunItem slimefunItem : getItems()) { for (SlimefunItem slimefunItem : getItems()) {
if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) { if (!slimefunItem.isHidden() && !slimefunItem.isDisabledIn(p.getWorld())) {
return false; return false;
} }
} }

View File

@ -387,6 +387,26 @@ public class SlimefunItem implements Placeable {
return state != ItemState.ENABLED; return state != ItemState.ENABLED;
} }
/**
* This method returns whether this {@link SlimefunItem} is disabled
* for that specific {@link World}.
* Note that if the item is disabled globally, this method will still return false.
*
* @param world
* The {@link World} to check
*
* @return Whether this {@link SlimefunItem} is disabled in that world (or in general).
*/
public boolean isDisabledIn(@Nonnull World world) {
if (state == ItemState.UNREGISTERED) {
error("isDisabled(World) cannot be called before registering the item", new UnregisteredItemException(this));
return false;
}
// Check if the Item is disabled globally or in this specific world
return isDisabled() || !SlimefunPlugin.getWorldSettingsService().isEnabled(world, this);
}
/** /**
* This method returns the {@link SlimefunAddon} that registered this * This method returns the {@link SlimefunAddon} that registered this
* {@link SlimefunItem}. If this Item is from Slimefun itself, the current * {@link SlimefunItem}. If this Item is from Slimefun itself, the current
@ -1006,7 +1026,6 @@ public class SlimefunItem implements Placeable {
*/ */
public void error(@Nonnull String message, @Nonnull Throwable throwable) { public void error(@Nonnull String message, @Nonnull Throwable throwable) {
Validate.notNull(addon, "Cannot send an error for an unregistered item!"); Validate.notNull(addon, "Cannot send an error for an unregistered item!");
addon.getLogger().log(Level.SEVERE, "Item \"{0}\" from {1} v{2} has caused an Error!", new Object[] { id, addon.getName(), addon.getPluginVersion() }); addon.getLogger().log(Level.SEVERE, "Item \"{0}\" from {1} v{2} has caused an Error!", new Object[] { id, addon.getName(), addon.getPluginVersion() });
if (addon.getBugTrackerURL() != null) { if (addon.getBugTrackerURL() != null) {

View File

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