ENTRIES = new HashMap<>();
+
+ static {
+ ENTRIES.put("true", TRUE);
+ ENTRIES.put("false", FALSE);
+ ENTRIES.put("placed", PLACED);
+ }
+ }
+
+ /**
+ * All blocks except for protected ones may be broken.
+ */
+ static final BuildMode TRUE = (Player player, GameWorld gameWorld, Block block) -> true;
+ /**
+ * Blocks may not be broken.
+ */
+ static final BuildMode FALSE = (Player player, GameWorld gameWorld, Block block) -> false;
+ /**
+ * Blocks placed by players may be broken.
+ */
+ static final BuildMode PLACED = (Player player, GameWorld gameWorld, Block block) -> gameWorld.getPlacedBlocks().contains(block);
+
+ /**
+ * Returns if the block can be broken or placed by the player.
+ *
+ * The plugin protects dungeon signs before checking this.
+ *
+ * @param player the player who breaks or places the block
+ * @param gameWorld the world the block is in
+ * @param block the block
+ * @return if the block can be broken or placed by the player
+ */
+ boolean check(Player player, GameWorld gameWorld, Block block);
+
+}
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 b5a44503..72167211 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
@@ -15,14 +15,19 @@
package de.erethon.dungeonsxl.api.dungeon;
import de.erethon.caliburn.item.ExItem;
+import de.erethon.caliburn.item.VanillaItem;
import de.erethon.caliburn.mob.ExMob;
import de.erethon.dungeonsxl.api.DungeonsAPI;
+import de.erethon.dungeonsxl.api.world.GameWorld;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
/**
* A functional interface to deserialize a raw value read from a configuration.
@@ -79,6 +84,28 @@ public interface ConfigReader {
}
return map;
};
+ static final ConfigReader BUILD_MODE_READER = (api, value) -> {
+ if (value instanceof Boolean) {
+ return (Boolean) value ? BuildMode.TRUE : BuildMode.FALSE;
+ } else if (value instanceof String) {
+ return BuildMode.Registry.ENTRIES.get(((String) value).toLowerCase());
+ } else if (value instanceof List) {
+ return (Player p, GameWorld w, Block b) -> ((List) value).contains(VanillaItem.get(b.getType()).getId());
+ } else {
+ Map> whitelist = TOOL_BLOCK_MAP_READER.read(api, value);
+ if (whitelist == null) {
+ return null;
+ }
+ return (Player p, GameWorld w, Block b) -> {
+ ExItem type = VanillaItem.get(b.getType());
+ ExItem breakTool = api.getCaliburn().getExItem(p.getItemInHand());
+ return whitelist.containsKey(type)
+ && (whitelist.get(type) == null
+ || whitelist.get(type).isEmpty()
+ || whitelist.get(type).contains(breakTool));
+ };
+ }
+ };
/**
* 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 8da1a8e6..c72b89db 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
@@ -14,7 +14,9 @@
*/
package de.erethon.dungeonsxl.api.dungeon;
+import de.erethon.caliburn.CaliburnAPI;
import de.erethon.caliburn.item.ExItem;
+import de.erethon.caliburn.item.VanillaItem;
import de.erethon.caliburn.mob.ExMob;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.misc.EnumUtil;
@@ -22,6 +24,7 @@ import de.erethon.commons.misc.NumberUtil;
import de.erethon.dungeonsxl.api.DungeonsAPI;
import de.erethon.dungeonsxl.api.Requirement;
import de.erethon.dungeonsxl.api.Reward;
+import de.erethon.dungeonsxl.api.world.GameWorld;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -33,7 +36,9 @@ import java.util.Map;
import java.util.Set;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
+import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
/**
* Represents a game rule for a {@link Game}.
@@ -99,16 +104,7 @@ public class GameRule {
/**
* If players can build and destroy blocks in this world.
*/
- public static final GameRule BREAK_BLOCKS = new GameRule<>(Boolean.class, "breakBlocks", false);
- /**
- * If players may destroy blocks they placed themselves.
- */
- public static final GameRule BREAK_PLACED_BLOCKS = new GameRule<>(Boolean.class, "breakPlacedBlocks", false);
- /**
- * A whitelist of breakable blocks. breakBlocks is supposed to be set to "true" if this should be used.
- */
- public static final GameRule