package tc.oc.pgm.blockdrops; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import org.bukkit.block.BlockState; import org.bukkit.event.Event; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import org.bukkit.util.BlockVector; import tc.oc.commons.bukkit.event.BlockPunchEvent; import tc.oc.commons.bukkit.event.BlockTrampleEvent; import tc.oc.commons.bukkit.util.BlockStateUtils; import tc.oc.commons.bukkit.util.NMSHacks; import tc.oc.commons.core.util.Pair; import tc.oc.pgm.filters.Filter; import tc.oc.pgm.filters.query.IBlockQuery; import tc.oc.pgm.filters.query.MaterialQuery; import tc.oc.pgm.filters.query.PlayerBlockEventQuery; import tc.oc.pgm.kits.Kit; import tc.oc.pgm.kits.KitNode; import tc.oc.pgm.match.ParticipantState; import tc.oc.pgm.regions.FiniteBlockRegion; public class BlockDropsRuleSet { private final ImmutableList<BlockDropsRule> rules; public BlockDropsRuleSet() { this(ImmutableList.<BlockDropsRule>of()); } public BlockDropsRuleSet(List<BlockDropsRule> rules) { this.rules = ImmutableList.copyOf(rules); } public boolean isEmpty() { return this.rules.isEmpty(); } public ImmutableList<BlockDropsRule> getRules() { return this.rules; } /** * Return the subset of rules that may act on the given region */ public BlockDropsRuleSet subsetAffecting(FiniteBlockRegion region) { ImmutableList.Builder<BlockDropsRule> subset = ImmutableList.builder(); for(BlockDropsRule rule : this.rules) { for(BlockVector block : region.getBlockVectors()) { if(rule.region == null || rule.region.contains(block)) { subset.add(rule); break; } } } return new BlockDropsRuleSet(subset.build()); } /** * Return the subset of rules that may act on any of the given materials */ public BlockDropsRuleSet subsetAffecting(Set<MaterialData> materials) { ImmutableList.Builder<BlockDropsRule> subset = ImmutableList.builder(); for(BlockDropsRule rule : this.rules) { for(MaterialData material : materials) { if(rule.filter == null || rule.filter.query(MaterialQuery.of(material)) != Filter.QueryResponse.DENY) { subset.add(rule); break; } } } return new BlockDropsRuleSet(subset.build()); } public BlockDrops getDrops(BlockState block, MaterialData material) { return this.getDrops(null, block, material, null); } public BlockDrops getDrops(@Nullable Event event, BlockState block, ParticipantState player) { return this.getDrops(event, block, block.getData(), player); } public BlockDrops getDrops(@Nullable Event event, BlockState block, MaterialData material, @Nullable ParticipantState playerState) { List<Pair<Double, ItemStack>> items = new ArrayList<>(); List<Kit> kits = new ArrayList<>(); MaterialData replacement = null; Float fallChance = null; Float landChance = null; double fallSpeed = 1; int experience = 0; boolean custom = false; block = BlockStateUtils.cloneWithMaterial(block.getBlock(), material); boolean rightToolUsed; if(event instanceof BlockBreakEvent) { rightToolUsed = NMSHacks.canMineBlock(material, ((BlockBreakEvent) event).getPlayer().getItemInHand());; } else { rightToolUsed = true; } for (BlockDropsRule rule : this.rules) { if(event instanceof BlockPunchEvent && !rule.punch) continue; if(event instanceof BlockTrampleEvent && !rule.trample) continue; if(rule.region != null && !rule.region.contains(block)) continue; if(rule.filter != null) { final IBlockQuery query = PlayerBlockEventQuery.of(block, Optional.ofNullable(event), Optional.ofNullable(playerState)); if(!rule.filter.query(query).isAllowed()) continue; } custom = true; if(rule.drops.kit != null) { kits.add(rule.drops.kit); } if(rule.drops.replacement != null) { replacement = rule.drops.replacement; } if(rule.drops.fallChance != null) { fallChance = rule.drops.fallChance; } if(rule.drops.landChance != null) { landChance = rule.drops.landChance; } if(rule.drops.fallSpeed != null) { fallSpeed = rule.drops.fallSpeed; } if(rule.dropOnWrongTool || rightToolUsed) { items.addAll(rule.drops.items); experience += rule.drops.experience; } } return custom ? new BlockDrops(items, KitNode.of(kits), experience, replacement, fallChance, landChance, fallSpeed) : null; } }