From a4857f7a4e457ff4c7c7e8da8410129efd4aabcf Mon Sep 17 00:00:00 2001
From: Krakenied
Date: Tue, 13 May 2025 19:30:31 +0200
Subject: API cleanup & ensure compatibility
---
.../quests/common/config/ConfigProblem.java | 52 ++++--
.../quests/common/player/QPlayer.java | 167 ++++++++++-------
.../quests/common/player/QPlayerData.java | 15 +-
.../quests/common/player/QPlayerManager.java | 40 +++--
.../player/questprogressfile/QuestProgress.java | 131 +++++++-------
.../questprogressfile/QuestProgressFile.java | 74 ++++----
.../player/questprogressfile/TaskProgress.java | 59 +++---
.../quests/common/plugin/Quests.java | 37 ++--
.../quests/common/quest/Category.java | 99 ++++++++---
.../leonardobishop/quests/common/quest/Quest.java | 7 +
.../quests/common/quest/QuestManager.java | 89 +++++++---
.../leonardobishop/quests/common/quest/Task.java | 66 ++++---
.../common/questcontroller/QuestController.java | 20 ++-
.../quests/common/tasktype/TaskType.java | 197 +++++++++++----------
.../quests/common/tasktype/TaskTypeManager.java | 170 ++++++++++--------
.../leonardobishop/quests/common/util/Modern.java | 21 +++
16 files changed, 734 insertions(+), 510 deletions(-)
create mode 100644 common/src/main/java/com/leonardobishop/quests/common/util/Modern.java
(limited to 'common/src/main')
diff --git a/common/src/main/java/com/leonardobishop/quests/common/config/ConfigProblem.java b/common/src/main/java/com/leonardobishop/quests/common/config/ConfigProblem.java
index f9e9de33..88c6d274 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/config/ConfigProblem.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/config/ConfigProblem.java
@@ -1,41 +1,53 @@
package com.leonardobishop.quests.common.config;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+import java.util.Objects;
+
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public final class ConfigProblem {
private final ConfigProblemType type;
private final String description;
- private final String extendedDescription;
+ private final @Nullable String extendedDescription;
private final String location;
- public ConfigProblem(ConfigProblemType type, String description, String extendedDescription, String location) {
- this.type = type;
- this.description = description == null ? "?" : description;
+ public ConfigProblem(final ConfigProblemType type, final @Nullable String description, final @Nullable String extendedDescription, final @Nullable String location) {
+ this.type = Objects.requireNonNull(type, "type cannot be null");
+ this.description = Objects.requireNonNullElse(description, "?");
this.extendedDescription = extendedDescription;
- this.location = location == null ? "?" : location;
+ this.location = Objects.requireNonNullElse(location, "?");
}
- public ConfigProblem(ConfigProblemType type, String description, String extendedDescription) {
+ public ConfigProblem(final ConfigProblemType type, final @Nullable String description, final @Nullable String extendedDescription) {
this(type, description, extendedDescription, null);
}
+ @Contract(pure = true)
public ConfigProblemType getType() {
- return type;
+ return this.type;
}
+ @Contract(pure = true)
public String getDescription() {
- return description;
+ return this.description;
}
- public String getExtendedDescription() {
- return extendedDescription;
+ @Contract(pure = true)
+ public @Nullable String getExtendedDescription() {
+ return this.extendedDescription;
}
+ @Contract(pure = true)
public String getLocation() {
- return location;
+ return this.location;
}
public enum ConfigProblemType {
-
ERROR("Error", "E", 1, "An error prevents a quest from being loaded"),
WARNING("Warning", "W", 2, "A warning indicates a quest may not work as expected");
@@ -44,27 +56,31 @@ public final class ConfigProblem {
private final int priority;
private final String description;
- ConfigProblemType(String title, String shortened, int priority, String description) {
+ ConfigProblemType(final String title, final String shortened, final int priority, final String description) {
this.title = title;
this.shortened = shortened;
this.priority = priority;
this.description = description;
}
+ @Contract(pure = true)
public String getTitle() {
- return title;
+ return this.title;
}
+ @Contract(pure = true)
public String getShortened() {
- return shortened;
+ return this.shortened;
}
+ @Contract(pure = true)
public int getPriority() {
- return priority;
+ return this.priority;
}
+ @Contract(pure = true)
public String getDescription() {
- return description;
+ return this.description;
}
}
-}
\ No newline at end of file
+}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayer.java b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayer.java
index bcfafdd0..e7d45981 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayer.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayer.java
@@ -5,8 +5,9 @@ import com.leonardobishop.quests.common.player.questprogressfile.QuestProgressFi
import com.leonardobishop.quests.common.plugin.Quests;
import com.leonardobishop.quests.common.quest.Quest;
import com.leonardobishop.quests.common.questcontroller.QuestController;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Contract;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -18,13 +19,14 @@ import java.util.UUID;
/**
* Represents a player.
*/
+@NullMarked
public final class QPlayer {
private final Quests plugin;
private final QPlayerData playerData;
private QuestController questController;
- public QPlayer(final @NotNull Quests plugin, final @NotNull QPlayerData playerData, final @NotNull QuestController questController) {
+ public QPlayer(final Quests plugin, final QPlayerData playerData, final QuestController questController) {
this.plugin = plugin;
this.playerData = playerData;
this.questController = questController;
@@ -35,7 +37,8 @@ public final class QPlayer {
*
* @return the players data
*/
- public @NotNull QPlayerData getPlayerData() {
+ @Contract(pure = true)
+ public QPlayerData getPlayerData() {
return this.playerData;
}
@@ -44,7 +47,8 @@ public final class QPlayer {
*
* @return uuid
*/
- public @NotNull UUID getPlayerUUID() {
+ @Contract(pure = true)
+ public UUID getPlayerUUID() {
return this.playerData.playerUUID();
}
@@ -53,7 +57,8 @@ public final class QPlayer {
*
* @return the players preferences
*/
- public @NotNull QPlayerPreferences getPlayerPreferences() {
+ @Contract(pure = true)
+ public QPlayerPreferences getPlayerPreferences() {
return this.playerData.playerPreferences();
}
@@ -62,10 +67,52 @@ public final class QPlayer {
*
* @return the quest progress file
*/
- public @NotNull QuestProgressFile getQuestProgressFile() {
+ @Contract(pure = true)
+ public QuestProgressFile getQuestProgressFile() {
return this.playerData.questProgressFile();
}
+ /**
+ * Check if the player can start a quest.
+ * Warning: will fail if the player is not online.
+ *
+ * @param quest the quest to check
+ * @return the quest start result
+ */
+ @Contract(pure = true)
+ public QuestStartResult canStartQuest(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ return this.questController.canPlayerStartQuest(this, quest);
+ }
+
+ /**
+ * Gets whether the player has started a specific quest.
+ *
+ * @param quest the quest to test for
+ * @return true if the quest is started or quest autostart is enabled and the quest is ready to start, false otherwise
+ */
+ @Contract(pure = true)
+ public boolean hasStartedQuest(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ return this.questController.hasPlayerStartedQuest(this, quest);
+ }
+
+ /**
+ * Attempt to start a quest for the player. This will also play all effects (such as titles, messages etc.)
+ * Warning: will fail if the player is not online.
+ *
+ * @param quest the quest to start
+ * @return the quest start result -- {@code QuestStartResult.QUEST_SUCCESS} indicates success
+ */
+ // TODO PlaceholderAPI support
+ public QuestStartResult startQuest(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ return this.questController.startQuestForPlayer(this, quest);
+ }
+
/**
* Attempt to complete a quest for the player. This will also play all effects (such as titles, messages etc.)
* and also dispatches all rewards for the player.
@@ -73,32 +120,43 @@ public final class QPlayer {
* @param quest the quest to complete
* @return true (always)
*/
- @SuppressWarnings("UnusedReturnValue")
- public boolean completeQuest(final @NotNull Quest quest) {
+ public boolean completeQuest(final Quest quest) {
Objects.requireNonNull(quest, "quest cannot be null");
return this.questController.completeQuestForPlayer(this, quest);
}
/**
- * Attempt to track a quest for the player. This will also play all effects (such as titles, messages etc.)
+ * Attempt to cancel a quest for the player. This will also play all effects (such as titles, messages etc.)
*
- * @param quest the quest to track
+ * @param quest the quest to start
+ * @return true if the quest was cancelled, false otherwise
*/
- public void trackQuest(final @Nullable Quest quest) {
- this.questController.trackQuestForPlayer(this, quest);
+ public boolean cancelQuest(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ return this.questController.cancelQuestForPlayer(this, quest);
}
/**
- * Gets whether the player has started a specific quest.
+ * Attempt to expire a quest for the player. This will also play all effects (such as titles, messages etc.)
*
- * @param quest the quest to test for
- * @return true if the quest is started or quest autostart is enabled and the quest is ready to start, false otherwise
+ * @param quest the quest to start
+ * @return true if the quest was expired, false otherwise
*/
- public boolean hasStartedQuest(final @NotNull Quest quest) {
+ public boolean expireQuest(final Quest quest) {
Objects.requireNonNull(quest, "quest cannot be null");
- return this.questController.hasPlayerStartedQuest(this, quest);
+ return this.questController.expireQuestForPlayer(this, quest);
+ }
+
+ /**
+ * Attempt to track a quest for the player. This will also play all effects (such as titles, messages etc.)
+ *
+ * @param quest the quest to track
+ */
+ public void trackQuest(final @Nullable Quest quest) {
+ this.questController.trackQuestForPlayer(this, quest);
}
/**
@@ -106,7 +164,8 @@ public final class QPlayer {
*
* @return list of effectively started quests
*/
- public @NotNull List getEffectiveStartedQuests() {
+ @Contract(pure = true)
+ public List getEffectiveStartedQuests() {
return this.getEffectiveStartedQuests(-1);
}
@@ -117,9 +176,10 @@ public final class QPlayer {
* @param limit the maximum number of quests to return. A value of -1 indicates no limit.
* @return list of effectively started quests, up to the specified limit
*/
- public @NotNull List getEffectiveStartedQuests(final int limit) {
+ @Contract(pure = true)
+ public List getEffectiveStartedQuests(final int limit) {
final Collection quests = this.plugin.getQuestManager()
- .getQuests()
+ .getQuestMap()
.values();
final List ret;
@@ -152,64 +212,35 @@ public final class QPlayer {
}
/**
- * Attempt to start a quest for the player. This will also play all effects (such as titles, messages etc.)
- * Warning: will fail if the player is not online.
- *
- * @param quest the quest to start
- * @return the quest start result -- {@code QuestStartResult.QUEST_SUCCESS} indicates success
- */
- // TODO PlaceholderAPI support
- public @NotNull QuestStartResult startQuest(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
-
- return this.questController.startQuestForPlayer(this, quest);
- }
-
- /**
- * Attempt to cancel a quest for the player. This will also play all effects (such as titles, messages etc.)
+ * Gets count of quests which the player has effectively started. This includes quests started automatically.
*
- * @param quest the quest to start
- * @return true if the quest was cancelled, false otherwise
+ * @return count of effectively started quests
*/
- public boolean cancelQuest(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
-
- return this.questController.cancelQuestForPlayer(this, quest);
- }
+ @Contract(pure = true)
+ public int getEffectiveStartedQuestsCount() {
+ int count = 0;
- /**
- * Attempt to expire a quest for the player. This will also play all effects (such as titles, messages etc.)
- *
- * @param quest the quest to start
- * @return true if the quest was expired, false otherwise
- */
- @SuppressWarnings("UnusedReturnValue")
- public boolean expireQuest(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
-
- return this.questController.expireQuestForPlayer(this, quest);
- }
+ final Collection quests = this.plugin.getQuestManager()
+ .getQuestMap()
+ .values();
- /**
- * Check if the player can start a quest.
- * Warning: will fail if the player is not online.
- *
- * @param quest the quest to check
- * @return the quest start result
- */
- public @NotNull QuestStartResult canStartQuest(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
+ for (final Quest quest : quests) {
+ if (this.questController.hasPlayerStartedQuest(this, quest)) {
+ count++;
+ }
+ }
- return this.questController.canPlayerStartQuest(this, quest);
+ return count;
}
/**
* Get player's associated {@link QuestController}. It's usually the server's active quest controller.
*
- * @see QPlayerManager#getActiveQuestController()
* @return the quest controller for this player
+ * @see QPlayerManager#getActiveQuestController()
*/
- public @NotNull QuestController getQuestController() {
+ @Contract(pure = true)
+ public QuestController getQuestController() {
return this.questController;
}
@@ -218,7 +249,7 @@ public final class QPlayer {
*
* @param questController new quest controller
*/
- public void setQuestController(final @NotNull QuestController questController) {
+ public void setQuestController(final QuestController questController) {
Objects.requireNonNull(questController, "questController cannot be null");
this.questController = questController;
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerData.java b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerData.java
index cdabd385..2209bcba 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerData.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerData.java
@@ -1,24 +1,27 @@
package com.leonardobishop.quests.common.player;
import com.leonardobishop.quests.common.player.questprogressfile.QuestProgressFile;
-import org.jetbrains.annotations.NotNull;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jspecify.annotations.NullMarked;
import java.util.Objects;
import java.util.UUID;
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public final class QPlayerData {
private final UUID playerUUID;
private final QPlayerPreferences playerPreferences;
private final QuestProgressFile questProgressFile;
- public QPlayerData(final @NotNull UUID playerUUID, final @NotNull QPlayerPreferences playerPreferences, final @NotNull QuestProgressFile questProgressFile) {
+ public QPlayerData(final UUID playerUUID, final QPlayerPreferences playerPreferences, final QuestProgressFile questProgressFile) {
this.playerUUID = Objects.requireNonNull(playerUUID, "playerUUID cannot be null");
this.playerPreferences = Objects.requireNonNull(playerPreferences, "playerPreferences cannot be null");
this.questProgressFile = Objects.requireNonNull(questProgressFile, "questProgressFile cannot be null");
}
- public QPlayerData(final @NotNull QPlayerData playerData) {
+ public QPlayerData(final QPlayerData playerData) {
Objects.requireNonNull(playerData, "playerData cannot be null");
this.playerUUID = playerData.playerUUID;
@@ -26,15 +29,15 @@ public final class QPlayerData {
this.questProgressFile = new QuestProgressFile(playerData.questProgressFile);
}
- public @NotNull UUID playerUUID() {
+ public UUID playerUUID() {
return this.playerUUID;
}
- public @NotNull QPlayerPreferences playerPreferences() {
+ public QPlayerPreferences playerPreferences() {
return this.playerPreferences;
}
- public @NotNull QuestProgressFile questProgressFile() {
+ public QuestProgressFile questProgressFile() {
return this.questProgressFile;
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
index 4c3704de..52c1985d 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
@@ -4,9 +4,10 @@ import com.leonardobishop.quests.common.player.questprogressfile.QuestProgressFi
import com.leonardobishop.quests.common.plugin.Quests;
import com.leonardobishop.quests.common.questcontroller.QuestController;
import com.leonardobishop.quests.common.storage.StorageProvider;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import com.leonardobishop.quests.common.util.Modern;
import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
@@ -20,6 +21,8 @@ import java.util.concurrent.ConcurrentHashMap;
* The QPlayerManager is responsible for keeping a reference to all players on the server and is used to
* obtain an instance of a player, load new players and save current players.
*/
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public final class QPlayerManager {
private final Quests plugin;
@@ -27,7 +30,7 @@ public final class QPlayerManager {
private final Map qPlayerMap;
private QuestController activeQuestController;
- public QPlayerManager(final @NotNull Quests plugin, final @NotNull StorageProvider storageProvider, final @NotNull QuestController questController) {
+ public QPlayerManager(final Quests plugin, final StorageProvider storageProvider, final QuestController questController) {
this.plugin = Objects.requireNonNull(plugin, "plugin cannot be null");
this.storageProvider = Objects.requireNonNull(storageProvider, "storageProvider cannot be null");
this.activeQuestController = Objects.requireNonNull(questController, "questController cannot be null");
@@ -40,7 +43,7 @@ public final class QPlayerManager {
* @param uuid the uuid
* @return {@link QPlayer} if they are loaded, otherwise null
*/
- public @Nullable QPlayer getPlayer(final @NotNull UUID uuid) {
+ public @Nullable QPlayer getPlayer(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
// QPlayer qPlayer = qPlayers.get(uuid);
@@ -58,7 +61,7 @@ public final class QPlayerManager {
*
* @param uuid the uuid of the player
*/
- public void removePlayer(final @NotNull UUID uuid) {
+ public void removePlayer(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
this.plugin.getQuestsLogger().debug("Unloading and saving player " + uuid + "...");
@@ -73,7 +76,7 @@ public final class QPlayerManager {
* @param uuid the uuid of the player
* @return completable future
*/
- public @NotNull CompletableFuture savePlayer(final @NotNull UUID uuid) {
+ public CompletableFuture<@Nullable Void> savePlayer(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
final QPlayer qPlayer = this.getPlayer(uuid);
@@ -88,10 +91,10 @@ public final class QPlayerManager {
* Schedules a save for the player with a specified {@link QuestProgressFile}. The modified status of the
* specified progress file will be reset.
*/
- public @NotNull CompletableFuture savePlayer(final @NotNull QPlayerData playerData) {
+ public CompletableFuture<@Nullable Void> savePlayer(final QPlayerData playerData) {
Objects.requireNonNull(playerData, "playerData cannot be null");
- final CompletableFuture future = new CompletableFuture<>();
+ final CompletableFuture<@Nullable Void> future = new CompletableFuture<>();
final QPlayerData clonedPlayerData = new QPlayerData(playerData);
playerData.setModified(false);
@@ -109,7 +112,7 @@ public final class QPlayerManager {
*
* @param uuid the uuid of the player
*/
- public void savePlayerSync(final @NotNull UUID uuid) {
+ public void savePlayerSync(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
final QPlayer qPlayer = this.getPlayer(uuid);
@@ -124,11 +127,11 @@ public final class QPlayerManager {
* Immediately saves the player with a specified {@link QuestProgressFile}, on the same thread. The modified status
* of the specified progress file is not changed.
*/
- public void savePlayerSync(final @NotNull QPlayerData playerData) {
+ public void savePlayerSync(final QPlayerData playerData) {
this.save(playerData);
}
- private void save(@NotNull QPlayerData playerData) {
+ private void save(final QPlayerData playerData) {
Objects.requireNonNull(playerData, "playerData cannot be null");
final String uuidString = playerData.playerUUID().toString();
@@ -146,7 +149,7 @@ public final class QPlayerManager {
*
* @param uuid the uuid of the player
*/
- public void dropPlayer(final @NotNull UUID uuid) {
+ public void dropPlayer(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
this.plugin.getQuestsLogger().debug("Dropping player " + uuid + ".");
@@ -158,8 +161,7 @@ public final class QPlayerManager {
*
* @return immutable collection of quest players
*/
- @UnmodifiableView
- public @NotNull Collection getQPlayers() {
+ public @UnmodifiableView Collection getQPlayers() {
return Collections.unmodifiableCollection(this.qPlayerMap.values());
}
@@ -170,12 +172,12 @@ public final class QPlayerManager {
* @param uuid the uuid of the player
* @return completable future with the loaded player, or null if there was an error
*/
- public @NotNull CompletableFuture loadPlayer(final @NotNull UUID uuid) {
+ public CompletableFuture<@Nullable QPlayer> loadPlayer(final UUID uuid) {
Objects.requireNonNull(uuid, "uuid cannot be null");
final String uuidString = uuid.toString();
this.plugin.getQuestsLogger().debug("Loading player " + uuidString + "...");
- final CompletableFuture future = new CompletableFuture<>();
+ final CompletableFuture<@Nullable QPlayer> future = new CompletableFuture<>();
this.plugin.getScheduler().doAsync(() -> {
final QPlayerData playerData = this.storageProvider.loadPlayerData(uuid);
@@ -201,15 +203,15 @@ public final class QPlayerManager {
*
* @return {@link StorageProvider}
*/
- public @NotNull StorageProvider getStorageProvider() {
+ public StorageProvider getStorageProvider() {
return this.storageProvider;
}
- public @NotNull QuestController getActiveQuestController() {
+ public QuestController getActiveQuestController() {
return this.activeQuestController;
}
- public void setActiveQuestController(final @NotNull QuestController activeQuestController) {
+ public void setActiveQuestController(final QuestController activeQuestController) {
this.activeQuestController = Objects.requireNonNull(activeQuestController, "activeQuestController cannot be null");
for (final QPlayer qPlayer : this.qPlayerMap.values()) {
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgress.java b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgress.java
index addc8a76..a6adf4cb 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgress.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgress.java
@@ -1,10 +1,9 @@
package com.leonardobishop.quests.common.player.questprogressfile;
import com.leonardobishop.quests.common.plugin.Quests;
-import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.Collection;
import java.util.HashMap;
@@ -12,6 +11,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
+@NullMarked
public final class QuestProgress {
private final Quests plugin;
@@ -39,7 +39,7 @@ public final class QuestProgress {
* @param completionDate the date of the last quest completion
* @param modified whether the object has been modified and needs to be saved
*/
- public QuestProgress(final @NotNull Quests plugin, final @NotNull String questId, final @NotNull UUID playerUUID, final boolean started, final long startedDate, final boolean completed, final boolean completedBefore, final long completionDate, final boolean modified) {
+ public QuestProgress(final Quests plugin, final String questId, final UUID playerUUID, final boolean started, final long startedDate, final boolean completed, final boolean completedBefore, final long completionDate, final boolean modified) {
this.plugin = plugin;
this.questId = questId;
this.playerUUID = playerUUID;
@@ -64,7 +64,7 @@ public final class QuestProgress {
* @param completedBefore whether the quest has been completed before
* @param completionDate the date of the last quest completion
*/
- public QuestProgress(final @NotNull Quests plugin, final @NotNull String questId, final @NotNull UUID playerUUID, final boolean started, final long startedDate, final boolean completed, final boolean completedBefore, final long completionDate) {
+ public QuestProgress(final Quests plugin, final String questId, final UUID playerUUID, final boolean started, final long startedDate, final boolean completed, final boolean completedBefore, final long completionDate) {
this(plugin, questId, playerUUID, started, startedDate, completed, completedBefore, completionDate, false);
}
@@ -73,14 +73,13 @@ public final class QuestProgress {
*
* @param questProgress the quest progress instance
*/
- @ApiStatus.Internal
- public QuestProgress(final @NotNull QuestProgress questProgress) {
+ public QuestProgress(final QuestProgress questProgress) {
final Set> progressEntries = questProgress.taskProgressMap.entrySet();
this.plugin = questProgress.plugin;
this.questId = questProgress.questId;
this.playerUUID = questProgress.playerUUID;
- this.taskProgressMap = new HashMap<>(progressEntries.size());
+ this.taskProgressMap = HashMap.newHashMap(progressEntries.size());
for (final Map.Entry progressEntry : progressEntries) {
this.taskProgressMap.put(progressEntry.getKey(), new TaskProgress(progressEntry.getValue()));
@@ -98,25 +97,15 @@ public final class QuestProgress {
* @return the associated quest ID
*/
@Contract(pure = true)
- public @NotNull String getQuestId() {
+ public String getQuestId() {
return this.questId;
}
- /**
- * @return the associated player ID
- * @see QuestProgress#getPlayerUUID()
- */
- @Deprecated(forRemoval = true)
- @Contract(pure = true)
- public @NotNull UUID getPlayer() {
- return this.playerUUID;
- }
-
/**
* @return the associated player ID
*/
@Contract(pure = true)
- public @NotNull UUID getPlayerUUID() {
+ public UUID getPlayerUUID() {
return this.playerUUID;
}
@@ -124,26 +113,15 @@ public final class QuestProgress {
* @return mutable task progress map
*/
@Contract(pure = true)
- public @NotNull Map getTaskProgressMap() {
+ public Map getTaskProgressMap() {
return this.taskProgressMap;
}
- /**
- * @return mutable task progress map values collection
- * @see QuestProgress#getAllTaskProgress()
- */
- @Deprecated(forRemoval = true)
- @Contract(pure = true)
- public @NotNull Collection getTaskProgress() {
- return this.taskProgressMap.values();
- }
-
/**
* @return mutable task progress map values collection
*/
- @SuppressWarnings("unused")
@Contract(pure = true)
- public @NotNull Collection getAllTaskProgress() {
+ public Collection getTaskProgresses() {
return this.taskProgressMap.values();
}
@@ -153,7 +131,7 @@ public final class QuestProgress {
* @param taskId the task ID to get the progress for
* @return {@link TaskProgress} or a blank generated one if the task does not exist
*/
- public @NotNull TaskProgress getTaskProgress(final @NotNull String taskId) {
+ public TaskProgress getTaskProgress(final String taskId) {
final TaskProgress taskProgress = this.taskProgressMap.get(taskId);
if (taskProgress != null) {
return taskProgress;
@@ -170,26 +148,15 @@ public final class QuestProgress {
* @param taskId the task ID to get the progress for
* @return {@link TaskProgress} or null if the task does not exist
*/
- @SuppressWarnings("unused")
@Contract(pure = true)
- public @Nullable TaskProgress getTaskProgressOrNull(final @NotNull String taskId) {
+ public @Nullable TaskProgress getTaskProgressOrNull(final String taskId) {
return this.taskProgressMap.get(taskId);
}
- /**
- * @param taskId the task ID to repair the progress for
- */
- @Deprecated(forRemoval = true)
- @ApiStatus.Internal
- public void repairTaskProgress(final @NotNull String taskId) {
- final TaskProgress taskProgress = new TaskProgress(this, taskId, this.playerUUID, null, false, false);
- this.addTaskProgress(taskProgress);
- }
-
/**
* @param taskProgress the task progress to put into the task progress map
*/
- public void addTaskProgress(final @NotNull TaskProgress taskProgress) {
+ public void addTaskProgress(final TaskProgress taskProgress) {
this.taskProgressMap.put(taskProgress.getTaskId(), taskProgress);
}
@@ -210,7 +177,7 @@ public final class QuestProgress {
}
/**
- * @return the date of the last quest start
+ * @return {@code 0} if the quest hasn't been started yet, the date of the last quest start
*/
@Contract(pure = true)
public long getStartedDate() {
@@ -258,7 +225,7 @@ public final class QuestProgress {
}
/**
- * @return the date of the last quest completion
+ * @return {@code 0} if the quest hasn't been completed yet, otherwise the date of the last quest completion
*/
@Contract(pure = true)
public long getCompletionDate() {
@@ -276,7 +243,6 @@ public final class QuestProgress {
/**
* @return whether the object has been modified and needs to be saved
*/
- @SuppressWarnings("unused")
@Contract(pure = true)
public boolean isModified() {
if (this.modified) {
@@ -292,16 +258,6 @@ public final class QuestProgress {
return false;
}
- /**
- * It's equivalent to {@code QuestProgress#setModified(false)}.
- *
- * @see QuestProgress#setModified(boolean)
- */
- @Deprecated(forRemoval = true)
- public void resetModified() {
- this.setModified(false);
- }
-
/**
* @param modified whether the object has been modified and needs to be saved
*/
@@ -322,7 +278,8 @@ public final class QuestProgress {
* - {@link QuestProgress#startedDate}
* - {@link QuestProgress#completed}
* - {@link QuestProgress#completedBefore}
- * - {@link QuestProgress#completionDate}
+ * - {@link QuestProgress#completionDate}
+ * - {@link QuestProgress#taskProgressMap}
*
*
* @return whether the object has non default values
@@ -345,8 +302,58 @@ public final class QuestProgress {
/**
* Queues the {@link QuestProgress} instance for a completion test.
*/
- @SuppressWarnings("unused")
public void queueForCompletionTest() {
this.plugin.getQuestCompleter().queueSingular(this);
}
+
+ // DEPRECATED AND FOR REMOVAL
+
+ /**
+ * @return the associated player ID
+ * @see QuestProgress#getPlayerUUID()
+ */
+ @Deprecated(forRemoval = true)
+ @Contract(pure = true)
+ public UUID getPlayer() {
+ return this.playerUUID;
+ }
+
+ /**
+ * @return mutable task progress map values collection
+ * @see QuestProgress#getTaskProgresses()
+ */
+ @Deprecated(forRemoval = true)
+ @Contract(pure = true)
+ public Collection getTaskProgress() {
+ return this.getTaskProgresses();
+ }
+
+ /**
+ * @return mutable task progress map values collection
+ * @see QuestProgress#getTaskProgresses()
+ */
+ @Deprecated(forRemoval = true)
+ @Contract(pure = true)
+ public Collection getAllTaskProgress() {
+ return this.getTaskProgresses();
+ }
+
+ /**
+ * @param taskId the task ID to repair the progress for
+ */
+ @Deprecated(forRemoval = true)
+ public void repairTaskProgress(final String taskId) {
+ final TaskProgress taskProgress = new TaskProgress(this, taskId, this.playerUUID, null, false, false);
+ this.addTaskProgress(taskProgress);
+ }
+
+ /**
+ * It's equivalent to {@code QuestProgress#setModified(false)}.
+ *
+ * @see QuestProgress#setModified(boolean)
+ */
+ @Deprecated(forRemoval = true)
+ public void resetModified() {
+ this.setModified(false);
+ }
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgressFile.java b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgressFile.java
index 2ebefe93..c4b1eea2 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgressFile.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/QuestProgressFile.java
@@ -5,10 +5,10 @@ import com.leonardobishop.quests.common.player.questprogressfile.filters.QuestPr
import com.leonardobishop.quests.common.plugin.Quests;
import com.leonardobishop.quests.common.quest.Quest;
import com.leonardobishop.quests.common.quest.Task;
-import org.jetbrains.annotations.ApiStatus;
+import com.leonardobishop.quests.common.util.Modern;
import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -22,6 +22,8 @@ import java.util.concurrent.TimeUnit;
/**
* Represents underlying quest progress for a player.
*/
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public final class QuestProgressFile {
// https://github.com/LMBishop/Quests/issues/760
@@ -37,7 +39,7 @@ public final class QuestProgressFile {
* @param plugin the plugin instance
* @param playerUUID the associated player UUID
*/
- public QuestProgressFile(final @NotNull Quests plugin, final @NotNull UUID playerUUID) {
+ public QuestProgressFile(final Quests plugin, final UUID playerUUID) {
this.plugin = plugin;
this.playerUUID = playerUUID;
this.questProgressMap = new HashMap<>();
@@ -48,13 +50,12 @@ public final class QuestProgressFile {
*
* @param questProgressFile the quest progress file instance
*/
- @ApiStatus.Internal
- public QuestProgressFile(final @NotNull QuestProgressFile questProgressFile) {
+ public QuestProgressFile(final QuestProgressFile questProgressFile) {
final Set> progressEntries = questProgressFile.questProgressMap.entrySet();
this.plugin = questProgressFile.plugin;
this.playerUUID = questProgressFile.playerUUID;
- this.questProgressMap = new HashMap<>(progressEntries.size());
+ this.questProgressMap = HashMap.newHashMap(progressEntries.size());
for (final Map.Entry progressEntry : progressEntries) {
this.questProgressMap.put(progressEntry.getKey(), new QuestProgress(progressEntry.getValue()));
@@ -64,7 +65,7 @@ public final class QuestProgressFile {
/**
* @param questProgress the quest progress to put into the quest progress map
*/
- public void addQuestProgress(final @NotNull QuestProgress questProgress) {
+ public void addQuestProgress(final QuestProgress questProgress) {
// TODO don't do that here
//if (Options.VERIFY_QUEST_EXISTS_ON_LOAD.getBooleanValue(true) && plugin.getQuestManager().getQuestById(questProgress.getQuestId()) == null) {
// return;
@@ -80,7 +81,7 @@ public final class QuestProgressFile {
* @return list of started quests
*/
@Contract(pure = true)
- public @NotNull List getStartedQuests() {
+ public List getStartedQuests() {
return this.getAllQuestsFromProgress(QuestProgressFilter.STARTED);
}
@@ -90,7 +91,7 @@ public final class QuestProgressFile {
* @return list of matching quests
*/
@Contract(pure = true)
- public @NotNull List getAllQuestsFromProgress(final @NotNull QuestProgressFilter filter) {
+ public List getAllQuestsFromProgress(final QuestProgressFilter filter) {
final List quests = new ArrayList<>();
for (final QuestProgress questProgress : this.questProgressMap.values()) {
@@ -112,7 +113,7 @@ public final class QuestProgressFile {
* @return count of matching quests
*/
@Contract(pure = true)
- public int getAllQuestsFromProgressCount(final @NotNull QuestProgressFilter filter) {
+ public int getAllQuestsFromProgressCount(final QuestProgressFilter filter) {
int count = 0;
for (final QuestProgress questProgress : this.questProgressMap.values()) {
@@ -126,7 +127,8 @@ public final class QuestProgressFile {
return count;
}
- private @Nullable Quest getQuestFromProgress(final @NotNull QuestProgressFilter filter, final QuestProgress questProgress) {
+ @Contract(pure = true)
+ private @Nullable Quest getQuestFromProgress(final QuestProgressFilter filter, final QuestProgress questProgress) {
final boolean matchesProgress = filter.matchesProgress(questProgress);
if (!matchesProgress) {
return null;
@@ -151,7 +153,7 @@ public final class QuestProgressFile {
* @return {@code Collection} all quest progresses
*/
@Contract(pure = true)
- public @NotNull Collection getAllQuestProgress() {
+ public Collection getAllQuestProgress() {
return this.questProgressMap.values();
}
@@ -162,7 +164,7 @@ public final class QuestProgressFile {
* @return true if they have quest progress
*/
@Contract(pure = true)
- public boolean hasQuestProgress(final @NotNull Quest quest) {
+ public boolean hasQuestProgress(final Quest quest) {
return this.questProgressMap.containsKey(quest.getId());
}
@@ -170,11 +172,11 @@ public final class QuestProgressFile {
* Gets the remaining cooldown before being able to start a specific quest.
*
* @param quest the quest to test for
- * @return 0 if no cooldown remaining, -1 if the cooldown is disabled or the quest is not completed,
+ * @return {@code 0} if no cooldown remaining, {@code -1} if the cooldown is disabled or the quest is not completed,
* otherwise the cooldown in milliseconds
*/
@Contract(pure = true)
- public long getCooldownFor(final @NotNull Quest quest) {
+ public long getCooldownFor(final Quest quest) {
if (!quest.isCooldownEnabled()) {
return -1;
}
@@ -185,7 +187,7 @@ public final class QuestProgressFile {
}
final long completionDate = questProgress.getCompletionDate();
- if (completionDate == 0) {
+ if (completionDate == 0L) {
return -1;
}
@@ -200,11 +202,11 @@ public final class QuestProgressFile {
* Gets the time remaining before a quest will have expired.
*
* @param quest the quest to test for
- * @return 0 if no time remaining, -1 if the time limit is disabled or the quest is not started,
+ * @return {@code 0} if no time remaining, {@code -1} if the time limit is disabled or the quest is not started,
* otherwise the time left in milliseconds
*/
@Contract(pure = true)
- public long getTimeRemainingFor(final @NotNull Quest quest) {
+ public long getTimeRemainingFor(final Quest quest) {
if (!quest.isTimeLimitEnabled()) {
return -1;
}
@@ -215,7 +217,7 @@ public final class QuestProgressFile {
}
final long startedDate = questProgress.getStartedDate();
- if (startedDate == 0) {
+ if (startedDate == 0L) {
return -1;
}
@@ -234,7 +236,7 @@ public final class QuestProgressFile {
*/
// TODO possibly move this
@Contract(pure = true)
- public boolean hasMetRequirements(final @NotNull Quest quest) {
+ public boolean hasMetRequirements(final Quest quest) {
for (final String requiredQuestId : quest.getRequirements()) {
final QuestProgress requiredQuestProgress = this.questProgressMap.get(requiredQuestId);
if (requiredQuestProgress == null || !requiredQuestProgress.isCompletedBefore()) {
@@ -259,7 +261,7 @@ public final class QuestProgressFile {
* @return the associated player UUID
*/
@Contract(pure = true)
- public @NotNull UUID getPlayerUUID() {
+ public UUID getPlayerUUID() {
return this.playerUUID;
}
@@ -269,7 +271,7 @@ public final class QuestProgressFile {
* @param quest the quest to get the progress for
* @return {@link QuestProgress} or a blank generated one if the quest does not exist
*/
- public @NotNull QuestProgress getQuestProgress(final @NotNull Quest quest) {
+ public QuestProgress getQuestProgress(final Quest quest) {
if (DEBUG_ISSUE_760 && !this.plugin.isPrimaryThread()) {
//noinspection CallToPrintStackTrace
new IllegalStateException("async getQuestProgress call").printStackTrace();
@@ -286,7 +288,7 @@ public final class QuestProgressFile {
* @return {@link QuestProgress} or null if the quest does not exist
*/
@Contract(pure = true)
- public @Nullable QuestProgress getQuestProgressOrNull(final @NotNull Quest quest) {
+ public @Nullable QuestProgress getQuestProgressOrNull(final Quest quest) {
return this.questProgressMap.get(quest.getId());
}
@@ -297,7 +299,7 @@ public final class QuestProgressFile {
* @return true if player has the quest started
*/
@Contract(pure = true)
- public boolean hasQuestStarted(final @NotNull Quest quest) {
+ public boolean hasQuestStarted(final Quest quest) {
final QuestProgress questProgress = this.getQuestProgressOrNull(quest);
return questProgress != null && questProgress.isStarted();
}
@@ -308,7 +310,7 @@ public final class QuestProgressFile {
* @param quest the quest to generate the progress for
* @return the generated blank {@link QuestProgress}
*/
- public @NotNull QuestProgress generateBlankQuestProgress(final @NotNull Quest quest) {
+ public QuestProgress generateBlankQuestProgress(final Quest quest) {
return this.generateBlankQuestProgress(quest, false);
}
@@ -319,7 +321,7 @@ public final class QuestProgressFile {
* @param modified the modified state of the quest
* @return the generated blank {@link QuestProgress}
*/
- public @NotNull QuestProgress generateBlankQuestProgress(final @NotNull Quest quest, final boolean modified) {
+ public QuestProgress generateBlankQuestProgress(final Quest quest, final boolean modified) {
final QuestProgress questProgress = new QuestProgress(this.plugin, quest.getId(), this.playerUUID, false, 0L, false, false, 0L, modified);
for (final Task task : quest.getTasks()) {
@@ -420,7 +422,7 @@ public final class QuestProgressFile {
*/
@Deprecated(forRemoval = true)
@Contract(pure = true)
- public @NotNull List getAllQuestsFromProgress(final @NotNull QuestsProgressFilter filter) {
+ public List getAllQuestsFromProgress(final QuestsProgressFilter filter) {
final List quests = new ArrayList<>();
for (final QuestProgress questProgress : this.questProgressMap.values()) {
@@ -445,46 +447,46 @@ public final class QuestProgressFile {
ALL("all") {
@Override
@Contract(pure = true)
- public boolean matches(final @NotNull QuestProgress questProgress) {
+ public boolean matches(final QuestProgress questProgress) {
return QuestProgressFilter.ALL.matchesProgress(questProgress);
}
},
COMPLETED("completed") {
@Override
@Contract(pure = true)
- public boolean matches(final @NotNull QuestProgress questProgress) {
+ public boolean matches(final QuestProgress questProgress) {
return QuestProgressFilter.COMPLETED.matchesProgress(questProgress);
}
},
COMPLETED_BEFORE("completedBefore") {
@Override
@Contract(pure = true)
- public boolean matches(final @NotNull QuestProgress questProgress) {
+ public boolean matches(final QuestProgress questProgress) {
return QuestProgressFilter.COMPLETED_BEFORE.matchesProgress(questProgress);
}
},
STARTED("started") {
@Override
@Contract(pure = true)
- public boolean matches(final @NotNull QuestProgress questProgress) {
+ public boolean matches(final QuestProgress questProgress) {
return QuestProgressFilter.STARTED.matchesProgress(questProgress);
}
};
private final String legacy;
- QuestsProgressFilter(final @NotNull String legacy) {
+ QuestsProgressFilter(final String legacy) {
this.legacy = legacy;
}
@SuppressWarnings("unused")
@Contract(pure = true)
- public @NotNull String getLegacy() {
+ public String getLegacy() {
return this.legacy;
}
@Contract(pure = true)
- public abstract boolean matches(final @NotNull QuestProgress questProgress);
+ public abstract boolean matches(final QuestProgress questProgress);
// And some static things to improve legacy performance (is it even used?)
@@ -498,7 +500,7 @@ public final class QuestProgressFile {
@SuppressWarnings("unused")
@Contract(pure = true)
- public static @NotNull QuestsProgressFilter fromLegacy(final @NotNull String legacy) {
+ public static QuestsProgressFilter fromLegacy(final String legacy) {
return QuestsProgressFilter.legacyToFilterMap.getOrDefault(legacy, QuestsProgressFilter.ALL);
}
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/TaskProgress.java b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/TaskProgress.java
index 9395634e..531a524f 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/TaskProgress.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/questprogressfile/TaskProgress.java
@@ -1,20 +1,22 @@
package com.leonardobishop.quests.common.player.questprogressfile;
-import org.jetbrains.annotations.ApiStatus;
+import com.leonardobishop.quests.common.util.Modern;
import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.Objects;
import java.util.UUID;
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public final class TaskProgress {
- private final QuestProgress questProgress;
+ private final @Nullable QuestProgress questProgress;
private final String taskId;
private final UUID playerUUID;
- private Object progress;
+ private @Nullable Object progress;
private boolean completed;
private boolean modified;
@@ -28,7 +30,7 @@ public final class TaskProgress {
* @param completed whether the task is completed
* @param modified whether the object has been modified and needs to be saved
*/
- public TaskProgress(final @Nullable QuestProgress questProgress, final @NotNull String taskId, final @NotNull UUID playerUUID, final @Nullable Object progress, final boolean completed, final boolean modified) {
+ public TaskProgress(final @Nullable QuestProgress questProgress, final String taskId, final UUID playerUUID, final @Nullable Object progress, final boolean completed, final boolean modified) {
this.questProgress = questProgress;
this.taskId = taskId;
this.playerUUID = playerUUID;
@@ -46,7 +48,7 @@ public final class TaskProgress {
* @param progress the progress object
* @param completed whether the task is completed
*/
- public TaskProgress(final @NotNull QuestProgress questProgress, final @NotNull String taskId, final @NotNull UUID playerUUID, final @Nullable Object progress, final boolean completed) {
+ public TaskProgress(final QuestProgress questProgress, final String taskId, final UUID playerUUID, final @Nullable Object progress, final boolean completed) {
this(questProgress, taskId, playerUUID, progress, completed, false);
}
@@ -55,8 +57,7 @@ public final class TaskProgress {
*
* @param taskProgress the task progress instance
*/
- @ApiStatus.Internal
- public TaskProgress(final @NotNull TaskProgress taskProgress) {
+ public TaskProgress(final TaskProgress taskProgress) {
this(null, taskProgress.taskId, taskProgress.playerUUID, taskProgress.progress, taskProgress.completed, taskProgress.modified);
}
@@ -64,25 +65,15 @@ public final class TaskProgress {
* @return the associated task ID
*/
@Contract(pure = true)
- public @NotNull String getTaskId() {
+ public String getTaskId() {
return this.taskId;
}
- /**
- * @return the associated player ID
- * @see QuestProgress#getPlayerUUID()
- */
- @Deprecated(forRemoval = true)
- @Contract(pure = true)
- public @NotNull UUID getPlayer() {
- return this.playerUUID;
- }
-
/**
* @return the associated player ID
*/
@Contract(pure = true)
- public @NotNull UUID getPlayerUUID() {
+ public UUID getPlayerUUID() {
return this.playerUUID;
}
@@ -144,6 +135,25 @@ public final class TaskProgress {
return this.modified;
}
+ /**
+ * @param modified whether the object has been modified and needs to be saved
+ */
+ public void setModified(final boolean modified) {
+ this.modified = modified;
+ }
+
+ // DEPRECATED AND FOR REMOVAL
+
+ /**
+ * @return the associated player ID
+ * @see QuestProgress#getPlayerUUID()
+ */
+ @Deprecated(forRemoval = true)
+ @Contract(pure = true)
+ public UUID getPlayer() {
+ return this.playerUUID;
+ }
+
/**
* It's equivalent to {@code TaskProgress#setModified(false)}.
*
@@ -153,11 +163,4 @@ public final class TaskProgress {
public void resetModified() {
this.setModified(false);
}
-
- /**
- * @param modified whether the object has been modified and needs to be saved
- */
- public void setModified(final boolean modified) {
- this.modified = modified;
- }
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/plugin/Quests.java b/common/src/main/java/com/leonardobishop/quests/common/plugin/Quests.java
index 23533210..ddfad1b2 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/plugin/Quests.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/plugin/Quests.java
@@ -10,8 +10,9 @@ import com.leonardobishop.quests.common.scheduler.ServerScheduler;
import com.leonardobishop.quests.common.storage.StorageProvider;
import com.leonardobishop.quests.common.tasktype.TaskTypeManager;
import com.leonardobishop.quests.common.updater.Updater;
-import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+@NullMarked
public interface Quests {
/**
@@ -20,7 +21,7 @@ public interface Quests {
* @see QuestsLogger
* @return quests logger
*/
- @NotNull QuestsLogger getQuestsLogger();
+ QuestsLogger getQuestsLogger();
/**
* Obtain an instance of the QuestManager.
@@ -28,7 +29,15 @@ public interface Quests {
* @see QuestManager
* @return quest manager
*/
- @NotNull QuestManager getQuestManager();
+ QuestManager getQuestManager();
+
+ /**
+ * Obtain an instance of the TaskTypeManager.
+ *
+ * @see TaskTypeManager
+ * @return task type manager
+ */
+ TaskTypeManager getTaskTypeManager();
/**
* Obtain an instance of the QPlayerManager.
@@ -36,7 +45,7 @@ public interface Quests {
* @see QPlayerManager
* @return quest player manager
*/
- @NotNull QPlayerManager getPlayerManager();
+ QPlayerManager getPlayerManager();
/**
* Obtain an instance of the QuestController.
@@ -44,15 +53,7 @@ public interface Quests {
* @see QuestController
* @return quest controller
*/
- @NotNull QuestController getQuestController();
-
- /**
- * Obtain an instance of the TaskTypeManager.
- *
- * @see TaskTypeManager
- * @return task type manager
- */
- @NotNull TaskTypeManager getTaskTypeManager();
+ QuestController getQuestController();
/**
* Obtain an instance of the QuestCompleter.
@@ -60,7 +61,7 @@ public interface Quests {
* @see QuestCompleter
* @return quest completer
*/
- @NotNull QuestCompleter getQuestCompleter();
+ QuestCompleter getQuestCompleter();
/**
* Obtain an instance of the QuestConfig.
@@ -68,7 +69,7 @@ public interface Quests {
* @see QuestsConfig
* @return quest config
*/
- @NotNull QuestsConfig getQuestsConfig();
+ QuestsConfig getQuestsConfig();
/**
* Obtain an instance of the Updater.
@@ -76,7 +77,7 @@ public interface Quests {
* @see Updater
* @return updater
*/
- @NotNull Updater getUpdater();
+ Updater getUpdater();
/**
* Obtain an instance of the ServerScheduler.
@@ -84,7 +85,7 @@ public interface Quests {
* @see ServerScheduler
* @return server scheduler
*/
- @NotNull ServerScheduler getScheduler();
+ ServerScheduler getScheduler();
/**
* Obtain an instance of the StorageProvider.
@@ -92,7 +93,7 @@ public interface Quests {
* @see StorageProvider
* @return storage provider
*/
- @NotNull StorageProvider getStorageProvider();
+ StorageProvider getStorageProvider();
/**
* Performs a full reload of the plugin, unloading and re-registering quests to their task types.
diff --git a/common/src/main/java/com/leonardobishop/quests/common/quest/Category.java b/common/src/main/java/com/leonardobishop/quests/common/quest/Category.java
index 0531af5b..285eff1a 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/quest/Category.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/quest/Category.java
@@ -1,73 +1,116 @@
package com.leonardobishop.quests.common.quest;
-import org.jetbrains.annotations.NotNull;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-public class Category {
+/**
+ * Represents a category for organizing quests within the quest system. Each category can have
+ * associated quests, and it can specify whether permission is required to access it and whether
+ * it should be hidden from the plugin menus.
+ */
+@Modern(type = Modern.Type.FULL)
+@NullMarked
+public final class Category {
+
+ private static final String PERMISSION_PREFIX = "quests.category.";
private final String id;
+ private final List registeredQuestIds;
private final boolean permissionRequired;
- private final List registeredQuestIds = new ArrayList<>();
private final boolean hidden;
- public Category(String id, boolean permissionRequired) {
- this(id, permissionRequired, false);
- }
-
- public Category(String id, boolean permissionRequired, boolean hidden) {
- this.id = id;
+ /**
+ * Constructs a Category with the specified parameters.
+ *
+ * @param id the unique identifier for the category; must not be null
+ * @param permissionRequired whether a permission is required to access this category
+ * @param hidden whether the category should be hidden from view
+ */
+ public Category(final String id, final boolean permissionRequired, final boolean hidden) {
+ this.id = Objects.requireNonNull(id, "id cannot be null");
+ this.registeredQuestIds = new ArrayList<>();
this.permissionRequired = permissionRequired;
this.hidden = hidden;
}
/**
- * Get the id of this category.
+ * Constructs a Category with {@link Category#hidden} set to {@code false}.
*
- * @return id
+ * @param id the unique identifier for the category; must not be null
+ * @param permissionRequired whether a permission is required to access this category
*/
- public @NotNull String getId() {
- return id;
+ public Category(final String id, final boolean permissionRequired) {
+ this(id, permissionRequired, false);
}
/**
- * Get if a specific permission is required to open this category and start quests within it.
- * This permission will be in the form of "quests.category.[category id]".
+ * Returns the unique identifier of this category.
*
- * @return boolean
+ * @return the category ID
*/
+ @Contract(pure = true)
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * Checks if a specific permission is required to access this category and start quests within it.
+ * The permission will be in the form of "quests.category.[category id]".
+ *
+ * @return true if permission is required, false otherwise
+ * @see Category#getPermission() Permission getter
+ */
+ @Contract(pure = true)
public boolean isPermissionRequired() {
- return permissionRequired;
+ return this.permissionRequired;
}
/**
- * Register a new quest ID to this category
+ * Returns the permission required to start quests in this category.
*
- * @param questId quest id to register
+ * @return the permission string if required, or null if no permission is needed
*/
- public void registerQuestId(@NotNull String questId) {
+ @Contract(pure = true)
+ public @Nullable String getPermission() {
+ return this.permissionRequired ? PERMISSION_PREFIX + this.id : null;
+ }
+
+ /**
+ * Registers a new quest ID to this category.
+ *
+ * @param questId the quest ID to register; must not be null
+ */
+ public void registerQuestId(final String questId) {
Objects.requireNonNull(questId, "questId cannot be null");
- registeredQuestIds.add(questId);
+
+ this.registeredQuestIds.add(questId);
}
/**
- * Get quest IDs which are registered to this category
+ * Returns an unmodifiable list of quest IDs that are registered to this category.
*
- * @return immutable list of quest ids
+ * @return an unmodifiable list of registered quest IDs
*/
- public @NotNull List getRegisteredQuestIds() {
- return Collections.unmodifiableList(registeredQuestIds);
+ @Contract(pure = true)
+ public @UnmodifiableView List getRegisteredQuestIds() {
+ return Collections.unmodifiableList(this.registeredQuestIds);
}
/**
- * Get if this category is hidden
+ * Checks if this category is hidden from view.
*
- * @return true if hidden
+ * @return true if the category is hidden, false otherwise
*/
+ @Contract(pure = true)
public boolean isHidden() {
- return hidden;
+ return this.hidden;
}
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/quest/Quest.java b/common/src/main/java/com/leonardobishop/quests/common/quest/Quest.java
index 1f5d6d0d..b0d73e4e 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/quest/Quest.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/quest/Quest.java
@@ -108,6 +108,13 @@ public class Quest implements Comparable {
return permissionRequired;
}
+ /**
+ * @return permission required to start the quest
+ */
+ public @Nullable String getPermission() {
+ return isPermissionRequired() ? "quests.quest." + id : null;
+ }
+
/**
* Get the reward string of the quest.
* The reward string is a series of messages sent to the player upon completing the quest.
diff --git a/common/src/main/java/com/leonardobishop/quests/common/quest/QuestManager.java b/common/src/main/java/com/leonardobishop/quests/common/quest/QuestManager.java
index 2a569b2e..562fad8a 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/quest/QuestManager.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/quest/QuestManager.java
@@ -1,8 +1,10 @@
package com.leonardobishop.quests.common.quest;
-import com.leonardobishop.quests.common.plugin.Quests;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
@@ -14,14 +16,20 @@ import java.util.Objects;
/**
* The quests manager stores all present Quests and Categories on the server and is used as a registry.
*/
-public class QuestManager {
+@Modern(type = Modern.Type.FULL)
+@NullMarked
+public final class QuestManager {
- private final Quests plugin;
- private final Map quests = new LinkedHashMap<>();
- private final List categories = new ArrayList<>();
+ private final Map questMap;
+ private final List categories;
- public QuestManager(Quests plugin) {
- this.plugin = plugin;
+ /**
+ * Constructs a QuestManager.
+ */
+ public QuestManager() {
+ // Specify expected size as people tend to add horrendous amounts of quests
+ this.questMap = LinkedHashMap.newLinkedHashMap(1024);
+ this.categories = new ArrayList<>();
}
/**
@@ -29,28 +37,31 @@ public class QuestManager {
*
* @param quest the category to register
*/
- public void registerQuest(@NotNull Quest quest) {
+ public void registerQuest(final Quest quest) {
Objects.requireNonNull(quest, "quest cannot be null");
- quests.put(quest.getId(), quest);
+ this.questMap.put(quest.getId(), quest);
}
/**
* @param id id to match
* @return {@link Quest}, or null
*/
- public @Nullable Quest getQuestById(@NotNull String id) {
+ @Contract(pure = true)
+ public @Nullable Quest getQuestById(final String id) {
Objects.requireNonNull(id, "id cannot be null");
- return quests.get(id);
+ return this.questMap.get(id);
}
/**
* Get a map of id-quest of all quests registered
+ *
* @return immutable map of all {@link Quest}
*/
- public @NotNull Map getQuests() {
- return Collections.unmodifiableMap(quests);
+ @Contract(pure = true)
+ public @UnmodifiableView Map getQuestMap() {
+ return Collections.unmodifiableMap(this.questMap);
}
/**
@@ -58,17 +69,10 @@ public class QuestManager {
*
* @param category the category to register
*/
- public void registerCategory(@NotNull Category category) {
+ public void registerCategory(final Category category) {
Objects.requireNonNull(category, "category cannot be null");
- categories.add(category);
- }
-
- /**
- * @return immutable list of all {@link Category}
- */
- public @NotNull List getCategories() {
- return Collections.unmodifiableList(categories);
+ this.categories.add(category);
}
/**
@@ -77,21 +81,48 @@ public class QuestManager {
* @param id the id
* @return {@link Category}, or null
*/
- public @Nullable Category getCategoryById(@NotNull String id) {
+ @Contract(pure = true)
+ public @Nullable Category getCategoryById(final String id) {
Objects.requireNonNull(id, "id cannot be null");
- for (Category category : categories) {
- if (category.getId().equals(id)) return category;
+ for (final Category category : this.categories) {
+ if (category.getId().equals(id)) {
+ return category;
+ }
}
+
return null;
}
+ /**
+ * Get a map of id-category of all categories registered
+ *
+ * @return immutable map of all {@link Quest}
+ */
+ @Contract(pure = true)
+ public @UnmodifiableView List getCategories() {
+ return Collections.unmodifiableList(this.categories);
+ }
+
/**
* Reset the quest manager and clears all registered quests and categories
*/
public void clear() {
- quests.clear();
- categories.clear();
+ this.questMap.clear();
+ this.categories.clear();
}
+ // DEPRECATED AND FOR REMOVAL
+
+ /**
+ * Get a map of id-quest of all quests registered
+ *
+ * @return immutable map of all {@link Quest}
+ * @see QuestManager#getQuestMap()
+ */
+ @Deprecated(forRemoval = true)
+ @Contract(pure = true)
+ public @UnmodifiableView Map getQuests() {
+ return this.getQuestMap();
+ }
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/quest/Task.java b/common/src/main/java/com/leonardobishop/quests/common/quest/Task.java
index b92ed59e..c11b508e 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/quest/Task.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/quest/Task.java
@@ -1,60 +1,70 @@
package com.leonardobishop.quests.common.quest;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
-public class Task {
+@Modern(type = Modern.Type.FULL)
+@NullMarked
+public final class Task {
- private final Map configValues = new HashMap<>();
private final String id;
private final String type;
+ private final Map configValues;
- public Task(String id, String type) {
+ public Task(final String id, final String type) {
this.id = id;
this.type = type;
+ this.configValues = new HashMap<>();
}
/**
- * @return the id of this task
+ * @return the id of the task
*/
- public @NotNull String getId() {
- return id;
+ @Contract(pure = true)
+ public String getId() {
+ return this.id;
}
/**
* @return the configured task type for this task
*/
- public @NotNull String getType() {
- return type;
+ @Contract(pure = true)
+ public String getType() {
+ return this.type;
}
/**
* Check if a config value is set for this task
*
- * @param key key of config value to check
- * @return whether it exists
+ * @param key key of the config value to check
+ * @return whether the specified key exists
*/
- public boolean hasConfigKey(@NotNull String key) {
+ @Contract(pure = true)
+ public boolean hasConfigKey(final String key) {
Objects.requireNonNull(key, "key cannot be null");
- return configValues.containsKey(key);
+ return this.configValues.containsKey(key);
}
/**
* Get a specific configuration value for this task
*
- * @param key key of config value to get
+ * @param key key of the config value to get
* @return config value, or null
*/
- public @Nullable Object getConfigValue(@NotNull String key) {
+ @Contract(pure = true)
+ public @Nullable Object getConfigValue(final String key) {
Objects.requireNonNull(key, "key cannot be null");
- return configValues.getOrDefault(key, null); //??? this will return null without the need of `OrDefault(key, null)`
+ return this.configValues.get(key);
}
/**
@@ -62,32 +72,34 @@ public class Task {
*
* @param key key of config value to get
* @param def default value if null
- * @return config value, or null
+ * @return config value, or default
*/
- public @Nullable Object getConfigValue(@NotNull String key, @Nullable Object def) {
+ @Contract(pure = true)
+ public Object getConfigValue(final String key, final Object def) {
Objects.requireNonNull(key, "key cannot be null");
+ Objects.requireNonNull(def, "def cannot be null");
- return configValues.getOrDefault(key, def);
+ return this.configValues.getOrDefault(key, def);
}
/**
- * @return immutable list containing all config values
+ * @return immutable map of the config values
*/
- public @NotNull Map getConfigValues() {
- return Collections.unmodifiableMap(configValues);
+ @Contract(pure = true)
+ public @UnmodifiableView Map getConfigValues() {
+ return Collections.unmodifiableMap(this.configValues);
}
/**
* Add a key-value pair to this tasks configuration
*
- * @param key key
+ * @param key key
* @param value value
*/
- public void addConfigValue(@NotNull String key, @NotNull Object value) {
+ public void addConfigValue(final String key, final Object value) {
Objects.requireNonNull(key, "key cannot be null");
Objects.requireNonNull(value, "value cannot be null");
- configValues.put(key, value);
+ this.configValues.put(key, value);
}
-
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/questcontroller/QuestController.java b/common/src/main/java/com/leonardobishop/quests/common/questcontroller/QuestController.java
index d1e4812c..a178ca5e 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/questcontroller/QuestController.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/questcontroller/QuestController.java
@@ -3,27 +3,35 @@ package com.leonardobishop.quests.common.questcontroller;
import com.leonardobishop.quests.common.enums.QuestStartResult;
import com.leonardobishop.quests.common.player.QPlayer;
import com.leonardobishop.quests.common.quest.Quest;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
/**
* The quests controller dictates how the plugin should act and acts as a bridge between a player
* and their progress file, interpreting the progress file and mutating it on certain events.
*/
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public interface QuestController {
+ @Contract(pure = true)
String getName();
- QuestStartResult startQuestForPlayer(QPlayer qPlayer, Quest quest);
-
+ @Contract(pure = true)
QuestStartResult canPlayerStartQuest(QPlayer qPlayer, Quest quest);
- boolean completeQuestForPlayer(QPlayer qPlayer, Quest quest);
-
+ @Contract(pure = true)
boolean hasPlayerStartedQuest(QPlayer qPlayer, Quest quest);
+ QuestStartResult startQuestForPlayer(QPlayer qPlayer, Quest quest);
+
+ boolean completeQuestForPlayer(QPlayer qPlayer, Quest quest);
+
boolean cancelQuestForPlayer(QPlayer qPlayer, Quest quest);
boolean expireQuestForPlayer(QPlayer qPlayer, Quest quest);
- void trackQuestForPlayer(QPlayer qPlayer, Quest quest);
-
+ void trackQuestForPlayer(QPlayer qPlayer, @Nullable Quest quest);
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskType.java b/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskType.java
index 526b7444..7e294c55 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskType.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskType.java
@@ -3,193 +3,208 @@ package com.leonardobishop.quests.common.tasktype;
import com.leonardobishop.quests.common.config.ConfigProblem;
import com.leonardobishop.quests.common.quest.Quest;
import com.leonardobishop.quests.common.quest.Task;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Unmodifiable;
+import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
/**
- * A task type which can be used within Quests. A {@link Quest}
- * will be registered to this if it contains at least 1 task
- * which is of this type. This is so you do not have to
- * iterate through every single quest.
+ * Represents a type of task that can be used within quests. A {@link Quest}
+ * will be associated with this task type if it contains at least one task
+ * of this type, allowing for efficient quest management without the need
+ * to iterate through every single quest.
*/
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public abstract class TaskType {
protected final String type;
- private final String author;
- private final String description;
- private final Set aliases;
- private final Set quests;
- private final Set configValidators;
+ private final @Nullable String author;
+ private final @Nullable String description;
+ private final List aliases;
+ private final List configValidators;
+ private final List quests;
/**
- * Constructs a TaskType.
+ * Constructs a new TaskType with the specified parameters.
*
- * @param type the name of the task type, should not contain spaces
- * @param author the name of the person (or people) who wrote it
- * @param description a short, simple description of the task type
- * @param aliases the aliases of the task type, should not contain spaces
+ * @param type the name of the task type; must not contain spaces
+ * @param author the name of the person (or people) who created this task type; can be null
+ * @param description a short description of the task type; can be null
+ * @param aliases an array of alternative names for this task type; must not be null
*/
- public TaskType(final @NotNull String type, final @Nullable String author, final @Nullable String description, final @NotNull String @NotNull ... aliases) {
+ public TaskType(final String type, final @Nullable String author, final @Nullable String description, final String... aliases) {
Objects.requireNonNull(type, "type cannot be null");
Objects.requireNonNull(aliases, "aliases cannot be null");
this.type = type;
this.author = author;
this.description = description;
- this.aliases = Set.of(aliases);
- this.quests = new HashSet<>();
- this.configValidators = new HashSet<>();
+ this.aliases = List.of(aliases);
+ this.configValidators = new ArrayList<>();
+ this.quests = new ArrayList<>();
}
/**
- * Constructs a TaskType with the specified type, author, and description.
+ * Constructs a new TaskType with the specified type, author, and description.
*
- * @param type the name of the task type, should not contain spaces
- * @param author the name of the person (or people) who wrote it
- * @param description a short, simple description of the task type
+ * @param type the name of the task type; must not contain spaces
+ * @param author the name of the person (or people) who created this task type; can be null
+ * @param description a short description of the task type; can be null
*/
- public TaskType(final @NotNull String type, final @Nullable String author, final @Nullable String description) {
+ public TaskType(final String type, final @Nullable String author, final @Nullable String description) {
this(type, author, description, new String[0]);
}
/**
- * Constructs a TaskType with the specified type.
+ * Constructs a new TaskType with the specified type.
*
- * @param type the name of the task type, should not contain spaces
+ * @param type the name of the task type; must not contain spaces
*/
- public TaskType(final @NotNull String type) {
+ public TaskType(final String type) {
this(type, null, null);
}
/**
- * Registers a {@link Quest} to this task type. This is usually done when
- * all the quests are initially loaded.
+ * Returns the name of this task type.
*
- * @param quest the {@link Quest} to register.
+ * @return the task type name
*/
- public final void registerQuest(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
-
- this.quests.add(quest);
+ @Contract(pure = true)
+ public final String getType() {
+ return this.type;
}
/**
- * Clears the set which contains the registered quests.
+ * Returns the author of this task type.
+ *
+ * @return the author's name, or null if not specified
*/
- protected final void unregisterAll() {
- this.quests.clear();
+ @Contract(pure = true)
+ public final @Nullable String getAuthor() {
+ return this.author;
}
/**
- * Returns an immutable set of all registered quests.
+ * Returns the description of this task type.
*
- * @return immutable {@link Set} of type {@link Quest} of all registered quests.
+ * @return the description, or null if not specified
*/
- public final @NotNull Set getRegisteredQuests() {
- return Collections.unmodifiableSet(this.quests);
+ @Contract(pure = true)
+ public final @Nullable String getDescription() {
+ return this.description;
}
/**
- * Returns the type of this task type.
+ * Returns an unmodifiable list of aliases for this task type.
*
- * @return the type of this task type
+ * @return an unmodifiable list of aliases
*/
- public final @NotNull String getType() {
- return this.type;
+ @Contract(pure = true)
+ public final @Unmodifiable List getAliases() {
+ return this.aliases;
}
/**
- * Returns the author of this task type.
+ * Returns an unmodifiable view of the list of configuration validators for this task type.
*
- * @return the author of this task type, or null if not specified
+ * @return an unmodifiable view of the configuration validators
*/
- public final @Nullable String getAuthor() {
- return this.author;
+ @Contract(pure = true)
+ public @UnmodifiableView List getConfigValidators() {
+ return Collections.unmodifiableList(this.configValidators);
}
/**
- * Returns the description of this task type.
+ * Adds a configuration validator to this task type.
*
- * @return the description of this task type, or null if not specified
+ * @param validator the configuration validator to add; must not be null
*/
- public final @Nullable String getDescription() {
- return this.description;
+ public void addConfigValidator(final ConfigValidator validator) {
+ Objects.requireNonNull(validator, "validator cannot be null");
+
+ this.configValidators.add(validator);
}
/**
- * Returns the aliases of this task type.
+ * Returns an unmodifiable list of all registered quests for this task type.
*
- * @return a set of aliases of this task type
+ * @return an unmodifiable list of registered quests
*/
- public final @NotNull Set getAliases() {
- return this.aliases;
+ @Contract(pure = true)
+ public final @UnmodifiableView List getRegisteredQuests() {
+ return Collections.unmodifiableList(this.quests);
}
/**
- * Called when Quests has finished registering all quests to the task type.
- * May be called several times if an operator uses /quests admin reload.
+ * Registers a quest to this task type. This is typically done when
+ * all quests are initially loaded.
+ *
+ * @param quest the quest to register; must not be null
*/
- public void onReady() {
- // not implemented here
+ public final void registerQuest(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ if (!this.quests.contains(quest)) {
+ this.quests.add(quest);
+ }
}
/**
- * Called when a player starts a quest containing a task of this type.
- *
- * @param quest the quest containing the task
- * @param task the task being started
- * @param playerUUID the UUID of the player starting the task
+ * Clears all registered quests from this task type.
*/
- public void onStart(final @NotNull Quest quest, final @NotNull Task task, final @NotNull UUID playerUUID) {
- // not implemented here
+ public final void unregisterAll() {
+ this.quests.clear();
}
/**
- * Called when a task type is disabled.
+ * Called when all quests have been registered to this task type.
+ * This method may be called multiple times if an operator uses
+ * the /quests admin reload command.
*/
- public void onDisable() {
- // not implemented here
+ public void onReady() {
+ // Not implemented here
}
/**
- * Adds a config validator to this task type.
+ * Called when a player starts a quest that contains a task of this type.
*
- * @param validator the config validator to add
+ * @param quest the quest being started
+ * @param task the task being started
+ * @param playerUUID the UUID of the player starting the quest
*/
- public void addConfigValidator(final @NotNull ConfigValidator validator) {
- Objects.requireNonNull(validator, "validator cannot be null");
-
- this.configValidators.add(validator);
+ public void onStart(final Quest quest, final Task task, final UUID playerUUID) {
+ // Not implemented here
}
/**
- * Returns an immutable set of config validators.
- *
- * @return an immutable set of config validators
+ * Called when this task type is disabled.
*/
- public @NotNull Set getConfigValidators() {
- return Collections.unmodifiableSet(this.configValidators);
+ public void onDisable() {
+ // Not implemented here
}
/**
- * A functional interface for config validation.
+ * A functional interface for validating task configuration.
*/
@FunctionalInterface
public interface ConfigValidator {
/**
- * Validates the configuration of a task.
+ * Validates the configuration for a task.
*
- * @param taskConfig the configuration of the task
- * @param problems the set of problems to report validation issues
+ * @param taskConfig the configuration map for the task
+ * @param problems a list to collect any configuration problems found
*/
- void validateConfig(final @NotNull Map taskConfig, final @NotNull Set problems);
+ void validateConfig(Map taskConfig, List problems);
}
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskTypeManager.java b/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskTypeManager.java
index c8aee763..f3f5ddd6 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskTypeManager.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/tasktype/TaskTypeManager.java
@@ -2,12 +2,17 @@ package com.leonardobishop.quests.common.tasktype;
import com.leonardobishop.quests.common.quest.Quest;
import com.leonardobishop.quests.common.quest.Task;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import com.leonardobishop.quests.common.util.Modern;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Unmodifiable;
+import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -16,11 +21,13 @@ import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
/**
- * The task type manager stores all registered task types and registers individual quests to each task type.
- * Task types can only be registered if registrations are enabled, which is typically only during start-up.
- * This is to ensure quests are only registered to task types when all task types have been registered first.
+ * Manages the registration and handling of task types within the quest system.
+ * The TaskTypeManager stores all registered task types and associates individual quests with each task type.
+ * Task types can only be registered when registrations are enabled, typically during the startup phase.
+ * This ensures that quests are only registered to task types after all task types have been registered.
*/
-@SuppressWarnings("UnusedReturnValue")
+@Modern(type = Modern.Type.FULL)
+@NullMarked
public abstract class TaskTypeManager {
private final Set exclusions;
@@ -34,12 +41,12 @@ public abstract class TaskTypeManager {
/**
* Constructs a TaskTypeManager with a specified set of exclusions.
*
- * @param exclusions a set of task type names to exclude from registration
+ * @param exclusions a collection of task type names to exclude from registration; must not be null
*/
- public TaskTypeManager(final @NotNull Set exclusions) {
+ public TaskTypeManager(final Collection exclusions) {
Objects.requireNonNull(exclusions, "exclusions cannot be null");
- this.exclusions = exclusions;
+ this.exclusions = Set.copyOf(exclusions);
this.taskTypes = new HashMap<>();
this.aliases = new HashMap<>();
this.registrationsOpen = true;
@@ -50,38 +57,39 @@ public abstract class TaskTypeManager {
/**
* Constructs a TaskTypeManager with an empty set of exclusions.
- * Use this constructor when no exclusions are needed.
*/
public TaskTypeManager() {
this(Set.of());
}
/**
- * Returns an immutable set containing all task type exclusions.
+ * Returns an unmodifiable set containing task type exclusions.
*
- * @return immutable {@link Set} containing all task type exclusions
+ * @return an unmodifiable set of task type exclusions
*/
- @SuppressWarnings("unused")
- public @NotNull Set getExclusions() {
- return Collections.unmodifiableSet(this.exclusions);
+ @Contract(pure = true)
+ public @Unmodifiable Set getExclusions() {
+ return this.exclusions;
}
/**
- * Returns an immutable collection containing all registered task types.
+ * Returns an unmodifiable collection of registered {@link TaskType} instances.
*
- * @return immutable {@link Set} containing all registered {@link TaskType}
+ * @return an unmodifiable collection of registered task types
*/
- public @NotNull Collection getTaskTypes() {
+ @Contract(pure = true)
+ public @UnmodifiableView Collection getTaskTypes() {
return Collections.unmodifiableCollection(this.taskTypes.values());
}
/**
- * Gets a registered task type by type.
+ * Retrieves a registered {@link TaskType} by its type name.
*
- * @param type the type to check
- * @return the {@link TaskType} if found, null otherwise
+ * @param type the type name of the task type to retrieve; must not be null
+ * @return the registered task type, or null if not found
*/
- public @Nullable TaskType getTaskType(final @NotNull String type) {
+ @Contract(pure = true)
+ public @Nullable TaskType getTaskType(final String type) {
Objects.requireNonNull(type, "type cannot be null");
final TaskType taskType = this.taskTypes.get(type);
@@ -98,12 +106,13 @@ public abstract class TaskTypeManager {
}
/**
- * Gets the actual name of a task type, following aliases.
+ * Resolves the actual name of a registered {@link TaskType}, considering aliases.
*
- * @param type name of task type
- * @return the actual name of the task type, or null if not found
+ * @param type the type name or alias of the task type to resolve; must not be null
+ * @return the actual name of the registered task type, or null if not found
*/
- public @Nullable String resolveTaskTypeName(final @NotNull String type) {
+ @Contract(pure = true)
+ public @Nullable String resolveTaskTypeName(final String type) {
Objects.requireNonNull(type, "type cannot be null");
return this.taskTypes.containsKey(type)
@@ -112,12 +121,12 @@ public abstract class TaskTypeManager {
}
/**
- * Registers a task type with the task type manager.
+ * Registers a {@link TaskType} with the task type manager.
*
- * @param taskType the task type to register
- * @return true if the task type was successfully registered, false otherwise
+ * @param taskType the task type to be registered; must not be null
+ * @return whether the task type was successfully registered
*/
- public boolean registerTaskType(final @NotNull TaskType taskType) {
+ public boolean registerTaskType(final TaskType taskType) {
Objects.requireNonNull(taskType, "taskType cannot be null");
if (!this.registrationsOpen) {
@@ -125,7 +134,7 @@ public abstract class TaskTypeManager {
}
final String type = taskType.getType();
- final Set aliases = taskType.getAliases();
+ final List aliases = taskType.getAliases();
if (this.exclusions.contains(type) || this.taskTypes.containsKey(type)
|| !Collections.disjoint(this.exclusions, aliases)
@@ -145,13 +154,13 @@ public abstract class TaskTypeManager {
}
/**
- * Registers a task type with the task type manager using suppliers.
+ * Registers a {@link TaskType} using a supplier and compatibility checks.
*
- * @param taskTypeSupplier supplier of the task type to register
- * @param compatibilitySuppliers suppliers to check for task type compatibility
- * @return true if the task type was successfully registered, false otherwise
+ * @param taskTypeSupplier a supplier that provides the task type to register; must not be null
+ * @param compatibilitySuppliers suppliers that check for task type compatibility; must not be null
+ * @return whether the task type was successfully registered
*/
- public boolean registerTaskType(final @NotNull Supplier taskTypeSupplier, final @NotNull BooleanSupplier @NotNull ... compatibilitySuppliers) {
+ public boolean registerTaskType(final Supplier taskTypeSupplier, final BooleanSupplier... compatibilitySuppliers) {
Objects.requireNonNull(taskTypeSupplier, "taskTypeSupplier cannot be null");
Objects.requireNonNull(compatibilitySuppliers, "compatibilitySuppliers cannot be null");
@@ -170,77 +179,90 @@ public abstract class TaskTypeManager {
}
/**
- * Closes the task type registrations. This is typically done after start-up.
+ * Registers a quest with its associated task types. This will register the quest to each task type it contains.
+ *
+ * @param quest the quest to register; must not be null
*/
- public void closeRegistrations() {
- this.registrationsOpen = false;
+ public void registerQuestTasksWithTaskTypes(final Quest quest) {
+ Objects.requireNonNull(quest, "quest cannot be null");
+
+ if (this.registrationsOpen) {
+ throw new IllegalStateException("Still accepting new task types (type registrations must be closed before registering quests)");
+ }
+
+ for (final Task task : quest.getTasks()) {
+ final TaskType taskType = this.getTaskType(task.getType());
+
+ if (taskType != null) {
+ taskType.registerQuest(quest);
+ }
+ }
}
/**
- * Checks if registrations are still open.
+ * Resets all quest-to-task type registrations. This does not clear the task types registered with the task type manager.
+ */
+ public void resetTaskTypes() {
+ for (final TaskType taskType : this.taskTypes.values()) {
+ taskType.unregisterAll();
+ }
+ }
+
+ /**
+ * Checks if task type registrations are still open.
*
* @return true if registrations are open, false otherwise
*/
+ @Contract(pure = true)
public boolean areRegistrationsOpen() {
return this.registrationsOpen;
}
/**
- * Returns the number of task types registered.
+ * Closes the task type registrations. This is typically done after the startup phase.
+ */
+ public void closeRegistrations() {
+ this.registrationsOpen = false;
+ }
+
+ /**
+ * Returns the number of task types that have been registered.
*
- * @return number of task types registered
+ * @return the count of registered task types
*/
+ @Contract(pure = true)
public int getRegistered() {
return this.registered;
}
/**
- * Returns the number of task types skipped due to exclusions or name conflicts.
+ * Returns the number of task types that were skipped due to exclusions or name conflicts.
*
- * @return number of task types skipped
+ * @return the count of skipped task types
*/
+ @Contract(pure = true)
public int getSkipped() {
return this.skipped;
}
/**
- * Returns the number of task types skipped due to failing to meet specified requirements.
+ * Returns the number of task types that were skipped due to failing to meet specified requirements.
*
- * @return number of task types skipped due to failing to meet specified requirements
+ * @return the count of unsupported task types
*/
+ @Contract(pure = true)
public int getUnsupported() {
return this.unsupported;
}
/**
- * Registers a quest with its task types. This will register the quest to each task type it contains.
+ * Sends a debug message.
*
- * @param quest the quest to register
- */
- public void registerQuestTasksWithTaskTypes(final @NotNull Quest quest) {
- Objects.requireNonNull(quest, "quest cannot be null");
-
- if (this.registrationsOpen) {
- throw new IllegalStateException("Still accepting new task types (type registrations must be closed before registering quests)");
- }
-
- for (final Task task : quest.getTasks()) {
- final TaskType taskType = this.getTaskType(task.getType());
-
- if (taskType != null) {
- taskType.registerQuest(quest);
- }
- }
- }
-
- /**
- * Resets all quest to task type registrations. This does not clear the task types registered to the task type manager.
+ * @param message the debug message to send
+ * @param taskType the name of the task type associated with the message
+ * @param questId the ID of the quest associated with the message
+ * @param taskId the ID of the task associated with the message
+ * @param associatedPlayer the UUID of the player associated with the message
*/
- public void resetTaskTypes() {
- for (final TaskType taskType : this.taskTypes.values()) {
- taskType.unregisterAll();
- }
- }
-
- public abstract void sendDebug(final @NotNull String message, final @NotNull String taskType, final @NotNull String questId, final @NotNull String taskId, final @NotNull UUID associatedPlayer);
+ public abstract void sendDebug(final String message, final String taskType, final String questId, final String taskId, final UUID associatedPlayer);
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/util/Modern.java b/common/src/main/java/com/leonardobishop/quests/common/util/Modern.java
new file mode 100644
index 00000000..a607e575
--- /dev/null
+++ b/common/src/main/java/com/leonardobishop/quests/common/util/Modern.java
@@ -0,0 +1,21 @@
+package com.leonardobishop.quests.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark classes which have been rewritten to meet project revamp requirements.
+ */
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Modern {
+
+ Type type();
+
+ enum Type {
+ FULL,
+ PARTIAL
+ }
+}
--
cgit v1.2.3-70-g09d2