1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Fixes #2518 (+ refactoring and documentation)

This commit is contained in:
TheBusyBiscuit 2020-11-21 14:06:38 +01:00
parent 5bf3e38bae
commit 55188bfd0a
7 changed files with 134 additions and 48 deletions

View File

@ -74,6 +74,7 @@
* Fixed Slimefun Guide Settings showing "last activity" as a negative number
* Fixed Armor Stands getting damaged/pushed by Explosive Bow
* Fixed Sword of Beheading dropping Zombie/Skeleton Skulls from Zombie/Skeleton subvariants
* Fixed #2518
## Release Candidate 17 (17 Oct 2020)

View File

@ -11,6 +11,7 @@ import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
@ -19,12 +20,25 @@ import io.github.thebusybiscuit.cscorelib2.data.ComputedOptional;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
public class PlayerRightClickEvent extends Event {
/**
* The {@link PlayerRightClickEvent} is our custom version of the {@link PlayerInteractEvent}.
* But it is only triggered on right click.
* The main and (almost) sole purpose of this {@link Event} is to cache the {@link SlimefunItem}
* of the {@link ItemStack} and/or {@link Block} involved.
* This allows us (and addons) to efficiently check the used {@link SlimefunItem} without the need
* to do a heavy lookup or item comparison.
*
* @author TheBusyBiscuit
*
*/
public class PlayerRightClickEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
/**
* The original {@link PlayerInteractEvent}.
*/
private final PlayerInteractEvent event;
private final Player player;
private final Optional<ItemStack> itemStack;
private final Optional<Block> clickedBlock;
@ -35,33 +49,45 @@ public class PlayerRightClickEvent extends Event {
private ComputedOptional<SlimefunItem> slimefunItem = ComputedOptional.createNew();
private ComputedOptional<SlimefunItem> slimefunBlock = ComputedOptional.createNew();
private Result itemResult = Result.DEFAULT;
private Result blockResult = Result.DEFAULT;
private Result itemResult;
private Result blockResult;
public PlayerRightClickEvent(@Nonnull PlayerInteractEvent e) {
event = e;
player = e.getPlayer();
clickedBlock = Optional.ofNullable(e.getClickedBlock());
face = e.getBlockFace();
hand = e.getHand();
/**
* This constructs a new {@link PlayerRightClickEvent} based on the original {@link PlayerInteractEvent}.
* The {@link Result} of the original {@link PlayerInteractEvent} will be copied.
*
* @param originalEvent
* The original {@link PlayerInteractEvent}
*/
public PlayerRightClickEvent(@Nonnull PlayerInteractEvent originalEvent) {
super(originalEvent.getPlayer());
if (e.getItem() == null || e.getItem().getType() == Material.AIR || e.getItem().getAmount() == 0) {
event = originalEvent;
clickedBlock = Optional.ofNullable(originalEvent.getClickedBlock());
face = originalEvent.getBlockFace();
hand = originalEvent.getHand();
itemResult = originalEvent.useItemInHand();
blockResult = originalEvent.useInteractedBlock();
if (originalEvent.getItem() == null || originalEvent.getItem().getType() == Material.AIR || originalEvent.getItem().getAmount() == 0) {
itemStack = Optional.empty();
} else {
itemStack = Optional.of(e.getItem());
itemStack = Optional.of(originalEvent.getItem());
}
}
/**
* This returns the original {@link PlayerInteractEvent} that triggered this
* {@link PlayerRightClickEvent}.
*
* @return The original {@link PlayerInteractEvent}
*/
@Nonnull
public PlayerInteractEvent getInteractEvent() {
return event;
}
@Nonnull
public Player getPlayer() {
return player;
}
/**
* This method returns the {@link ItemStack} that was held in the hand of the {@link Player}.
* It will never return null, should there be no {@link ItemStack} then it will return
@ -121,6 +147,10 @@ public class PlayerRightClickEvent extends Event {
return slimefunBlock.getAsOptional();
}
/**
* This method cancels the {@link PlayerRightClickEvent}.
* This will deny the item and block usage.
*/
public void cancel() {
itemResult = Result.DENY;
blockResult = Result.DENY;

View File

@ -76,7 +76,7 @@ public class Contributor {
* specified role.
*
* @param role
* The role
* The role of this {@link Contributor}
* @param commits
* The amount of contributions made as that role
*/
@ -122,7 +122,7 @@ public class Contributor {
/**
* This returns a {@link List} of contributions for this {@link Contributor}.
* Each {@link Entry} consists of a {@link String} (for the role) and an {@link Integer}
* Each entry consists of a {@link String} (for the role) and an {@link Integer}
* (for the amount of commits).
*
* @return A {@link List} of contributions for this {@link Contributor}
@ -144,6 +144,8 @@ public class Contributor {
* @return The amount of contributions this {@link Contributor} submitted as the given role
*/
public int getContributions(@Nonnull String role) {
Validate.notNull(role, "The role cannot be null!");
return contributions.getOrDefault(role, 0);
}

View File

@ -76,6 +76,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksList
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GadgetsListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GrapplingHookListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.IronGolemListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MobDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
@ -87,7 +88,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBoots
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBowListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunGuideListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemConsumeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemInteractListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
@ -483,7 +484,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private void registerListeners() {
new SlimefunBootsListener(this);
new SlimefunItemListener(this);
new SlimefunItemInteractListener(this);
new SlimefunItemConsumeListener(this);
new BlockPhysicsListener(this);
new CargoNodeListener(this);
@ -493,6 +494,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new BlockListener(this);
new EnhancedFurnaceListener(this);
new ItemPickupListener(this);
new ItemDropListener(this);
new DeathpointListener(this);
new ExplosionsListener(this);
new DebugFishListener(this);

View File

@ -57,6 +57,9 @@ public class MagicianTalisman extends Talisman {
*
* @param item
* The {@link ItemStack} to find an {@link Enchantment} for
* @param existingEnchantments
* A {@link Set} containing the {@link Enchantment Enchantments} that currently exist on the
* {@link ItemStack}
*
* @return An applicable {@link TalismanEnchantment} or null
*/

View File

@ -0,0 +1,35 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import javax.annotation.Nonnull;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerDropItemEvent;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemDropHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
/**
* Listens to the {@link PlayerDropItemEvent} to call any {@link ItemDropHandler}.
*
* @author TheBusyBiscuit
*
* @see ItemDropHandler
*/
public class ItemDropListener implements Listener {
public ItemDropListener(@Nonnull SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onItemDrop(PlayerDropItemEvent e) {
for (ItemHandler handler : SlimefunItem.getPublicItemHandlers(ItemDropHandler.class)) {
if (((ItemDropHandler) handler).onItemDrop(e, e.getPlayer(), e.getItemDrop())) {
return;
}
}
}
}

View File

@ -7,56 +7,78 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
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.block.Action;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemDropHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
public class SlimefunItemListener implements Listener {
/**
* This {@link Listener} listens to the {@link PlayerInteractEvent}.
* It is also responsible for calling our {@link PlayerRightClickEvent} and triggering any
* {@link ItemUseHandler} or {@link BlockUseHandler} for the clicked {@link ItemStack} or {@link Block}.
*
* @author TheBusyBiscuit
* @author Liruxo
*
* @see PlayerRightClickEvent
* @see ItemUseHandler
* @see BlockUseHandler
*
*/
public class SlimefunItemInteractListener implements Listener {
public SlimefunItemListener(@Nonnull SlimefunPlugin plugin) {
public SlimefunItemInteractListener(@Nonnull SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onRightClick(PlayerInteractEvent e) {
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
// Exclude the Debug Fish here because it is handled in a seperate Listener
if (SlimefunUtils.isItemSimilar(e.getItem(), SlimefunItems.DEBUG_FISH, true)) {
return;
}
// Fire our custom Event
PlayerRightClickEvent event = new PlayerRightClickEvent(e);
Bukkit.getPluginManager().callEvent(event);
boolean itemUsed = e.getHand() == EquipmentSlot.OFF_HAND;
// Only handle the Item if it hasn't been denied
if (event.useItem() != Result.DENY) {
rightClickItem(e, event, itemUsed);
}
if (!itemUsed && event.useBlock() != Result.DENY && !rightClickBlock(e, event)) {
if (!itemUsed && event.useBlock() != Result.DENY && !rightClickBlock(event)) {
return;
}
/**
* If the original Event was not denied but the custom one was,
* we also want to deny the original one.
* This only applies for non-denied events because we do not want to
* override any protective checks.
*/
if (e.useInteractedBlock() != Result.DENY) {
e.setUseInteractedBlock(event.useBlock());
}
@ -83,12 +105,12 @@ public class SlimefunItemListener implements Listener {
}
@ParametersAreNonnullByDefault
private boolean rightClickBlock(PlayerInteractEvent e, PlayerRightClickEvent event) {
private boolean rightClickBlock(PlayerRightClickEvent event) {
Optional<SlimefunItem> optional = event.getSlimefunBlock();
if (optional.isPresent()) {
if (!Slimefun.hasUnlocked(e.getPlayer(), optional.get(), true)) {
e.setCancelled(true);
if (!Slimefun.hasUnlocked(event.getPlayer(), optional.get(), true)) {
event.getInteractEvent().setCancelled(true);
return false;
}
@ -96,10 +118,10 @@ public class SlimefunItemListener implements Listener {
if (!interactable) {
String id = optional.get().getId();
Player p = e.getPlayer();
Player p = event.getPlayer();
if (BlockMenuPreset.isInventory(id)) {
openInventory(p, id, e, event);
openInventory(p, id, event.getInteractEvent().getClickedBlock(), event);
return false;
}
}
@ -109,22 +131,22 @@ public class SlimefunItemListener implements Listener {
}
@ParametersAreNonnullByDefault
private void openInventory(Player p, String id, PlayerInteractEvent e, PlayerRightClickEvent event) {
if (!p.isSneaking() || Material.AIR == event.getItem().getType()) {
e.setCancelled(true);
private void openInventory(Player p, String id, Block clickedBlock, PlayerRightClickEvent event) {
if (!p.isSneaking() || event.getItem().getType() == Material.AIR) {
event.getInteractEvent().setCancelled(true);
if (BlockStorage.hasUniversalInventory(id)) {
UniversalBlockMenu menu = BlockStorage.getUniversalInventory(id);
if (menu.canOpen(e.getClickedBlock(), p)) {
if (menu.canOpen(clickedBlock, p)) {
menu.open(p);
} else {
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
}
} else if (BlockStorage.getStorage(e.getClickedBlock().getWorld()).hasInventory(e.getClickedBlock().getLocation())) {
BlockMenu menu = BlockStorage.getInventory(e.getClickedBlock().getLocation());
} else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) {
BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation());
if (menu.canOpen(e.getClickedBlock(), p)) {
if (menu.canOpen(clickedBlock, p)) {
menu.open(p);
} else {
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
@ -133,13 +155,4 @@ public class SlimefunItemListener implements Listener {
}
}
@EventHandler
public void onItemDrop(PlayerDropItemEvent e) {
for (ItemHandler handler : SlimefunItem.getPublicItemHandlers(ItemDropHandler.class)) {
if (((ItemDropHandler) handler).onItemDrop(e, e.getPlayer(), e.getItemDrop())) {
return;
}
}
}
}