From 243f9ab7c91fad7f2b442e09ccbe8882f84aa0c0 Mon Sep 17 00:00:00 2001 From: Daniel Saukel Date: Fri, 17 Apr 2020 01:07:25 +0200 Subject: [PATCH] Add interactionBlacklist game rule; resolves #536 --- .../dungeonsxl/api/dungeon/ConfigReader.java | 23 +++++++++++ .../dungeonsxl/api/dungeon/GameRule.java | 25 ++++-------- .../dungeonsxl/world/DWorldListener.java | 39 +++++++++++++++++++ 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/ConfigReader.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/ConfigReader.java index ea8663f1..17bf5d2e 100644 --- a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/ConfigReader.java +++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/ConfigReader.java @@ -18,8 +18,11 @@ import de.erethon.caliburn.item.ExItem; import de.erethon.caliburn.mob.ExMob; import de.erethon.dungeonsxl.api.DungeonsAPI; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import org.bukkit.configuration.ConfigurationSection; /** * A functional interface to deserialize a raw value read from a configuration. @@ -56,6 +59,26 @@ public interface ConfigReader { } return set; }; + /** + * Reads a map of Caliburn items as tool keys and a set of Caliburn items as block values. + */ + static final ConfigReader>> TOOL_BLOCK_MAP_READER = (api, value) -> { + if (!(value instanceof ConfigurationSection)) { + return null; + } + ConfigurationSection section = (ConfigurationSection) value; + Map> map = new HashMap<>(); + for (Map.Entry entry : section.getValues(false).entrySet()) { + ExItem tool = api.getCaliburn().getExItem(entry.getKey()); + if (tool == null) { + continue; + } + HashSet blocks = new HashSet<>(); + blocks.addAll(api.getCaliburn().deserializeExItemList(section, entry.getKey())); + map.put(tool, blocks); + } + return map; + }; /** * Reads a game rule state from the configuration. diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java index 426df9ec..29caf7ee 100644 --- a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java +++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java @@ -109,23 +109,13 @@ public class GameRule { /** * A whitelist of breakable blocks. breakBlocks is supposed to be set to "true" if this should be used. */ - public static final GameRule>> BREAK_WHITELIST = new MapGameRule<>("breakWhitelist", null, (api, value) -> { - if (!(value instanceof ConfigurationSection)) { - return null; - } - ConfigurationSection section = (ConfigurationSection) value; - Map> map = new HashMap<>(); - for (Map.Entry entry : section.getValues(false).entrySet()) { - ExItem tool = api.getCaliburn().getExItem(entry.getKey()); - if (tool == null) { - continue; - } - HashSet blocks = new HashSet<>(); - blocks.addAll(api.getCaliburn().deserializeExItemList(section, entry.getKey())); - map.put(tool, blocks); - } - return map; - }, HashMap::new); + public static final GameRule>> BREAK_WHITELIST + = new MapGameRule<>("breakWhitelist", null, ConfigReader.TOOL_BLOCK_MAP_READER, HashMap::new); + /** + * A blacklist of block types players cannot interact with. + */ + public static final GameRule>> INTERACTION_BLACKLIST + = new MapGameRule<>("interactionBlacklist", null, ConfigReader.TOOL_BLOCK_MAP_READER, HashMap::new); /** * A list of all entity types that shall be protected from damage. If this is left out AND if breakBlocks is false, armor stands, paintings and item frames * will be protected by default. If this is left out and if breakBlocks is true, nothing will be protected by default. @@ -151,6 +141,7 @@ public class GameRule { * A whitelist of placeable blocks. placeBlocks is supposed to be set to "true" if this should be used. */ public static final GameRule> PLACE_WHITELIST = new CollectionGameRule<>("placeWhitelist", null, ConfigReader.EX_ITEM_SET_READER, HashSet::new); + /** * A set of blocks that do not fade. * * @see org.bukkit.event.block.BlockFadeEvent diff --git a/core/src/main/java/de/erethon/dungeonsxl/world/DWorldListener.java b/core/src/main/java/de/erethon/dungeonsxl/world/DWorldListener.java index 0356b6ea..a54663a0 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/world/DWorldListener.java +++ b/core/src/main/java/de/erethon/dungeonsxl/world/DWorldListener.java @@ -21,12 +21,15 @@ import de.erethon.caliburn.category.Category; import de.erethon.caliburn.item.ExItem; import de.erethon.caliburn.item.VanillaItem; import de.erethon.caliburn.mob.ExMob; +import de.erethon.commons.compatibility.Version; import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.api.dungeon.GameRule; import de.erethon.dungeonsxl.api.dungeon.GameRuleContainer; import de.erethon.dungeonsxl.api.world.EditWorld; import de.erethon.dungeonsxl.api.world.GameWorld; import de.erethon.dungeonsxl.api.world.InstanceWorld; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.bukkit.World; import org.bukkit.block.Block; @@ -47,8 +50,12 @@ import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.hanging.HangingBreakEvent; import org.bukkit.event.player.PlayerArmorStandManipulateEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.world.WorldInitEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; /** * @author Daniel Saukel, Frank Baumann, Milan Albrecht @@ -90,6 +97,38 @@ public class DWorldListener implements Listener { } } + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onBlockInteract(PlayerInteractEvent event) { + Block block = event.getClickedBlock(); + GameWorld gameWorld = plugin.getGameWorld(block.getWorld()); + if (gameWorld == null || gameWorld.isPlaying()) { + return; + } + + Map> blacklist = gameWorld.getDungeon().getRules().getState(GameRule.INTERACTION_BLACKLIST); + if (blacklist == null) { + return; + } + + ExItem material = VanillaItem.get(block.getType()); + ExItem tool = caliburn.getExItem(getItemInHand(event)); + if (blacklist.containsKey(material) + && (blacklist.get(material) == null + || blacklist.get(material).isEmpty() + || blacklist.get(material).contains(tool))) { + event.setCancelled(true); + } + } + + private ItemStack getItemInHand(PlayerInteractEvent event) { + PlayerInventory inventory = event.getPlayer().getInventory(); + if (Version.isAtLeast(Version.MC1_9)) { + return event.getHand() == EquipmentSlot.HAND ? inventory.getItemInMainHand() : inventory.getItemInOffHand(); + } else { + return inventory.getItemInHand(); + } + } + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onBlockPlace(BlockPlaceEvent event) { Block block = event.getBlock();