mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-10-14 01:58:20 +02:00
new event McMMOModifyBlockDropItemEvent and mcMMO now modifies the drop list in BlockDropItemEvent instead of spawning items
Fixes #5214
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
package com.gmail.nossr50.events.items;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.block.BlockDropItemEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when mcMMO is modifying the amount of bonus drops to add to an Item involved in a {@link BlockDropItemEvent}.
|
||||
* <p>
|
||||
* This event is called before mcMMO has modified the ItemStack quantity on the {@link Item} entity.
|
||||
* <p>
|
||||
* This event is called once per Item entity that is involved in the {@link BlockDropItemEvent}.
|
||||
* <p>
|
||||
* This event is called during mcMMO logic on the {@link BlockDropItemEvent}, and can be used to
|
||||
* modify the quantity that mcMMO will add to the ItemStack.
|
||||
* <p>
|
||||
* This event is considered cancelled if it is either cancelled directly or if bonus drops are 0 or
|
||||
* less.
|
||||
*/
|
||||
public class McMMOModifyBlockDropItemEvent extends Event implements Cancellable {
|
||||
private final @NotNull BlockDropItemEvent blockDropItemEvent;
|
||||
private final int originalBonusAmountToAdd;
|
||||
private int modifiedItemStackQuantity;
|
||||
private final @NotNull Item itemThatHasBonusDrops;
|
||||
private boolean isCancelled = false;
|
||||
private final int originalItemStackQuantity;
|
||||
|
||||
public McMMOModifyBlockDropItemEvent(@NotNull BlockDropItemEvent blockDropItemEvent,
|
||||
@NotNull Item itemThatHasBonusDrops, int bonusDropsToAdd) {
|
||||
super(false);
|
||||
requireNonNull(blockDropItemEvent, "blockDropItemEvent cannot be null");
|
||||
requireNonNull(itemThatHasBonusDrops, "itemThatHasBonusDrops cannot be null");
|
||||
if (bonusDropsToAdd <= 0) {
|
||||
throw new IllegalArgumentException("cannot instantiate a new"
|
||||
+ " McMMOModifyBlockDropItemEvent with a bonusDropsToAdd that is <= 0");
|
||||
}
|
||||
this.blockDropItemEvent = blockDropItemEvent;
|
||||
this.itemThatHasBonusDrops = itemThatHasBonusDrops;
|
||||
this.originalItemStackQuantity = itemThatHasBonusDrops.getItemStack().getAmount();
|
||||
this.originalBonusAmountToAdd = bonusDropsToAdd;
|
||||
this.modifiedItemStackQuantity = itemThatHasBonusDrops.getItemStack().getAmount()
|
||||
+ bonusDropsToAdd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return isCancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.isCancelled = cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* The original BlockDropItemEvent which caused this event to be fired.
|
||||
* @return the original BlockDropItemEvent
|
||||
*/
|
||||
public @NotNull BlockDropItemEvent getBlockDropItemEvent() {
|
||||
return blockDropItemEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* The original bonus mcMMO would have added before any modifications to this event from
|
||||
* other plugins.
|
||||
* @return the original bonus amount to add
|
||||
*/
|
||||
public int getOriginalBonusAmountToAdd() {
|
||||
return originalBonusAmountToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Item entity that is being modified by this event.
|
||||
* This item returned by this call should not be modified, it is provided as a convenience.
|
||||
* @return the Item entity that is having bonus drops added to it.
|
||||
*/
|
||||
public @NotNull Item getItem() {
|
||||
return itemThatHasBonusDrops;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The modified ItemStack quantity that will be set on the Item entity if this event is not
|
||||
* cancelled.
|
||||
*
|
||||
* @return the modified ItemStack quantity that will be set on the Item entity
|
||||
*/
|
||||
public int getModifiedItemStackQuantity() {
|
||||
return modifiedItemStackQuantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* The original ItemStack quantity of the Item entity before any modifications from this event.
|
||||
* This is a reflection of the state of the Item when mcMMO fired this event.
|
||||
* It is possible it has modified since then, so do not rely on this value to be the current.
|
||||
* @return the original ItemStack quantity of the Item entity before any modifications from this event
|
||||
*/
|
||||
public int getOriginalItemStackQuantity() {
|
||||
return originalItemStackQuantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of bonus that will be added to the ItemStack quantity if this event is not
|
||||
* cancelled.
|
||||
* @return the amount of bonus that will be added to the ItemStack quantity
|
||||
*/
|
||||
public int getBonusAmountToAdd() {
|
||||
return Math.max(0, modifiedItemStackQuantity - originalItemStackQuantity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of bonus that will be added to the ItemStack quantity if this event is not
|
||||
* cancelled.
|
||||
* @param bonus the amount of bonus that will be added to the ItemStack quantity
|
||||
* @throws IllegalArgumentException if bonus is less than 0
|
||||
*/
|
||||
public void setBonusAmountToAdd(int bonus) {
|
||||
if (bonus < 0) throw new IllegalArgumentException("bonus must be >= 0");
|
||||
this.modifiedItemStackQuantity = originalItemStackQuantity + bonus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the modified ItemStack quantity that will be set on the Item entity if this event is not
|
||||
* cancelled. This CANNOT be lower than the original quantity of the ItemStack.
|
||||
* @param modifiedItemStackQuantity the modified ItemStack quantity that will be set on the Item entity
|
||||
* @throws IllegalArgumentException if modifiedItemStackQuantity is less than originalItemStackQuantity
|
||||
*/
|
||||
public void setModifiedItemStackQuantity(int modifiedItemStackQuantity) {
|
||||
if (modifiedItemStackQuantity < originalItemStackQuantity) {
|
||||
throw new IllegalArgumentException(
|
||||
"modifiedItemStackQuantity cannot be less than the originalItemStackQuantity");
|
||||
}
|
||||
this.modifiedItemStackQuantity = modifiedItemStackQuantity;
|
||||
}
|
||||
|
||||
public boolean isEffectivelyNoBonus() {
|
||||
return modifiedItemStackQuantity == originalItemStackQuantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate method for {@link BlockDropItemEvent}, gets the Player that is breaking the block
|
||||
* involved in this event.
|
||||
*
|
||||
* @return The Player that is breaking the block involved in this event
|
||||
*/
|
||||
public @NotNull Player getPlayer() {
|
||||
return blockDropItemEvent.getPlayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate method for {@link BlockDropItemEvent#getBlock()}.
|
||||
* Gets the Block involved in this event.
|
||||
*
|
||||
* @return the Block involved in this event
|
||||
*/
|
||||
public @NotNull Block getBlock() {
|
||||
return blockDropItemEvent.getBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate method for {@link BlockDropItemEvent#getBlockState()}.
|
||||
* Gets the BlockState of the block involved in this event.
|
||||
*
|
||||
* @return the BlockState of the block involved in this event
|
||||
*/
|
||||
public @NotNull BlockState getBlockState() {
|
||||
return blockDropItemEvent.getBlockState();
|
||||
}
|
||||
|
||||
private static final @NotNull HandlerList handlers = new HandlerList();
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static @NotNull HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toString() {
|
||||
return "McMMOModifyBlockDropItemEvent{" +
|
||||
"blockDropItemEvent=" + blockDropItemEvent +
|
||||
", originalBonusAmountToAdd=" + originalBonusAmountToAdd +
|
||||
", modifiedItemStackQuantity=" + modifiedItemStackQuantity +
|
||||
", itemThatHasBonusDrops=" + itemThatHasBonusDrops +
|
||||
", isCancelled=" + isCancelled +
|
||||
", originalItemStackQuantity=" + originalItemStackQuantity +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (!(o instanceof McMMOModifyBlockDropItemEvent that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return originalBonusAmountToAdd == that.originalBonusAmountToAdd
|
||||
&& modifiedItemStackQuantity == that.modifiedItemStackQuantity
|
||||
&& isCancelled == that.isCancelled
|
||||
&& originalItemStackQuantity == that.originalItemStackQuantity
|
||||
&& blockDropItemEvent.equals(that.blockDropItemEvent)
|
||||
&& itemThatHasBonusDrops.equals(
|
||||
that.itemThatHasBonusDrops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = blockDropItemEvent.hashCode();
|
||||
result = 31 * result + originalBonusAmountToAdd;
|
||||
result = 31 * result + modifiedItemStackQuantity;
|
||||
result = 31 * result + itemThatHasBonusDrops.hashCode();
|
||||
result = 31 * result + Boolean.hashCode(isCancelled);
|
||||
result = 31 * result + originalItemStackQuantity;
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.gmail.nossr50.listeners;
|
||||
|
||||
import static com.gmail.nossr50.util.MetadataConstants.METADATA_KEY_BONUS_DROPS;
|
||||
import static com.gmail.nossr50.util.Misc.getBlockCenter;
|
||||
|
||||
import com.gmail.nossr50.api.ItemSpawnReason;
|
||||
@@ -14,6 +15,7 @@ import com.gmail.nossr50.datatypes.skills.ToolType;
|
||||
import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
|
||||
import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
|
||||
import com.gmail.nossr50.events.fake.FakeEvent;
|
||||
import com.gmail.nossr50.events.items.McMMOModifyBlockDropItemEvent;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.skills.alchemy.Alchemy;
|
||||
import com.gmail.nossr50.skills.excavation.ExcavationManager;
|
||||
@@ -35,6 +37,8 @@ import com.gmail.nossr50.util.sounds.SoundType;
|
||||
import com.gmail.nossr50.worldguard.WorldGuardManager;
|
||||
import com.gmail.nossr50.worldguard.WorldGuardUtils;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@@ -62,6 +66,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.EntityBlockFormEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
|
||||
public class BlockListener implements Listener {
|
||||
private final mcMMO plugin;
|
||||
@@ -70,88 +75,96 @@ public class BlockListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = false)
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
|
||||
public void onBlockDropItemEvent(BlockDropItemEvent event) {
|
||||
//Make sure we clean up metadata on these blocks
|
||||
final Block block = event.getBlock();
|
||||
if (event.isCancelled()) {
|
||||
if (event.getBlock().hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) {
|
||||
event.getBlock().removeMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, plugin);
|
||||
if (block.hasMetadata(METADATA_KEY_BONUS_DROPS)) {
|
||||
block.removeMetadata(METADATA_KEY_BONUS_DROPS, plugin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int tileEntityTolerance = 1;
|
||||
try {
|
||||
int tileEntityTolerance = 1;
|
||||
|
||||
// beetroot hotfix, potentially other plants may need this fix
|
||||
if (event.getBlock().getType() == Material.BEETROOTS) {
|
||||
tileEntityTolerance = 2;
|
||||
}
|
||||
|
||||
//Track how many "things" are being dropped
|
||||
HashSet<Material> uniqueMaterials = new HashSet<>();
|
||||
boolean dontRewardTE = false; //If we suspect TEs are mixed in with other things don't reward bonus drops for anything that isn't a block
|
||||
int blockCount = 0;
|
||||
|
||||
for (Item item : event.getItems()) {
|
||||
//Track unique materials
|
||||
uniqueMaterials.add(item.getItemStack().getType());
|
||||
|
||||
//Count blocks as a second failsafe
|
||||
if (item.getItemStack().getType().isBlock()) {
|
||||
blockCount++;
|
||||
// beetroot hotfix, potentially other plants may need this fix
|
||||
final Material blockType = block.getType();
|
||||
if (blockType == Material.BEETROOTS) {
|
||||
tileEntityTolerance = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (uniqueMaterials.size() > tileEntityTolerance) {
|
||||
//Too many things are dropping, assume tile entities might be duped
|
||||
//Technically this would also prevent something like coal from being bonus dropped if you placed a TE above a coal ore when mining it but that's pretty edge case and this is a good solution for now
|
||||
dontRewardTE = true;
|
||||
}
|
||||
//Track how many "things" are being dropped
|
||||
final Set<Material> uniqueMaterials = new HashSet<>();
|
||||
boolean dontRewardTE = false; //If we suspect TEs are mixed in with other things don't reward bonus drops for anything that isn't a block
|
||||
int blockCount = 0;
|
||||
|
||||
//If there are more than one block in the item list we can't really trust it and will back out of rewarding bonus drops
|
||||
if (blockCount <= 1) {
|
||||
for (Item item : event.getItems()) {
|
||||
ItemStack is = new ItemStack(item.getItemStack());
|
||||
final List<Item> eventItems = event.getItems();
|
||||
for (Item item : eventItems) {
|
||||
//Track unique materials
|
||||
uniqueMaterials.add(item.getItemStack().getType());
|
||||
|
||||
if (is.getAmount() <= 0) {
|
||||
continue;
|
||||
//Count blocks as a second failsafe
|
||||
if (item.getItemStack().getType().isBlock()) {
|
||||
blockCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Ignore this abomination its rewritten in 2.2
|
||||
if (!mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.MINING, is.getType())
|
||||
&& !mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.HERBALISM, is.getType())
|
||||
&& !mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, is.getType())) {
|
||||
continue;
|
||||
}
|
||||
if (uniqueMaterials.size() > tileEntityTolerance) {
|
||||
// Too many things are dropping, assume tile entities might be duped
|
||||
// Technically this would also prevent something like coal from being bonus dropped
|
||||
// if you placed a TE above a coal ore when mining it but that's pretty edge case
|
||||
// and this is a good solution for now
|
||||
dontRewardTE = true;
|
||||
}
|
||||
|
||||
//If we suspect TEs might be duped only reward block
|
||||
if (dontRewardTE) {
|
||||
if (!is.getType().isBlock()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//If there are more than one block in the item list we can't really trust it
|
||||
// and will back out of rewarding bonus drops
|
||||
if (!block.getMetadata(METADATA_KEY_BONUS_DROPS).isEmpty()) {
|
||||
final MetadataValue bonusDropMeta = block
|
||||
.getMetadata(METADATA_KEY_BONUS_DROPS).get(0);
|
||||
if (blockCount <= 1) {
|
||||
for (final Item item : eventItems) {
|
||||
final ItemStack eventItemStack = item.getItemStack();
|
||||
int originalAmount = eventItemStack.getAmount();
|
||||
|
||||
if (event.getBlock().getMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS).size()
|
||||
> 0) {
|
||||
final BonusDropMeta bonusDropMeta =
|
||||
(BonusDropMeta) event.getBlock().getMetadata(
|
||||
MetadataConstants.METADATA_KEY_BONUS_DROPS).get(0);
|
||||
int bonusCount = bonusDropMeta.asInt();
|
||||
final Location centeredLocation = getBlockCenter(event.getBlock());
|
||||
for (int i = 0; i < bonusCount; i++) {
|
||||
if (eventItemStack.getAmount() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemUtils.spawnItemNaturally(event.getPlayer(),
|
||||
centeredLocation, is, ItemSpawnReason.BONUS_DROPS);
|
||||
final Material itemType = eventItemStack.getType();
|
||||
if (!mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.MINING, itemType)
|
||||
&& !mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.HERBALISM, itemType)
|
||||
&& !mcMMO.p.getGeneralConfig()
|
||||
.getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, itemType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//If we suspect TEs might be duped only reward block
|
||||
if (dontRewardTE) {
|
||||
if (!itemType.isBlock()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int amountToAddFromBonus = bonusDropMeta.asInt();
|
||||
final McMMOModifyBlockDropItemEvent modifyBlockDropItemEvent
|
||||
= new McMMOModifyBlockDropItemEvent(event, item, amountToAddFromBonus);
|
||||
plugin.getServer().getPluginManager().callEvent(modifyBlockDropItemEvent);
|
||||
if (!modifyBlockDropItemEvent.isCancelled()
|
||||
&& modifyBlockDropItemEvent.getModifiedItemStackQuantity() > originalAmount) {
|
||||
eventItemStack.setAmount(modifyBlockDropItemEvent.getModifiedItemStackQuantity());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getBlock().hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) {
|
||||
event.getBlock().removeMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, plugin);
|
||||
} finally {
|
||||
if (block.hasMetadata(METADATA_KEY_BONUS_DROPS)) {
|
||||
block.removeMetadata(METADATA_KEY_BONUS_DROPS, plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user