members, String name, Dungeon dungeon);
+
+ /**
+ * Wraps the given {@link LivingEntity} object in a {@link DungeonMob} object.
+ *
+ * @param entity the entity
+ * @param gameWorld the game world where the entity is
+ * @return the wrapped DungeonMob
+ */
+ DungeonMob wrapEntity(LivingEntity entity, GameWorld gameWorld);
+
+ /**
+ * Wraps the given {@link LivingEntity} object in a {@link DungeonMob} object.
+ *
+ * @param entity the entity
+ * @param gameWorld the game world where the entity is
+ * @param triggerId the identifier used in mob triggers
+ * @return the wrapped DungeonMob
+ */
+ DungeonMob wrapEntity(LivingEntity entity, GameWorld gameWorld, String triggerId);
+
+ /**
+ * Wraps the given {@link LivingEntity} object in a {@link DungeonMob} object.
+ *
+ * @param entity the entity
+ * @param gameWorld the game world where the entity is
+ * @param type the ExMob type of the entity
+ * @return the wrapped DungeonMob
+ */
+ DungeonMob wrapEntity(LivingEntity entity, GameWorld gameWorld, ExMob type);
+
+ /**
+ * Wraps the given {@link LivingEntity} object in a {@link DungeonMob} object.
+ *
+ * @param entity the entity
+ * @param gameWorld the game world where the entity is
+ * @param type the ExMob type of the entity
+ * @param triggerId the identifier used in mob triggers
+ * @return the wrapped DungeonMob
+ */
+ DungeonMob wrapEntity(LivingEntity entity, GameWorld gameWorld, ExMob type, String triggerId);
+
+ /* Getters */
+ /**
+ * Returns an existing {@link DungeonMob} object that wraps the given {@link LivingEntity} object or null if none exists.
+ *
+ * @param entity the entity
+ * @return an existing {@link DungeonMob} object that wraps the given {@link LivingEntity} object or null if none exists
+ */
+ DungeonMob getDungeonMob(LivingEntity entity);
+
+ /**
+ * Returns the game the given group plays.
+ *
+ * @param group the group
+ * @return the game the given group plays
+ */
+ Game getGame(PlayerGroup group);
+
+ /**
+ * Returns the game the given player plays.
+ *
+ * @param player the player
+ * @return the game the given player plays
+ */
+ Game getGame(Player player);
+
+ /**
+ * Returns the game played in the given instance world.
+ *
+ * @param world the instance world
+ * @return the game played in the given instance world
+ */
+ Game getGame(World world);
+
+ /**
+ * Returns the GameWorld that wraps the given instance world.
+ *
+ * @param world the instance world
+ * @return the GameWorld that wraps the given instance world
+ */
+ GameWorld getGameWorld(World world);
+
+ /**
+ * Returns the EditWorld that wraps the given instance world.
+ *
+ * @param world the instance world
+ * @return the EditWorld that wraps the given instance worl
+ */
+ EditWorld getEditWorld(World world);
+
+ /**
+ * Returns if the given world is an instance.
+ *
+ * @param world the world
+ * @return if the given world is an instance
+ */
+ boolean isInstance(World world);
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/Requirement.java b/api/src/main/java/de/erethon/dungeonsxl/api/Requirement.java
new file mode 100644
index 00000000..629ebdba
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/Requirement.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api;
+
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+
+/**
+ * Something a player needs to fulfill in order to be allowed to start the game (= trigger a ready sign).
+ *
+ * @author Daniel Saukel
+ */
+public interface Requirement {
+
+ /**
+ * Sets up the requirement from the given requirements {@link de.erethon.dungeonsxl.api.dungeon.GameRule} section.
+ *
+ * @param config the requirements config section
+ */
+ void setup(ConfigurationSection config);
+
+ /**
+ * Returns if the given player fulfills the requirements. If true, this lets him start the game (= trigger a ready sign).
+ *
+ * @param player the player
+ * @return if the given player fulfills the requirements
+ */
+ boolean check(Player player);
+
+ /**
+ * This is fired after the {@link #check(Player)} has been accepted. It demands the requirement from the given player. This may be empty for a "key" or may
+ * take something away for a "fee" requirement.
+ *
+ * @param player the player
+ */
+ void demand(Player player);
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/Reward.java b/api/src/main/java/de/erethon/dungeonsxl/api/Reward.java
new file mode 100644
index 00000000..f5beb88b
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/Reward.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api;
+
+import org.bukkit.entity.Player;
+
+/**
+ * Something players are given when they successfully finish a {@link de.erethon.dungeonsxl.api.dungeon.Dungeon}.
+ *
+ * @see de.erethon.dungeonsxl.api.player.PlayerGroup#getRewards()
+ * @author Daniel Saukel
+ */
+public interface Reward {
+
+ /**
+ * Gives the reward to the given player.
+ *
+ * @param player the player
+ */
+ void giveTo(Player player);
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/Trigger.java b/api/src/main/java/de/erethon/dungeonsxl/api/Trigger.java
new file mode 100644
index 00000000..baa66f76
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/Trigger.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api;
+
+import org.bukkit.entity.Player;
+
+/**
+ * @deprecated stub
+ *
+ * @author Daniel Saukel
+ */
+@Deprecated
+public interface Trigger {
+
+ @Deprecated
+ boolean isTriggered();
+
+ @Deprecated
+ Player getPlayer();
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/CollectionGameRule.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/CollectionGameRule.java
new file mode 100644
index 00000000..1717ee32
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/CollectionGameRule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api.dungeon;
+
+import java.util.Collection;
+
+/**
+ * A {@link GameRule} where the value is a {@link java.util.Collection}.
+ *
+ * @param the type of the collection
+ * @param the type of the game rule value
+ * @author Daniel Saukel
+ */
+public class CollectionGameRule> extends GameRule {
+
+ public CollectionGameRule(Class type, String key, V defaultValue) {
+ super(type, key, defaultValue);
+ }
+
+ @Override
+ public void merge(GameRuleContainer overriding, GameRuleContainer subsidiary, GameRuleContainer writeTo) {
+ V write = writeTo.getState(this);
+ write.addAll(subsidiary.getState(this));
+ write.addAll(overriding.getState(this));
+ writeTo.setState(this, write);
+ }
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Dungeon.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Dungeon.java
new file mode 100644
index 00000000..a2b96a04
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Dungeon.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api.dungeon;
+
+import de.erethon.dungeonsxl.api.world.ResourceWorld;
+import java.util.List;
+
+/**
+ * A dungeon consists of floors and settings including its game rules.
+ *
+ * MFD = multiple floor dungeon; SFD = single floor dungeon.
+ *
+ * @author Daniel Saukel
+ */
+public interface Dungeon {
+
+ /**
+ * Returns the name.
+ *
+ * @return the name
+ */
+ String getName();
+
+ /**
+ * Sets the name to the given value.
+ *
+ * @param name the name
+ */
+ void setName(String name);
+
+ /**
+ * Returns if this dungeon has multiple floors.
+ *
+ * @return if this dungeon has multiple floors
+ */
+ boolean isMultiFloor();
+
+ /**
+ * Returns the map to instantiate.
+ *
+ * This method is the same as {@link #getStartFloor()} but a bit more intuitive for SFDs.
+ *
+ * @return the map to instantiate
+ */
+ default ResourceWorld getMap() {
+ return getStartFloor();
+ }
+
+ /**
+ * Returns the first floor of this dungeon.
+ *
+ * @return the first floor of this dungeon
+ */
+ ResourceWorld getStartFloor();
+
+ /**
+ * Sets the first floor of this dungeon.
+ *
+ * @param startFloor the startFloor to set
+ */
+ void setStartFloor(ResourceWorld startFloor);
+
+ /**
+ * Returns the last floor of this dungeon or null if this is an SFD.
+ *
+ * @return the last floor of this dungeon or null if this is an SFD
+ */
+ ResourceWorld getEndFloor();
+
+ /**
+ * Sets the last floor of this MFD.
+ *
+ * @param endFloor the last floor
+ */
+ void setEndFloor(ResourceWorld endFloor);
+
+ /**
+ * Returns a list of the floors without start and end floor.
+ *
+ * @return a list of the floors without start and end floor
+ */
+ List getFloors();
+
+ /**
+ * Adds the given floor.
+ *
+ * @param resource the resource to add
+ */
+ void addFloor(ResourceWorld resource);
+
+ /**
+ * Removes the given floor.
+ *
+ * @param resource the resource to remove
+ */
+ void removeFloor(ResourceWorld resource);
+
+ /**
+ * Returns the amount of floors in this dungeon including start and end floor.
+ *
+ * This may be less than the size of {@link #getFloors()} + 2 if not all floors from the list are used.
+ *
+ * @return the amount of floors in this dungeon including start and end floor
+ */
+ int getFloorCount();
+
+ /**
+ * Sets the amount of floors that shall be played.
+ *
+ * @param floorCount the amount of floors to set
+ */
+ void setFloorCount(int floorCount);
+
+ /**
+ * Returns if floors cannot be played once if floors are selected randomly from the list.
+ *
+ * @return the removeWhenPlayed if floors cannot be played once if floors are selected randomly from the list
+ */
+ boolean getRemoveWhenPlayed();
+
+ /**
+ * Sets if floors cannot be played once if floors are selected randomly from the list.
+ *
+ * @param removeWhenPlayed if floors cannot be played once if floors are selected randomly from the list
+ */
+ void setRemoveWhenPlayed(boolean removeWhenPlayed);
+
+ /**
+ * The values from this game rule container will override all values of the game rule containers of the dungeon's maps.
+ *
+ * @return the override values
+ */
+ GameRuleContainer getOverrideValues();
+
+ /**
+ * Sets the game rule container whose values override all values of the game rule containers of the dungeon's maps.
+ *
+ * @param rules the override values
+ */
+ void setOverrideValues(GameRuleContainer rules);
+
+ /**
+ * The values from this game rule container will be overriden by values of the game rule containers of the dungeon's maps. They will however still override
+ * the values from the main config.
+ *
+ * @return the default values
+ */
+ GameRuleContainer getDefaultValues();
+
+ /**
+ * Sets the game rule container whose values will be overriden by values of the game rule containers of the dungeon's maps. They will however still override
+ * the values from the main config.
+ *
+ * @param rules the default values
+ */
+ void setDefaultValues(GameRuleContainer rules);
+
+ /**
+ * Returns true if the floor is either in the floors list or the start / end floor.
+ *
+ * @param resource the ResourceWorld to check
+ * @return true if the floor is either in the floors list or the start / end floor.
+ */
+ default boolean containsFloor(ResourceWorld resource) {
+ return getFloors().contains(resource) || getStartFloor().equals(resource) || getEndFloor().equals(resource);
+ }
+
+ /**
+ * Returns true if the floor is either in the floors list or the start / end floor.
+ *
+ * @param mapName the name of the map to check
+ * @return true if the floor is either in the floors list or the start / end floor.
+ */
+ default boolean containsFloor(String mapName) {
+ for (ResourceWorld world : getFloors()) {
+ if (world.getName().equals(mapName)) {
+ return true;
+ }
+ }
+ return getStartFloor().getName().equals(mapName) || getEndFloor().getName().equals(mapName);
+ }
+
+ /**
+ * Returns the rules of this game.
+ *
+ * This is not necessarily represented 1:1 by a config file because it is usually merged together through {@link #setupRules()}.
+ *
+ * @return the rules of this game
+ */
+ GameRuleContainer getRules();
+
+ /**
+ * Sets the rules of the game.
+ *
+ * @param rules the rules
+ */
+ void setRules(GameRuleContainer rules);
+
+ /**
+ * Sets up the rules with the following priority: 1. Game type 2. Dungeon config: Override values 3. Floor config 4. Dungeon config: Default values 5. Main
+ * config: Default values 6. The default values
+ */
+ void setupRules();
+
+ /**
+ * Returns false if there are errors in the setup; true if not.
+ *
+ * @return false if there are errors in the setup; true if not
+ */
+ boolean isSetupCorrect();
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Game.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Game.java
new file mode 100644
index 00000000..cd0ec04d
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/Game.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api.dungeon;
+
+import de.erethon.commons.player.PlayerCollection;
+import de.erethon.dungeonsxl.api.player.PlayerGroup;
+import de.erethon.dungeonsxl.api.world.GameWorld;
+import de.erethon.dungeonsxl.api.world.ResourceWorld;
+import java.util.List;
+
+/**
+ * Handles the rules of playing in a dungeon.
+ *
+ * Tracks the progress of groups in a dungeon and handles their interaction with each other.
+ *
+ * @author Daniel Saukel
+ */
+// Implementation-specific methods: wave and kill counter methods
+public interface Game {
+
+ /**
+ * Returns if this is a tutorial game.
+ *
+ * @return if this is a tutorial game
+ */
+ boolean isTutorial();
+
+ /**
+ * Sets if this is a tutorial game
+ *
+ * @param tutorial if this is a tutorial game
+ */
+ void setTutorial(boolean tutorial);
+
+ /**
+ * Returns a read-only List of the groups that are playing this game.
+ *
+ * @return a read-only List of the groups that are playing this game
+ */
+ List getGroups();
+
+ /**
+ * Adds the given group to this game.
+ *
+ * @param group the group
+ */
+ void addGroup(PlayerGroup group);
+
+ /**
+ * Removes the given group from this game.
+ *
+ * @param group the group
+ */
+ void removeGroup(PlayerGroup group);
+
+ /**
+ * Returns if the group has started (=if the ready sign has been triggered).
+ *
+ * @return if the group has started
+ */
+ boolean hasStarted();
+
+ /**
+ * Sets the status of the game to have started / not yet started.
+ *
+ * @param started if the game has started
+ */
+ void setStarted(boolean started);
+
+ /**
+ * Returns the game instance in which this game takes place.
+ *
+ * @return the game instance in which this game takes place
+ */
+ GameWorld getWorld();
+
+ /**
+ * Sets the game instance in which this game takes place.
+ *
+ * @param gameWorld the game instance in which this game takes place
+ */
+ void setWorld(GameWorld gameWorld);
+
+ /**
+ * Returns the rules of the dungeon of this game.
+ *
+ * This is not necessarily represented 1:1 by a config file because it is usually merged together through {@link Dungeon#setupRules()}.
+ *
+ * @return the rules of the dungeon of this game
+ */
+ default GameRuleContainer getRules() {
+ return getDungeon().getRules();
+ }
+
+ /**
+ * Returns a read-only List of the remaining floors to play.
+ *
+ * @return a read-only List of the remaining floors to play
+ */
+ List getUnplayedFloors();
+
+ /**
+ * Returns the amount of played floors in this game.
+ *
+ * @return the amount of played floors in this game
+ */
+ int getFloorCount();
+
+ /**
+ * Returns the dungeon that "hosts" this game.
+ *
+ * @return the dungeon that "hosts" this game
+ */
+ Dungeon getDungeon();
+
+ /**
+ * Returns the players playing the game.
+ *
+ * @return the players playing the game
+ */
+ PlayerCollection getPlayers();
+
+ /**
+ * Returns true if there are no groups in this game; false if not.
+ *
+ * @return true if there are no groups in this game; false if not
+ */
+ boolean isEmpty();
+
+ /**
+ * Deletes this game.
+ */
+ void delete();
+
+ /**
+ * Returns true if all groups of the game have finished it; false if not.
+ *
+ * @return true if all groups of the game have finished it; false if not
+ */
+ default boolean isFinished() {
+ return getGroups().stream().allMatch(PlayerGroup::isFinished);
+ }
+
+ /**
+ * Sends a message to each player in each group.
+ *
+ * @param message the message. Supports color codes
+ */
+ default void sendMessage(String message) {
+ getGroups().forEach(g -> g.sendMessage(message));
+ }
+
+}
diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameGoal.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameGoal.java
new file mode 100644
index 00000000..5b7102dd
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameGoal.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api.dungeon;
+
+/**
+ * A game goal defines what the players have to do in order to finish the game.
+ *
+ * @author Daniel Saukel
+ */
+public enum GameGoal {
+
+ /**
+ * The default goal. The game ends when the end is reached.
+ */
+ END,
+ /**
+ * The game does not end. Instead, the goal is to survive as long as possible to beat a highscore.
+ */
+ HIGHSCORE,
+ /**
+ * The game ends when a player dies and only one group is left.
+ */
+ LAST_MAN_STANDING,
+ /**
+ * The game ends when a group reachs a specific score.
+ */
+ REACH_SCORE,
+ /**
+ * The game ends after a specific time. The goal is to get the highest score until then.
+ */
+ TIME_SCORE,
+ /**
+ * The game ends after a specific time. The goal is to survive until then.
+ */
+ TIME_SURVIVAL;
+
+}
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
new file mode 100644
index 00000000..4db55881
--- /dev/null
+++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2014-2020 Daniel Saukel
+ *
+ * This library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNULesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package de.erethon.dungeonsxl.api.dungeon;
+
+import de.erethon.caliburn.CaliburnAPI;
+import de.erethon.caliburn.item.ExItem;
+import de.erethon.caliburn.mob.ExMob;
+import de.erethon.caliburn.mob.VanillaMob;
+import de.erethon.commons.misc.EnumUtil;
+import de.erethon.dungeonsxl.api.DungeonsAPI;
+import de.erethon.dungeonsxl.api.Requirement;
+import de.erethon.dungeonsxl.api.Reward;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.bukkit.GameMode;
+import org.bukkit.configuration.ConfigurationSection;
+
+/**
+ * Represents a game rule for a {@link Game}.
+ *
+ * @param the type of the game rule value
+ * @author Daniel Saukel
+ */
+// TODO: These values aren't properly fetched from config yet: values that involve Caliburn, requirements & rewards; maybe messages.
+// Check special merging rules for damageProtectedEntities and interactionProtectedEntities.
+public class GameRule {
+
+ /**
+ * Shall players play the dungeon with their own items or do you want to use classes?
+ */
+ public static final GameRule KEEP_INVENTORY_ON_ENTER = new GameRule<>(Boolean.class, "keepInventoryOnEnter", false);
+ /**
+ * Shall players keep their inventory when they leave the dungeon without succeeding?
+ */
+ public static final GameRule KEEP_INVENTORY_ON_ESCAPE = new GameRule<>(Boolean.class, "keepInventoryOnEscape", false);
+ /**
+ * Shall players keep their inventory when they finish the dungeon?
+ */
+ public static final GameRule KEEP_INVENTORY_ON_FINISH = new GameRule<>(Boolean.class, "keepInventoryOnFinish", false);
+ /**
+ * Shall players lose their items when they die (do not mix up this with "onEscape"!)?
+ */
+ public static final GameRule KEEP_INVENTORY_ON_DEATH = new GameRule<>(Boolean.class, "keepInventoryOnDeath", true);
+ /**
+ * If the Lobby is disabled. This applies only to Dungeons that have to be solved alone and where there are no classes to choose from.
+ */
+ public static final GameRule IS_LOBBY_DISABLED = new GameRule<>(Boolean.class, "isLobbyDisabled", false);
+ /**
+ * The game mode.
+ */
+ public static final GameRule GAME_MODE = new GameRule<>(GameMode.class, "gameMode", GameMode.SURVIVAL);
+ /**
+ * If players may fly.
+ */
+ public static final GameRule FLY = new GameRule<>(Boolean.class, "fly", false);
+ /**
+ * 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