Add interactionBlacklist game rule; resolves #536

This commit is contained in:
Daniel Saukel 2020-04-17 01:07:25 +02:00
parent 3df0e333ee
commit 243f9ab7c9
3 changed files with 70 additions and 17 deletions

View File

@ -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<V> {
}
return set;
};
/**
* Reads a map of Caliburn items as tool keys and a set of Caliburn items as block values.
*/
static final ConfigReader<Map<ExItem, HashSet<ExItem>>> TOOL_BLOCK_MAP_READER = (api, value) -> {
if (!(value instanceof ConfigurationSection)) {
return null;
}
ConfigurationSection section = (ConfigurationSection) value;
Map<ExItem, HashSet<ExItem>> map = new HashMap<>();
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
ExItem tool = api.getCaliburn().getExItem(entry.getKey());
if (tool == null) {
continue;
}
HashSet<ExItem> 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.

View File

@ -109,23 +109,13 @@ public class GameRule<V> {
/**
* A whitelist of breakable blocks. breakBlocks is supposed to be set to "true" if this should be used.
*/
public static final GameRule<Map<ExItem, HashSet<ExItem>>> BREAK_WHITELIST = new MapGameRule<>("breakWhitelist", null, (api, value) -> {
if (!(value instanceof ConfigurationSection)) {
return null;
}
ConfigurationSection section = (ConfigurationSection) value;
Map<ExItem, HashSet<ExItem>> map = new HashMap<>();
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
ExItem tool = api.getCaliburn().getExItem(entry.getKey());
if (tool == null) {
continue;
}
HashSet<ExItem> blocks = new HashSet<>();
blocks.addAll(api.getCaliburn().deserializeExItemList(section, entry.getKey()));
map.put(tool, blocks);
}
return map;
}, HashMap::new);
public static final GameRule<Map<ExItem, HashSet<ExItem>>> 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<Map<ExItem, HashSet<ExItem>>> 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<V> {
* A whitelist of placeable blocks. placeBlocks is supposed to be set to "true" if this should be used.
*/
public static final GameRule<Set<ExItem>> PLACE_WHITELIST = new CollectionGameRule<>("placeWhitelist", null, ConfigReader.EX_ITEM_SET_READER, HashSet::new);
/**
* A set of blocks that do not fade.
*
* @see <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/block/BlockFadeEvent.html">org.bukkit.event.block.BlockFadeEvent</a>

View File

@ -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<ExItem, HashSet<ExItem>> 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();