diff --git a/api/pom.xml b/api/pom.xml index f1ee3a0f..91c9c8d4 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -64,7 +64,7 @@ de.erethon.commons commons-dist - 6.2.5 + 6.3 compile 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 4d4f15c0..9fe894aa 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 @@ -184,14 +184,6 @@ public class GameRule { * Maximum time in hours since the dungeons specified by other rules were finished. 0 = ignore. */ public static final GameRule TIME_LAST_PLAYED_REQUIRED_DUNGEONS = new GameRule<>(Integer.class, "timeLastPlayedRequiredDungeons", 0); - /** - * Time in hours when the game may be played again after it has been started. - */ - public static final GameRule TIME_TO_NEXT_PLAY_AFTER_START = new GameRule<>(Integer.class, "timeToNextPlayAfterStart", 0); - /** - * When the game may be played again after it has been finished. - */ - public static final GameRule TIME_TO_NEXT_PLAY_AFTER_FINISH = new GameRule<>(Integer.class, "timeToNextPlayAfterFinish", 0); /** * When loot may be taken away out of the dungeon again. */ diff --git a/core/src/main/java/de/erethon/dungeonsxl/DXLModule.java b/core/src/main/java/de/erethon/dungeonsxl/DXLModule.java index 9e54c59e..550a347f 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/DXLModule.java +++ b/core/src/main/java/de/erethon/dungeonsxl/DXLModule.java @@ -42,6 +42,8 @@ public class DXLModule implements DungeonModule { requirementRegistry.add("groupSize", GroupSizeRequirement.class); requirementRegistry.add("keyItems", KeyItemsRequirement.class); requirementRegistry.add("permission", PermissionRequirement.class); + requirementRegistry.add("timeSinceFinish", TimeSinceFinishRequirement.class); + requirementRegistry.add("timeSinceStart", TimeSinceStartRequirement.class); requirementRegistry.add("timeframe", TimeframeRequirement.class); } diff --git a/core/src/main/java/de/erethon/dungeonsxl/config/DMessage.java b/core/src/main/java/de/erethon/dungeonsxl/config/DMessage.java index 9adb7506..c01a5afa 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/config/DMessage.java +++ b/core/src/main/java/de/erethon/dungeonsxl/config/DMessage.java @@ -108,7 +108,6 @@ public enum DMessage implements Message { ERROR_BED("error.bed"), ERROR_CHEST_IS_OPENED("error.chestIsOpened"), ERROR_CMD("error.cmd"), - ERROR_COOLDOWN("error.cooldown"), ERROR_DISPENSER("error.dispenser"), ERROR_DROP("error.drop"), ERROR_ENDERCHEST("error.enderchest"), @@ -218,6 +217,9 @@ public enum DMessage implements Message { REQUIREMENT_GROUP_SIZE("requirement.groupSize"), REQUIREMENT_KEY_ITEMS("requirement.keyItems"), REQUIREMENT_PERMISSION("requirement.permission"), + REQUIREMENT_TIME_SINCE_NEVER("requirement.timeSince.never"), + REQUIREMENT_TIME_SINCE_FINISH("requirement.timeSince.finish"), + REQUIREMENT_TIME_SINCE_START("requirement.timeSince.start"), REQUIREMENT_TIMEFRAME("requirement.timeframe"), REWARD_GENERAL("reward.general"), SIGN_END("sign.end"), diff --git a/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java b/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java index af91d5c1..e1e6300f 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java +++ b/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java @@ -267,22 +267,6 @@ public class DGlobalPlayer implements GlobalPlayer { boolean fulfilled = true; GameRuleContainer rules = dungeon.getRules(); - if (!checkTimeAfterStart(dungeon) && !checkTimeAfterFinish(dungeon)) { - int longestTime = rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_START) >= rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_FINISH) - ? rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_START) : rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_FINISH); - MessageUtil.sendMessage(player, DMessage.ERROR_COOLDOWN.getMessage(String.valueOf(longestTime))); - fulfilled = false; - - } else if (!checkTimeAfterStart(dungeon)) { - MessageUtil.sendMessage(player, DMessage.ERROR_COOLDOWN.getMessage(String.valueOf(rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_START)))); - fulfilled = false; - - } else if (!checkTimeAfterFinish(dungeon)) { - MessageUtil.sendMessage(player, DMessage.ERROR_COOLDOWN.getMessage(String.valueOf(rules.getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_FINISH)))); - fulfilled = false; - } - - boolean genericReqs = true; List msgs = new ArrayList<>(rules.getState(GameRule.REQUIREMENTS).size()); for (Requirement requirement : rules.getState(GameRule.REQUIREMENTS)) { if (requirement == null) { @@ -298,10 +282,9 @@ public class DGlobalPlayer implements GlobalPlayer { msgs.add(event.getCheckMessage()); if (!requirement.check(player)) { fulfilled = false; - genericReqs = false; } } - if (!genericReqs) { + if (!fulfilled) { MessageUtil.sendMessage(player, DMessage.ERROR_REQUIREMENTS.getMessage()); msgs.forEach(msg -> MessageUtil.sendMessage(player, msg)); } @@ -363,24 +346,6 @@ public class DGlobalPlayer implements GlobalPlayer { return fulfilled || DPermission.hasPermission(player, DPermission.IGNORE_REQUIREMENTS); } - public boolean checkTimeAfterStart(Dungeon dungeon) { - return checkTime(dungeon, dungeon.getRules().getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_START), - getData().getTimeLastStarted(dungeon.getName())); - } - - public boolean checkTimeAfterFinish(Dungeon dungeon) { - return checkTime(dungeon, dungeon.getRules().getState(GameRule.TIME_TO_NEXT_PLAY_AFTER_FINISH), - getData().getTimeLastFinished(dungeon.getName())); - } - - public boolean checkTime(Dungeon dungeon, int requirement, long dataTime) { - if (DPermission.hasPermission(player, DPermission.IGNORE_TIME_LIMIT)) { - return true; - } - - return dataTime == -1 || dataTime + requirement * 1000 * 60 * 60 <= System.currentTimeMillis(); - } - public void giveLoot(Dungeon dungeon, List rewards) { if (!canLoot(dungeon)) { return; diff --git a/core/src/main/java/de/erethon/dungeonsxl/player/DGroup.java b/core/src/main/java/de/erethon/dungeonsxl/player/DGroup.java index 547ce441..a9d30c5c 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/player/DGroup.java +++ b/core/src/main/java/de/erethon/dungeonsxl/player/DGroup.java @@ -605,21 +605,6 @@ public class DGroup implements PlayerGroup { } } - // This is not used. - public boolean checkTime() { - if (DPermission.hasPermission(getLeader(), DPermission.IGNORE_TIME_LIMIT)) { - return true; - } - - for (DGamePlayer dPlayer : getDGamePlayers()) { - if (!dPlayer.checkTimeAfterStart(dungeon) || !dPlayer.checkTimeAfterFinish(dungeon)) { - return false; - } - } - - return true; - } - // This is not used. public boolean checkRequirements() { if (DPermission.hasPermission(getLeader(), DPermission.IGNORE_REQUIREMENTS)) { diff --git a/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceFinishRequirement.java b/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceFinishRequirement.java new file mode 100644 index 00000000..b50c3926 --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceFinishRequirement.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012-2021 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.requirement; + +import de.erethon.dungeonsxl.api.DungeonsAPI; +import de.erethon.dungeonsxl.api.Requirement; +import de.erethon.dungeonsxl.config.DMessage; +import de.erethon.dungeonsxl.player.DGlobalPlayer; +import de.erethon.dungeonsxl.player.DPermission; +import de.erethon.dungeonsxl.util.commons.misc.SimpleDateUtil; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +/** + * Time in hours when the game may be played again since it has been started the last time. + * + * @author Daniel Saukel + */ +public class TimeSinceFinishRequirement implements Requirement { + + private static final long MILLIS_TO_HOURS = 3600000L; + + private DungeonsAPI api; + + private double time; + + public TimeSinceFinishRequirement(DungeonsAPI api) { + this.api = api; + } + + @Override + public void setup(ConfigurationSection config) { + time = config.getDouble("timeSinceFinish", 0.0); + } + + @Override + public boolean check(Player player) { + if (DPermission.hasPermission(player, DPermission.IGNORE_TIME_LIMIT)) { + return true; + } + DGlobalPlayer globalPlayer = (DGlobalPlayer) api.getPlayerCache().get(player); + return (globalPlayer.getData().getTimeLastFinished(globalPlayer.getGroup().getDungeon().getName()) + + time * MILLIS_TO_HOURS) < System.currentTimeMillis(); + } + + @Override + public BaseComponent[] getCheckMessage(Player player) { + int hours = (int) time; + int minutes = (int) Math.round((time - hours) * 60); + String timeFormatted = hours + ":" + (minutes < 10 ? 0 : "") + minutes; + ComponentBuilder builder = new ComponentBuilder(DMessage.REQUIREMENT_TIME_SINCE_FINISH + .getMessage(timeFormatted) + ": ").color(ChatColor.GOLD); + + DGlobalPlayer globalPlayer = (DGlobalPlayer) api.getPlayerCache().get(player); + String dungeonName = globalPlayer.getGroup().getDungeon().getName(); + long lastTime = globalPlayer.getData().getTimeLastFinished(dungeonName); + if (lastTime == -1) { + builder.append(DMessage.REQUIREMENT_TIME_SINCE_NEVER.getMessage()).color(ChatColor.GREEN); + } else { + ChatColor color = lastTime + time * MILLIS_TO_HOURS < System.currentTimeMillis() ? ChatColor.GREEN : ChatColor.DARK_RED; + builder.append(SimpleDateUtil.ddMMMMyyyyhhmmss(lastTime)).color(color); + } + + return builder.create(); + } + + @Override + public void demand(Player player) { + } + +} diff --git a/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceStartRequirement.java b/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceStartRequirement.java new file mode 100644 index 00000000..9a6ba121 --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/requirement/TimeSinceStartRequirement.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012-2021 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.requirement; + +import de.erethon.dungeonsxl.api.DungeonsAPI; +import de.erethon.dungeonsxl.api.Requirement; +import de.erethon.dungeonsxl.config.DMessage; +import de.erethon.dungeonsxl.player.DGlobalPlayer; +import de.erethon.dungeonsxl.player.DPermission; +import de.erethon.dungeonsxl.util.commons.misc.SimpleDateUtil; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +/** + * Time in hours when the game may be played again since it has been started the last time. + * + * @author Daniel Saukel + */ +public class TimeSinceStartRequirement implements Requirement { + + private static final long MILLIS_TO_HOURS = 3600000L; + + private DungeonsAPI api; + + private double time; + + public TimeSinceStartRequirement(DungeonsAPI api) { + this.api = api; + } + + @Override + public void setup(ConfigurationSection config) { + time = config.getDouble("timeSinceStart", 0.0); + } + + @Override + public boolean check(Player player) { + if (DPermission.hasPermission(player, DPermission.IGNORE_TIME_LIMIT)) { + return true; + } + DGlobalPlayer globalPlayer = (DGlobalPlayer) api.getPlayerCache().get(player); + return (globalPlayer.getData().getTimeLastStarted(globalPlayer.getGroup().getDungeon().getName()) + + time * MILLIS_TO_HOURS) < System.currentTimeMillis(); + } + + @Override + public BaseComponent[] getCheckMessage(Player player) { + int hours = (int) time; + int minutes = (int) Math.round((time - hours) * 60); + String timeFormatted = hours + ":" + (minutes < 10 ? 0 : "") + minutes; + ComponentBuilder builder = new ComponentBuilder(DMessage.REQUIREMENT_TIME_SINCE_START + .getMessage(timeFormatted) + ": ").color(ChatColor.GOLD); + + DGlobalPlayer globalPlayer = (DGlobalPlayer) api.getPlayerCache().get(player); + String dungeonName = globalPlayer.getGroup().getDungeon().getName(); + long lastTime = globalPlayer.getData().getTimeLastStarted(dungeonName); + if (lastTime == -1) { + builder.append(DMessage.REQUIREMENT_TIME_SINCE_NEVER.getMessage()).color(ChatColor.GREEN); + } else { + ChatColor color = lastTime + time * MILLIS_TO_HOURS < System.currentTimeMillis() ? ChatColor.GREEN : ChatColor.DARK_RED; + builder.append(SimpleDateUtil.ddMMMMyyyyhhmmss(lastTime)).color(color); + } + + return builder.create(); + } + + @Override + public void demand(Player player) { + } + +} diff --git a/core/src/main/resources/languages/english.yml b/core/src/main/resources/languages/english.yml index 6d699a10..961bd124 100644 --- a/core/src/main/resources/languages/english.yml +++ b/core/src/main/resources/languages/english.yml @@ -124,7 +124,6 @@ error: blockOwnTeam: "&4This block belongs to your own group." chestIsOpened: "&4This chest has already been opened." cmd: "&4Commands are not allowed while in a dungeon." - cooldown: "&4You can only enter this dungeon every &6&v1&4 hours." dispenser: "&4You cannot access this dispenser." drop: "&4You cannot drop safe items" enderchest: "&4You cannot use an enderchest while in a dungeon." @@ -234,6 +233,10 @@ requirement: groupSize: "Group size" keyItems: "Keys" permission: "Permissions" + timeSince: + finish: "Enough passed time since last playthrough (&v1 hours)" + start: "Enough passed time since last try (&v1 hours)" + never: "No playthroughs so far." timeframe: "Timeframe" reward: general: "&6You received &4&v1 &6for finishing the dungeon." diff --git a/core/src/main/resources/languages/french.yml b/core/src/main/resources/languages/french.yml index a1f990e3..3734868d 100644 --- a/core/src/main/resources/languages/french.yml +++ b/core/src/main/resources/languages/french.yml @@ -124,7 +124,6 @@ error: blockOwnTeam: "&4Ce bloque appartient à votre groupe." chestIsOpened: "&4Ce coffre a déjà été ouvert." cmd: "&4Les commandes ne sont pas autorisées pendant un donjon." - cooldown: "&4Vous ne pouvez entrer dans ce donjon que toutes les &6&v1&4 heures." dispenser: "&4Vous ne pouvez accéder à ce distributeur." drop: "&4Vous ne pouvez pas lâcher cet objet protégé." enderchest: "&4Vous ne pouvez utiliser un coffre de l'ender quand vous êtes dans un donjon." @@ -234,6 +233,10 @@ requirement: groupSize: "Quantité des joueurs" keyItems: "Clés" permission: "Permissions" + timeSince: + finish: "Assez de temps passé depuis le dernier jeu terminé (&v1 heures)" + start: "Assez de temps passé depuis le dernier jeu commencé (&v1 heures)" + never: "Pas de jeux." timeframe: "Créneau horaire" reward: general: "&6Vous avez reçu &4&v1 &6pour avoir fini le donjon." diff --git a/core/src/main/resources/languages/german.yml b/core/src/main/resources/languages/german.yml index 34e3c2df..1e0567bc 100644 --- a/core/src/main/resources/languages/german.yml +++ b/core/src/main/resources/languages/german.yml @@ -124,7 +124,6 @@ error: blockOwnTeam: "&4Dieser Block gehört zu Deiner eigenen Gruppe." chestIsOpened: "&4Diese Truhe wurde schon geöffnet." cmd: "&4Befehle sind im Dungeon nicht erlaubt." - cooldown: "&4Du kannst diesen Dungeon nur alle &6&v1&4 Stunden betreten." dispenser: "&4Du kannst auf diesen Werfer nicht zugreifen." drop: "&4Du kannst keine gesicherten Items wegwerfen." enderchest: "&4Du kannst im Dungeon keine Endertruhen benutzen." @@ -234,6 +233,10 @@ requirement: groupSize: "Gruppengröße" keyItems: "Schlüssel" permission: "Permissions" + timeSince: + finish: "Ausreichend vergangene Zeit seit dem letzten abgeschlossenen Spiel (&v1 Stunden)" + start: "Ausreichend vergangene Zeit seit dem letzten Versuch (&v1 Stunden)" + never: "Bisher keine Versuche." timeframe: "Zeitfenster" reward: general: "&6Du hast &4&v1 &6für das Beenden des Dungeons erhalten."