diff --git a/CHANGELOG.md b/CHANGELOG.md index 84befbac6..65659030b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,10 +35,12 @@ * Fixed #2794 * Fixed #2793 * Fixed #2809 +* Fixed a small exception which gets thrown when Slimefun is disabled due to an invalid environment * Fixed #2810 * Fixed #2804 * Fixed #2817 -* Fixed a small exception which gets thrown when Slimefun is disabled due to an invalid environment +* Fixed exceptions with inventories not being printed using the logger of the addon that caused it +* Fixed #2818 ## Release Candidate 20 (30 Jan 2021) 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 22afeab24..1f6e88ea8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java @@ -131,11 +131,23 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu; */ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { + /** + * Our static instance of {@link SlimefunPlugin}. + * Make sure to clean this up in {@link #onDisable()} ! + */ private static SlimefunPlugin instance; + /** + * Keep track of which {@link MinecraftVersion} we are on. + */ private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN; + + /** + * Keep track of whether this is a fresh install or a regular boot up. + */ private boolean isNewlyInstalled = false; + // Various things we need private final SlimefunRegistry registry = new SlimefunRegistry(); private final SlimefunCommand command = new SlimefunCommand(this); 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 HologramsService hologramsService = new HologramsService(this); + // Some other things we need private final IntegrationsManager integrations = new IntegrationsManager(this); private final SlimefunProfiler profiler = new SlimefunProfiler(); private final GPSNetwork gpsNetwork = new GPSNetwork(this); + // Even more things we need private NetworkManager networkManager; private LocalizationService local; @@ -234,6 +248,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private void onPluginStart() { long timestamp = System.nanoTime(); + // Check if Paper (<3) is installed if (PaperLib.isPaper()) { getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied."); } else { @@ -259,6 +274,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { int networkSize = config.getInt("networks.max-size"); + // Make sure that the network size is a valid input if (networkSize < 1) { getLogger().log(Level.WARNING, "Your 'networks.max-size' setting is misconfigured! It must be at least 1, it was set to: {0}", networkSize); networkSize = 1; @@ -660,7 +676,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { * This (re)loads every {@link SlimefunTag}. */ private void loadTags() { - for (SlimefunTag tag : SlimefunTag.valuesCache) { + for (SlimefunTag tag : SlimefunTag.values()) { try { // Only reload "empty" (or unloaded) Tags if (tag.isEmpty()) { 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 60097f43a..8c9f34f6f 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 @@ -9,6 +9,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -143,23 +144,35 @@ public class Talisman extends SlimefunItem { } @ParametersAreNonnullByDefault - public static boolean checkFor(Event e, SlimefunItemStack stack) { - return checkFor(e, stack.getItem()); + public static boolean trigger(Event e, SlimefunItemStack stack) { + return trigger(e, stack.getItem(), true); } @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)) { return false; } Talisman talisman = (Talisman) item; + if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) { return false; } Player p = getPlayerByEventType(e); - if (p == null || !pass(p, talisman)) { + + if (p == null || !talisman.canEffectsBeApplied(p)) { return false; } @@ -167,7 +180,7 @@ public class Talisman extends SlimefunItem { if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) { if (talisman.canUse(p, true)) { - activateTalisman(e, p, p.getInventory(), talisman, talismanItem); + activateTalisman(e, p, p.getInventory(), talisman, talismanItem, sendMessage); return true; } else { return false; @@ -177,7 +190,7 @@ public class Talisman extends SlimefunItem { if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) { if (talisman.canUse(p, true)) { - activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman); + activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage); return true; } else { return false; @@ -189,11 +202,14 @@ public class Talisman extends SlimefunItem { } @ParametersAreNonnullByDefault - private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem) { + private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem, boolean sendMessage) { consumeItem(inv, talisman, talismanItem); applyTalismanEffects(p, talisman); cancelEvent(e, talisman); - talisman.sendMessage(p); + + if (sendMessage) { + talisman.sendMessage(p); + } } @ParametersAreNonnullByDefault @@ -242,19 +258,45 @@ public class Talisman extends SlimefunItem { return suffix; } - @ParametersAreNonnullByDefault - private void sendMessage(Player p) { - if (!isSilent()) { - String messageKey = "messages.talisman." + getMessageSuffix(); + /** + * This method sends the given {@link Player} the message of this {@link Talisman}. + * Dependent on the selected config setting, the message will be sent via the actionbar + * or in the chat window. + * + * @param p + * The {@link Player} who shall receive the message + */ + public void sendMessage(@Nonnull Player p) { + Validate.notNull(p, "The Player must not be null."); - if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) { - SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false); - } else { - SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true); + // Check if this Talisman has a message + if (!isSilent()) { + try { + String messageKey = "messages.talisman." + getMessageSuffix(); + + if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) { + // Use the actionbar + SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false); + } else { + // Send the message via chat + SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true); + } + } catch (Exception x) { + error("An Exception was thrown while trying to send a Talisman message", x); } } } + private boolean canEffectsBeApplied(@Nonnull Player p) { + for (PotionEffect effect : getEffects()) { + if (effect != null && p.hasPotionEffect(effect.getType())) { + return false; + } + } + + return true; + } + @Nullable private static Player getPlayerByEventType(@Nonnull Event e) { if (e instanceof EntityDeathEvent) { @@ -274,14 +316,4 @@ public class Talisman extends SlimefunItem { 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; - } - } \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java index 1a5ae752c..ce21c0f35 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java @@ -1,12 +1,15 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; -import io.github.thebusybiscuit.cscorelib2.item.CustomItem; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; -import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman; -import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; -import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment; -import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -38,14 +41,13 @@ import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.util.Vector; -import javax.annotation.Nonnull; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; +import io.github.thebusybiscuit.cscorelib2.item.CustomItem; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman; +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; +import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; public class TalismanListener implements Listener { @@ -59,24 +61,24 @@ public class TalismanListener implements Listener { public void onDamageGet(EntityDamageEvent e) { if (e.getEntity() instanceof Player) { if (e.getCause() == DamageCause.LAVA) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA); + Talisman.trigger(e, SlimefunItems.TALISMAN_LAVA); } if (e.getCause() == DamageCause.DROWNING) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER); + Talisman.trigger(e, SlimefunItems.TALISMAN_WATER); } if (e.getCause() == DamageCause.FALL) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL); + Talisman.trigger(e, SlimefunItems.TALISMAN_ANGEL); } if (e.getCause() == DamageCause.FIRE) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE); + Talisman.trigger(e, SlimefunItems.TALISMAN_FIRE); } if (e.getCause() == DamageCause.ENTITY_ATTACK) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT); - Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR); + Talisman.trigger(e, SlimefunItems.TALISMAN_KNIGHT); + Talisman.trigger(e, SlimefunItems.TALISMAN_WARRIOR); } if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) { @@ -89,7 +91,7 @@ public class TalismanListener implements Listener { if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) { Projectile projectile = (Projectile) e.getDamager(); - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_WHIRLWIND)) { Player p = (Player) e.getEntity(); returnProjectile(p, projectile); } @@ -141,7 +143,7 @@ public class TalismanListener implements Listener { // We are also excluding entities which can pickup items, this is not perfect // but it at least prevents dupes by tossing items to zombies - if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) { + if (!entity.getCanPickupItems() && Talisman.trigger(e, SlimefunItems.TALISMAN_HUNTER)) { Collection extraDrops = getExtraDrops(e.getEntity(), e.getDrops()); for (ItemStack drop : extraDrops) { @@ -190,7 +192,7 @@ public class TalismanListener implements Listener { @EventHandler public void onItemBreak(PlayerItemBreakEvent e) { - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_ANVIL)) { PlayerInventory inv = e.getPlayer().getInventory(); int slot = inv.getHeldItemSlot(); @@ -223,7 +225,7 @@ public class TalismanListener implements Listener { @EventHandler public void onSprint(PlayerToggleSprintEvent e) { if (e.isSprinting()) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_TRAVELLER); + Talisman.trigger(e, SlimefunItems.TALISMAN_TRAVELLER); } } @@ -236,7 +238,7 @@ public class TalismanListener implements Listener { MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem(); 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 * 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 - 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 for (Map.Entry entry : enchantments.entrySet()) { if (entry.getValue() > 1 && random.nextInt(100) < 40) { @@ -264,7 +266,8 @@ public class TalismanListener implements Listener { @EventHandler(ignoreCancelled = true) public void onExperienceReceive(PlayerExpChangeEvent e) { - if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) { + // Check if the experience change was positive. + if (e.getAmount() > 0 && Talisman.trigger(e, SlimefunItems.TALISMAN_WISE)) { // Double-XP e.setAmount(e.getAmount() * 2); } @@ -272,21 +275,27 @@ public class TalismanListener implements Listener { @EventHandler(ignoreCancelled = true) public void onBlockDropItems(BlockDropItemEvent e) { - // We only want to double ores - Material type = e.getBlockState().getType(); - if (type.name().endsWith("_ORE")) { - ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); + ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); - if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { + // We are going to ignore Silk Touch here + if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { + Material type = e.getBlockState().getType(); + + // We only want to double ores + if (SlimefunTag.MINER_TALISMAN_TRIGGERS.isTagged(type)) { Collection drops = e.getItems(); - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_MINER, false)) { int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS)); + + // Keep track of whether we actually doubled the drops or not boolean doubledDrops = false; + // Loop through all dropped items for (Item drop : drops) { ItemStack droppedItem = drop.getItemStack(); + // We do not want to dupe blocks if (!droppedItem.getType().isBlock()) { int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount()); e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount)); @@ -294,8 +303,14 @@ public class TalismanListener implements Listener { } } + // Fixes #2077 if (doubledDrops) { - SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.miner", true); + Talisman talisman = SlimefunItems.TALISMAN_MINER.getItem(Talisman.class); + + // Fixes #2818 + if (talisman != null) { + talisman.sendMessage(e.getPlayer()); + } } } } @@ -305,7 +320,7 @@ public class TalismanListener implements Listener { @EventHandler public void onBlockBreak(BlockBreakEvent e) { if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN); + Talisman.trigger(e, SlimefunItems.TALISMAN_CAVEMAN); } } 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 d6893e361..14cf74b07 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 @@ -22,6 +22,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationExce import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator; +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel; @@ -190,6 +191,11 @@ public enum SlimefunTag implements Tag { */ 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. */ @@ -216,8 +222,16 @@ public enum SlimefunTag implements Tag { */ CAVEMAN_TALISMAN_TRIGGERS; + /** + * Lookup table for tag names. + */ private static final Map nameLookup = new HashMap<>(); - public static final SlimefunTag[] valuesCache = values(); + + /** + * Speed up lookups by caching the values instead of creating a new array + * on every method call. + */ + private static final SlimefunTag[] valuesCache = values(); static { for (SlimefunTag tag : valuesCache) { diff --git a/src/main/resources/tags/miner_talisman_triggers.json b/src/main/resources/tags/miner_talisman_triggers.json new file mode 100644 index 000000000..8dfd56669 --- /dev/null +++ b/src/main/resources/tags/miner_talisman_triggers.json @@ -0,0 +1,9 @@ +{ + "values" : [ + "#slimefun:fortune_compatible_ores", + { + "id" : "minecraft:gilded_blackstone", + "required" : false + } + ] +}