fixed #252 double drops

This commit is contained in:
Indyuce 2021-08-20 17:11:12 +02:00
parent e9b417f191
commit c1a98bc5a5
2 changed files with 196 additions and 204 deletions

View File

@ -1,33 +1,33 @@
package net.Indyuce.mmocore.api.droptable.dropitem; package net.Indyuce.mmocore.api.droptable.dropitem;
import org.apache.commons.lang.Validate; import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.droptable.DropTable; import net.Indyuce.mmocore.api.droptable.DropTable;
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance; import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
import net.Indyuce.mmocore.api.loot.LootBuilder; import net.Indyuce.mmocore.api.loot.LootBuilder;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import io.lumine.mythic.lib.api.MMOLineConfig; import org.apache.commons.lang.Validate;
public class DropTableDropItem extends DropItem { public class DropTableDropItem extends DropItem {
private final DropTable dropTable; private final DropTable dropTable;
public DropTableDropItem(MMOLineConfig config) { public DropTableDropItem(MMOLineConfig config) {
super(config); super(config);
config.validate("id"); config.validate("id");
String id = config.getString("id"); String id = config.getString("id");
Validate.isTrue(MMOCore.plugin.dropTableManager.has(id), "Could not find drop table " + id); Validate.isTrue(MMOCore.plugin.dropTableManager.has(id), "Could not find drop table " + id);
this.dropTable = MMOCore.plugin.dropTableManager.get(id); this.dropTable = MMOCore.plugin.dropTableManager.get(id);
} }
@Override @Override
public void collect(LootBuilder builder) { public void collect(LootBuilder builder) {
PlayerData data = builder.getEntity(); PlayerData data = builder.getEntity();
if(!data.isOnline()) return; if (!data.isOnline()) return;
if (dropTable.areConditionsMet(new ConditionInstance(data.getPlayer())))
for (int j = 0; j < rollAmount(); j++) if (dropTable.areConditionsMet(new ConditionInstance(data.getPlayer())))
builder.addLoot(dropTable.collect(builder)); for (int j = 0; j < rollAmount(); j++)
} dropTable.collect(builder);
}
} }

View File

@ -1,25 +1,5 @@
package net.Indyuce.mmocore.listener; package net.Indyuce.mmocore.listener;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.utils.Schedulers; import io.lumine.mythic.utils.Schedulers;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
@ -28,200 +8,212 @@ import net.Indyuce.mmocore.api.block.BlockInfo.BlockInfoOption;
import net.Indyuce.mmocore.api.block.VanillaBlockType; import net.Indyuce.mmocore.api.block.VanillaBlockType;
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance; import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent; import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
import net.Indyuce.mmocore.api.loot.LootBuilder;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import java.util.ArrayList;
import java.util.List;
public class BlockListener implements Listener { public class BlockListener implements Listener {
private static final BlockFace[] order = { BlockFace.UP, BlockFace.DOWN, BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH }; private static final BlockFace[] order = {BlockFace.UP, BlockFace.DOWN, BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onCustomBreak(BlockBreakEvent event) { public void onCustomBreak(BlockBreakEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE) if (player.getGameMode() == GameMode.CREATIVE)
return; return;
String savedData = event.getBlock().getBlockData().getAsString(); String savedData = event.getBlock().getBlockData().getAsString();
Block block = event.getBlock(); Block block = event.getBlock();
/* /*
* Check for custom mining in the current region first. * Check for custom mining in the current region first.
*/ */
boolean customMine = MMOCore.plugin.mineManager.isEnabled(player, block.getLocation()); boolean customMine = MMOCore.plugin.mineManager.isEnabled(player, block.getLocation());
if (!customMine) if (!customMine)
return; return;
/* /*
* If the block is a temporary block placed by block regen, immediately * If the block is a temporary block placed by block regen, immediately
* cancel the break event; also check for extra config provided block * cancel the break event; also check for extra config provided block
* conditions * conditions
*/ */
BlockInfo info = MMOCore.plugin.mineManager.getInfo(block); BlockInfo info = MMOCore.plugin.mineManager.getInfo(block);
boolean temporaryBlock = MMOCore.plugin.mineManager.isTemporaryBlock(block); boolean temporaryBlock = MMOCore.plugin.mineManager.isTemporaryBlock(block);
if ((temporaryBlock && info == null) || (info != null && !info.checkConditions(block))) { if ((temporaryBlock && info == null) || (info != null && !info.checkConditions(block))) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (info == null) { if (info == null) {
/* /*
* If players are prevented from breaking blocks in custom mining * If players are prevented from breaking blocks in custom mining
* regions * regions
*/ */
if (MMOCore.plugin.mineManager.shouldProtect()) if (MMOCore.plugin.mineManager.shouldProtect())
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
/* /*
* Extra breaking conditions. * Extra breaking conditions.
*/ */
if (!info.getBlock().breakRestrictions(block)) { if (!info.getBlock().breakRestrictions(block)) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
boolean canBreak = true; boolean canBreak = true;
ItemStack item = player.getInventory().getItemInMainHand(); ItemStack item = player.getInventory().getItemInMainHand();
if (!MMOCore.plugin.restrictionManager.checkPermissions(item, info.getBlock())) { if (!MMOCore.plugin.restrictionManager.checkPermissions(item, info.getBlock())) {
MMOCore.plugin.configManager.getSimpleMessage("cannot-break").send(player); MMOCore.plugin.configManager.getSimpleMessage("cannot-break").send(player);
canBreak = false; canBreak = false;
} }
/* /*
* Calls the event and listen for cancel & for drops changes... also * Find the block drops
* allows to apply tool durability & enchants to drops, etc. */
*/ boolean conditionsMet = !info.hasDropTable() || info.getDropTable().areConditionsMet(new ConditionInstance(player));
CustomBlockMineEvent called = new CustomBlockMineEvent(PlayerData.get(player), block, info, canBreak); List<ItemStack> drops = conditionsMet ? info.getDropTable().collect(new LootBuilder(PlayerData.get(player), 0)) : new ArrayList<>();
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled() || !called.canBreak()) { /*
event.setCancelled(true); * Calls the event and listen for cancel & for drops changes... also
return; * allows to apply tool durability & enchants to drops, etc.
} */
CustomBlockMineEvent called = new CustomBlockMineEvent(PlayerData.get(player), block, info, drops, !canBreak);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled()) {
event.setCancelled(true);
return;
}
/* /*
* Remove vanilla drops if needed and * Remove vanilla drops if needed and
* decreases the durability of the item * decreases the durability of the item
* used to mine the block. * used to mine the block.
*/ */
if (!info.getOption(BlockInfoOption.VANILLA_DROPS)) { if (!info.getOption(BlockInfoOption.VANILLA_DROPS)) {
event.setCancelled(true); event.setCancelled(true);
event.getBlock().setType(Material.AIR); event.getBlock().setType(Material.AIR);
MMOCoreUtils.decreaseDurability(player, EquipmentSlot.HAND, 1); MMOCoreUtils.decreaseDurability(player, EquipmentSlot.HAND, 1);
} }
/* /*
* Apply triggers, add experience info to the event so the other events * Apply triggers, add experience info to the event so the other events
* can give exp to other TOOLS and display HOLOGRAMS * can give exp to other TOOLS and display HOLOGRAMS
*/ */
if (info.hasTriggers() && !block.hasMetadata("player_placed")) { if (conditionsMet && info.hasTriggers() && !block.hasMetadata("player_placed")) {
if (!info.hasDropTable() || info.hasDropTable() && info.getDropTable().areConditionsMet(new ConditionInstance(player))) { PlayerData playerData = PlayerData.get(player);
PlayerData playerData = PlayerData.get(player); info.getTriggers().forEach(trigger -> trigger.apply(playerData));
info.getTriggers().forEach(trigger -> trigger.apply(playerData)); }
}
}
/* /*
* Apply drop tables * Apply drop tables
*/ *
if (info.hasDropTable()) { * You can apply the drop tables even if the block was placed by a player.
Location dropLocation = getSafeDropLocation(block, */
!block.getType().isSolid() || !(info.regenerates() && info.getRegenerationInfo().hasTemporaryBlock())); if (conditionsMet && info.hasDropTable()) {
for (ItemStack drop : called.getDrops()) Location dropLocation = getSafeDropLocation(block, !block.getType().isSolid() || !(info.regenerates() && info.getRegenerationInfo().hasTemporaryBlock()));
if (drop.getType() != Material.AIR && drop.getAmount() > 0) for (ItemStack drop : drops)
UtilityMethods.dropItemNaturally(dropLocation, drop); if (drop.getType() != Material.AIR && drop.getAmount() > 0)
} UtilityMethods.dropItemNaturally(dropLocation, drop);
}
/* /*
* Finally enable block regen. * Finally enable block regen.
*/ */
if (info.hasRegen()) { if (info.hasRegen())
Schedulers.sync().runLater(()-> { Schedulers.sync().runLater(() -> MMOCore.plugin.mineManager.initialize(info.startRegeneration(Bukkit.createBlockData(savedData), block.getLocation()), !temporaryBlock), 1);
MMOCore.plugin.mineManager.initialize(info.startRegeneration(Bukkit.createBlockData(savedData), block.getLocation()), !temporaryBlock); }
}, 1);
} /*
} * This is handled in a separate event because it
* needs to happen AFTER it's already checked the tag
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void unregisterPlayerPlacedBlocksTag(BlockBreakEvent event) {
if (event.getBlock().hasMetadata("player_placed"))
event.getBlock().removeMetadata("player_placed", MMOCore.plugin);
}
/* @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
* This is handled in a separate event because it public void registerPlayerPlacedBlocksTag(BlockPlaceEvent event) {
* needs to happen AFTER it's already checked the tag event.getBlock().setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
*/ }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void unregisterPlayerPlacedBlocksTag(BlockBreakEvent event) {
if(event.getBlock().hasMetadata("player_placed"))
event.getBlock().removeMetadata("player_placed", MMOCore.plugin);
}
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void registerPlayerPlacedBlocksTag(BlockPlaceEvent event) { public void blockPistonExtend(BlockPistonExtendEvent event) {
event.getBlock().setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true)); Block movedBlock = event.getBlock();
} if (!movedBlock.hasMetadata("player_placed"))
return;
BlockFace direction = event.getDirection();
// movedBlock = movedBlock.getRelative(direction, 2);
for (Block b : event.getBlocks())
if (b.hasMetadata("player_placed")) {
movedBlock = b.getRelative(direction);
movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void blockPistonRetract(BlockPistonRetractEvent event) {
BlockFace direction = event.getDirection();
Block movedBlock = event.getBlock().getRelative(direction);
movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) for (Block block : event.getBlocks()) {
public void blockPistonExtend(BlockPistonExtendEvent event) { movedBlock = block.getRelative(direction);
Block movedBlock = event.getBlock(); movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
if (!movedBlock.hasMetadata("player_placed")) }
return; }
BlockFace direction = event.getDirection();
// movedBlock = movedBlock.getRelative(direction, 2);
for (Block b : event.getBlocks()) /*
if (b.hasMetadata("player_placed")) { * Allows to mark cobblestone generated by cobblestone generators so that
movedBlock = b.getRelative(direction); * exp is not gained by these blocks
movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true)); */
} @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
} public void cobblestoneGeneratorHandling(BlockFormEvent event) {
if (event.getBlock().hasMetadata("player_placed"))
event.getBlock().removeMetadata("player_placed", MMOCore.plugin);
if (MMOCore.plugin.configManager.cobbleGeneratorXP) return;
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) if (event.getBlock().getType() == Material.WATER || event.getBlock().getType() == Material.LAVA)
public void blockPistonRetract(BlockPistonRetractEvent event) { if (event.getNewState().getType() == Material.COBBLESTONE || event.getNewState().getType() == Material.OBSIDIAN)
BlockFace direction = event.getDirection(); event.getNewState().setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
Block movedBlock = event.getBlock().getRelative(direction); }
movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
for (Block block : event.getBlocks()) { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
movedBlock = block.getRelative(direction); public void handlePlayerStatistics(CustomBlockMineEvent event) {
movedBlock.setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true)); if (event.getBlockInfo().getBlock() instanceof VanillaBlockType)
} event.getPlayer().incrementStatistic(Statistic.MINE_BLOCK, ((VanillaBlockType) event.getBlockInfo().getBlock()).getType());
} }
/* private Location getSafeDropLocation(Block block, boolean self) {
* Allows to mark cobblestone generated by cobblestone generators so that if (block.getType() == Material.AIR && self)
* exp is not gained by these blocks return block.getLocation();
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) for (BlockFace face : order) {
public void cobblestoneGeneratorHandling(BlockFormEvent event) { Block relative = block.getRelative(face);
if(event.getBlock().hasMetadata("player_placed")) if (!relative.getType().isSolid())
event.getBlock().removeMetadata("player_placed", MMOCore.plugin); return relative.getLocation().add(block.getLocation().subtract(relative.getLocation()).multiply(.6));
if(MMOCore.plugin.configManager.cobbleGeneratorXP) return; }
if (event.getBlock().getType() == Material.WATER || event.getBlock().getType() == Material.LAVA) return block.getLocation();
if (event.getNewState().getType() == Material.COBBLESTONE || event.getNewState().getType() == Material.OBSIDIAN) }
event.getNewState().setMetadata("player_placed", new FixedMetadataValue(MMOCore.plugin, true));
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void handlePlayerStatistics(CustomBlockMineEvent event) {
if (event.getBlockInfo().getBlock() instanceof VanillaBlockType)
event.getPlayer().incrementStatistic(Statistic.MINE_BLOCK, ((VanillaBlockType) event.getBlockInfo().getBlock()).getType());
}
private Location getSafeDropLocation(Block block, boolean self) {
if (block.getType() == Material.AIR && self)
return block.getLocation();
for (BlockFace face : order) {
Block relative = block.getRelative(face);
if (!relative.getType().isSolid())
return relative.getLocation().add(block.getLocation().subtract(relative.getLocation()).multiply(.6));
}
return block.getLocation();
}
} }