From 865f91c9367870e7b6eb513adcced50d057dad27 Mon Sep 17 00:00:00 2001 From: Rubenicos <44579213+rubenicos@users.noreply.github.com> Date: Wed, 3 Feb 2021 07:41:35 -0600 Subject: New faster placeholders --- .github/workflows/build.yml | 40 ++ .gitignore | 10 +- README.md | 19 +- build.gradle | 80 ++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58695 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 183 ++++++++ gradlew.bat | 100 ++++ pom.xml | 199 -------- settings.gradle | 1 + .../java/com/leonardobishop/quests/Quests.java | 6 +- .../quests/api/QuestsPlaceholders.java | 518 +++++++++------------ src/main/resources/config.yml | 2 + src/main/resources/plugin.yml | 14 +- 14 files changed, 676 insertions(+), 502 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat delete mode 100644 pom.xml create mode 100644 settings.gradle diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..16a80b27 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,40 @@ +name: Build Plugin + +on: ["pull_request", "push"] + +jobs: + build: + strategy: + matrix: + java: ["1.8", "11"] + os: ["ubuntu-18.04"] + runs-on: "${{ matrix.os }}" + + steps: + - name: "Checkout Repository" + uses: "actions/checkout@v2.3.4" + - name: "Setup JDK ${{ matrix.java }}" + uses: "actions/setup-java@v1.4.3" + with: + java-version: "${{ matrix.java }}" + - name: Cache .gradle/caches + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + restore-keys: ${{ runner.os }}-gradle- + - name: Cache .gradle/wrapper + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-wrapper- + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build + - name: Upload Plugin + uses: actions/upload-artifact@master + with: + name: Quests-JDK${{ matrix.java }} + path: build/libs/*.jar \ No newline at end of file diff --git a/.gitignore b/.gitignore index cb4e1edc..d5cf5977 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -out/ +.gradle/ .idea/ -*.iml -.github/ -target/ -/bin/ -.classpath -.project -.settings/ \ No newline at end of file +build/ \ No newline at end of file diff --git a/README.md b/README.md index cba4c2aa..5c7aec7d 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,16 @@ This plugin will allow your players to do quests in-game to earn rewards. This c ## Downloads/Building The latest release version of Quests can be found on [Spigot](https://www.spigotmc.org/resources/▶-quests-◀-set-up-goals-for-players.23696/). +The latest build of Quests can be found on [Github](https://github.com/LMBishop/Quests/actions). -Alternatively, you can build Quests via Maven using ``mvn clean package``. +Alternatively, you can build Quests via Gradle using ``gradlew build``. -### Maven +### Custom Task Creating new Task Types within Quests is supported, [see the wiki](https://github.com/LMBishop/Quests/wiki/New-Task-Type) for help. -You can include quests in your Maven project using [JitPack](https://jitpack.io/#LMBishop/Quests): +You can include quests in your project using [JitPack](https://jitpack.io/#LMBishop/Quests) repository. + +### Maven ```xml jitpack.io @@ -30,6 +33,16 @@ You can include quests in your Maven project using [JitPack](https://jitpack.io/ ``` +### Gradle +```groovy +repositories { + maven { url = 'https://jitpack.io' } +} +dependencies { + compileOnly 'com.github.LMBishop:Quests:master-SNAPSHOT' +} +``` + ## Contributors See https://github.com/LMBishop/Quests/graphs/contributors diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..a9819cae --- /dev/null +++ b/build.gradle @@ -0,0 +1,80 @@ +plugins { + id 'java' +} + +group = 'com.leonardobishop.quests' +version = '2.11' + +processResources { + from(sourceSets.main.resources.srcDirs) { + include 'plugin.yml' + expand( + 'name': project.name, + 'main': project.group + '.' + project.name, + 'version': project.version + ) + } +} + +repositories { + // Spigot + maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } + // ASkyBlock + maven { + url 'http://dl.bintray.com/tastybento/maven-repo' + credentials { + username = 'bintray' + } + } + // BentoBox + maven { url = 'https://repo.codemc.org/repository/maven-public/' } + // uSkyBlock + maven { url = 'https://raw.github.com/rlf/uSkyBlock/mvn-repo/' } + // Citizens + maven { url = 'http://repo.citizensnpcs.co/' } + // MythicMobs + maven { url = 'https://mvn.lumine.io/repository/maven-public/' } + // PlaceholderAPI + maven { url = 'http://repo.extendedclip.com/content/repositories/placeholderapi/' } + // JitPack + maven { url = 'https://jitpack.io' } + mavenCentral() +} + +dependencies { + // Spigot + compileOnly ('org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT') { + exclude group: 'net.md-5', module: 'bungeecord-chat' + exclude group: 'com.google.guava', module: 'guava' + exclude group: 'org.yaml', module: 'snakeyaml' + } + // ASkyBlock + compileOnly ('com.wasteofplastic:askyblock:3.0.8.2') { + exclude group: 'net.milkbowl.vault', module: 'VaultAPI' + } + // BentoBox (bSkyBlock) + compileOnly ('world.bentobox:bentobox:1.15.5-SNAPSHOT') { + exclude group: 'org.eclipse.jdt', module: 'org.eclipse.jdt.annotation' + exclude group: 'org.mongodb', module: 'mongodb-driver' + } + // IridiumSkyblock + compileOnly 'com.github.IridiumLLC:IridiumSkyblock:master' + // uSkyBlock + compileOnly 'com.github.rlf:uSkyBlock-API:2.6.4' + // MythicMobs + compileOnly 'io.lumine.xikage:MythicMobs:4.11.0-BETA' + // Citizens + compileOnly ('net.citizensnpcs:citizens:2.0.27-SNAPSHOT') { + exclude group: 'net.citizensnpcs', module: 'citizens-main' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_8_R3' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_12_R1' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_13_R2' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_14_R1' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_15_R1' + exclude group: 'net.citizensnpcs', module: 'citizens-v1_16_R3' + } + // PlaceholderAPI + compileOnly 'me.clip:placeholderapi:2.10.9' + + compileOnly fileTree(dir: 'libs', includes: ['*.jar']) +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..f3d88b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..42ab3796 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat May 16 22:29:02 CST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..2fe81a7d --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..9618d8d9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 2ac88f45..00000000 --- a/pom.xml +++ /dev/null @@ -1,199 +0,0 @@ - - - 4.0.0 - - com.leonardobishop - quests - - 2.11 - Quests - - - ${project.version} - UTF-8 - target - - - - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - - - - bintray-tastybento-maven-repo - bintray - http://dl.bintray.com/tastybento/maven-repo - - - - - codemc-repo - https://repo.codemc.org/repository/maven-public/ - - - - - uSkyBlock-mvn-repo - https://raw.github.com/rlf/uSkyBlock/mvn-repo/ - - true - always - - - - - - everything - http://repo.citizensnpcs.co/ - - - - - mythicmobs - http://mc.hackerzlair.org:8888/repository/public - - - - - placeholderapi - http://repo.extendedclip.com/content/repositories/placeholderapi/ - - - - - jitpack.io - https://jitpack.io - - - - - - - org.spigotmc - spigot-api - 1.14.4-R0.1-SNAPSHOT - provided - - - - - com.wasteofplastic - askyblock - LATEST - provided - - - - - world.bentobox - bentobox - LATEST - provided - - - - - com.github.IridiumLLC - IridiumSkyblock - master - provided - - - - - com.github.rlf - uSkyBlock-API - 2.6.4 - provided - - - - - io.lumine.xikage - mythicmobs - 4.5.7 - jar - provided - - - - - net.citizensnpcs - citizens - 2.0.24-SNAPSHOT - jar - provided - - - - - me.clip - placeholderapi - 2.10.4 - jar - provided - - - - - quests - src/main/java - - - - ${basedir}/src/main/resources/ - false - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 8 - 8 - - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - replace - prepare-package - - - - - - - - - - run - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - ${maven.jar.outputDirectory} - - - - - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..b0609435 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'Quests' diff --git a/src/main/java/com/leonardobishop/quests/Quests.java b/src/main/java/com/leonardobishop/quests/Quests.java index ee22dcff..a957425c 100644 --- a/src/main/java/com/leonardobishop/quests/Quests.java +++ b/src/main/java/com/leonardobishop/quests/Quests.java @@ -22,6 +22,7 @@ import com.leonardobishop.quests.title.Title_Bukkit; import com.leonardobishop.quests.title.Title_BukkitNoTimings; import com.leonardobishop.quests.title.Title_Other; import com.leonardobishop.quests.updater.Updater; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -43,6 +44,7 @@ public class Quests extends JavaPlugin { private ItemGetter itemGetter; private QuestsConfigLoader questsConfigLoader; private QuestsLogger questsLogger; + private PlaceholderExpansion placeholder; private boolean brokenConfig = false; private BukkitTask questCompleterTask; @@ -112,7 +114,8 @@ public class Quests extends JavaPlugin { Bukkit.getPluginManager().registerEvents(new EventPlayerLeave(this), this); if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { - new QuestsPlaceholders(this).register(); + placeholder = new QuestsPlaceholders(this); + placeholder.register(); } Metrics metrics = new Metrics(this); @@ -202,6 +205,7 @@ public class Quests extends JavaPlugin { @Override public void onDisable() { + if (placeholder != null) placeholder.unregister(); for (TaskType taskType : getTaskTypeManager().getTaskTypes()) { try { taskType.onDisable(); diff --git a/src/main/java/com/leonardobishop/quests/api/QuestsPlaceholders.java b/src/main/java/com/leonardobishop/quests/api/QuestsPlaceholders.java index 8e8af093..e3d74c5c 100644 --- a/src/main/java/com/leonardobishop/quests/api/QuestsPlaceholders.java +++ b/src/main/java/com/leonardobishop/quests/api/QuestsPlaceholders.java @@ -4,25 +4,34 @@ import com.leonardobishop.quests.Quests; import com.leonardobishop.quests.api.enums.QuestStartResult; import com.leonardobishop.quests.obj.Options; import com.leonardobishop.quests.player.QPlayer; -import com.leonardobishop.quests.player.questprogressfile.QuestProgress; import com.leonardobishop.quests.player.questprogressfile.QuestProgressFile; import com.leonardobishop.quests.quests.Category; import com.leonardobishop.quests.quests.Quest; +import me.clip.placeholderapi.expansion.Cacheable; import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.concurrent.TimeUnit; -public class QuestsPlaceholders extends PlaceholderExpansion { +public class QuestsPlaceholders extends PlaceholderExpansion implements Cacheable { + private final Quests plugin; + private final Map> cache = new HashMap<>(); + private final Map formats = new HashMap<>(); public QuestsPlaceholders(Quests plugin) { this.plugin = plugin; } + @Override + public void clear() { + cache.clear(); + formats.clear(); + } + @Override public String getIdentifier() { return "quests"; @@ -30,12 +39,12 @@ public class QuestsPlaceholders extends PlaceholderExpansion { @Override public String getAuthor() { - return this.plugin.getDescription().getAuthors().toString(); + return plugin.getDescription().getAuthors().toString(); } @Override public String getVersion() { - return this.plugin.getDescription().getVersion(); + return plugin.getDescription().getVersion(); } @Override @@ -43,308 +52,245 @@ public class QuestsPlaceholders extends PlaceholderExpansion { return true; } - //TODO maybe cache these results for a bit? all these calls could be heavy - @Override public String onPlaceholderRequest(Player p, String params) { - if (p == null || !p.isOnline()) - return null; + if (p == null || !p.isOnline()) return null; + if (cache.containsKey(p) && cache.get(p).containsKey(params)) return cache.get(p).get(params); - String[] key = params.split("_", 5); - QPlayer questP = this.plugin.getPlayerManager().getPlayer(p.getUniqueId()); + String[] args = params.split("_", 4); + if (args.length < 1) return "Invalid Placeholder"; - if (key[0].equals("all") || key[0].equals("completed") || key[0].equals("completedBefore") - || key[0].equals("completedbefore") || key[0].equals("started") || key[0].equals("categories")) { - if (key.length == 1) { - switch (key[0]) { - case "all": - return String.valueOf(this.plugin.getQuestManager().getQuests().size()); - case "completed": - return String.valueOf(questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED).size()); - case "completedbefore": - case "completedBefore": - return String.valueOf(questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE).size()); - case "started": - return String.valueOf(questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.STARTED).size()); - case "categories": - return String.valueOf(this.plugin.getQuestManager().getCategories().size()); - } - } else if (key[1].equals("list") || key[1].equals("l")) { - String separator = ","; - if (!(key.length == 2)) { - separator = key[2]; - } + final boolean save = args[args.length-1].toLowerCase().equals("cache"); + if (save) args = Arrays.copyOf(args, args.length - 1); - switch (key[0]) { - case "all": - List listAll = new ArrayList<>(); - for (Quest q : this.plugin.getQuestManager().getQuests().values()) { - listAll.add(q.getDisplayNameStripped()); - } - return String.join(separator, listAll); - case "categories": - List listCategories = new ArrayList<>(); - for (Category c : this.plugin.getQuestManager().getCategories()) { - listCategories.add(c.getDisplayNameStripped()); - } - return String.join(separator, listCategories); - case "completed": - List listCompleted = new ArrayList<>(); - for (Quest qCompleted : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED)) { - listCompleted.add(qCompleted.getDisplayNameStripped()); - } - return String.join(separator, listCompleted); - case "completedbefore": - case "completedBefore": - List listCompletedBefore = new ArrayList<>(); - for (Quest qCompletedBefore : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE)) { - listCompletedBefore.add(qCompletedBefore.getDisplayNameStripped()); - } - return String.join(separator, listCompletedBefore); - case "started": - List listStarted = new ArrayList<>(); - for (Quest qStarted : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.STARTED)) { - listStarted.add(qStarted.getDisplayNameStripped()); - } - return String.join(separator, listStarted); - } - } else if (key[1].equals("listid") || key[1].equals("lid")) { - String separator = ","; - if (!(key.length == 2)) { - separator = key[2]; - } + final QPlayer qPlayer = plugin.getPlayerManager().getPlayer(p.getUniqueId()); + String split = args[args.length-1]; - switch (key[0]) { - case "all": - List listAll = new ArrayList<>(); - for (Quest q : this.plugin.getQuestManager().getQuests().values()) { - listAll.add(q.getId()); - } - return String.join(separator, listAll); - case "categories": - List listCategories = new ArrayList<>(); - for (Category c : this.plugin.getQuestManager().getCategories()) { - listCategories.add(c.getId()); - } - return String.join(separator, listCategories); - case "completed": - List listCompleted = new ArrayList<>(); - for (Quest qCompleted : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED)) { - listCompleted.add(qCompleted.getId()); - } - return String.join(separator, listCompleted); - case "completedbefore": - case "completedBefore": - List listCompletedBefore = new ArrayList<>(); - for (Quest qCompletedBefore : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE)) { - listCompletedBefore.add(qCompletedBefore.getId()); - } - return String.join(separator, listCompletedBefore); - case "started": - List listStarted = new ArrayList<>(); - for (Quest qStarted : questP.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.STARTED)) { - listStarted.add(qStarted.getId()); - } - return String.join(separator, listStarted); - } - } - return "null"; - } + String result = "null"; + if (!args[0].contains(":")) { + if (args.length > 1 && split.equals(args[1])) split = ","; - if (key[0].startsWith("quest:") || key[0].startsWith("q:")) { - Quest quest = this.plugin.getQuestManager().getQuestById(key[0].substring(key[0].lastIndexOf(":") + 1)); - if (key.length < 2) { - if (quest != null) { - return quest.getId(); - } else { - return "null"; - } - } else if (key[1].equals("started") || key[1].equals("s")) { - if (quest != null && questP.getQuestProgressFile().getQuestProgress(quest).isStarted()) { - return "true"; - } - return "false"; - } else if (key[1].equals("completed") || key[1].equals("c")) { - if (quest != null && questP.getQuestProgressFile().getQuestProgress(quest).isCompleted()) { - return "true"; - } - return "false"; - } else if (key[1].equals("completedbefore") || key[1].equals("completedBefore") || key[1].equals("cB")) { - if (quest != null && questP.getQuestProgressFile().getQuestProgress(quest).isCompletedBefore()) { - return "true"; - } - return "false"; - } else if (key[1].equals("completiondate") || key[1].equals("completionDate")) { - if (quest != null && questP.getQuestProgressFile().getQuestProgress(quest).isCompleted()) { - SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); //TODO make configurable for all our american friends - return sdf.format(questP.getQuestProgressFile().getQuestProgress(quest).getCompletionDate()); - } - return "Never"; - } else if (key[1].equals("cooldown")) { - if (quest != null && questP.getQuestProgressFile().getQuestProgress(quest).isCompleted()) { - String time = this.plugin.convertToFormat(TimeUnit.SECONDS.convert(questP.getQuestProgressFile().getCooldownFor(quest), TimeUnit.MILLISECONDS)); - if (time.startsWith("-")) { - return "0"; - } - return time; - } - return "0"; - } else if (key[1].equals("canaccept") || key[1].equals("canAccept")) { - if (quest != null && questP.getQuestProgressFile().canStartQuest(quest) == QuestStartResult.QUEST_SUCCESS) { - return "true"; - } - return "false"; - } else if (key[1].equals("meetsrequirements") || key[1].equals("meetsRequirements")) { - if (quest != null && questP.getQuestProgressFile().hasMetRequirements(quest)) { - return "true"; - } - return "false"; - } else if (key[1].startsWith("task") || key[1].startsWith("t")) { - String[] t = key[1].split(":"); - if (key[2].equals("progress") || key[2].equals("p")) { - if (quest == null || questP.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).getProgress() == null) { - return "0"; - } - return String.valueOf(questP.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).getProgress()); - } else if (key[2].equals("completed") || key[2].equals("c")) { - if (quest == null || questP.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).isCompleted()) { - return "true"; + switch (args[0].toLowerCase()) { + case "all": + case "a": + final Collection listAll = plugin.getQuestManager().getQuests().values(); + result = (args.length == 1 ? String.valueOf(listAll.size()) : parseList((List) listAll, args[1], split)); + break; + case "completed": + case "c": + final List listCompleted = qPlayer.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED); + result = (args.length == 1 ? String.valueOf(listCompleted.size()) : parseList(listCompleted, args[1], split)); + break; + case "completedbefore": + case "cb": + final List listCompletedB = qPlayer.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE); + result = (args.length == 1 ? String.valueOf(listCompletedB.size()) : parseList(listCompletedB, args[1], split)); + break; + case "started": + case "s": + final List listStarted = qPlayer.getQuestProgressFile().getAllQuestsFromProgress(QuestProgressFile.QuestsProgressFilter.STARTED); + result = (args.length == 1 ? String.valueOf(listStarted.size()) : parseList(listStarted, args[1], split)); + break; + case "categories": + if (args.length == 1) { + result = String.valueOf(plugin.getQuestManager().getCategories().size()); + } else { + final List listCategories = new ArrayList<>(); + switch (args[1].toLowerCase()) { + case "list": + case "l": + plugin.getQuestManager().getCategories().forEach(c -> listCategories.add(c.getDisplayNameStripped())); + break; + case "listid": + case "lid": + plugin.getQuestManager().getCategories().forEach(c -> listCategories.add(c.getId())); + break; + default: + return args[0] + "_" + args[1] + "is not a valid placeholder"; + } + result = String.join(split, listCategories); } - return "false"; - } + break; + default: + return args[0] + "is not a valid placeholder"; } + } else { + final String[] key = args[0].split(":"); + switch (key[0].toLowerCase()) { + case "quest": + case "q": + if (key.length == 1) return "Please specify quest name"; - return "null"; - } + final Quest quest = plugin.getQuestManager().getQuestById(key[1]); + if (quest == null) return key[1] + "is not a quest"; - if (key[0].startsWith("category:") || key[0].startsWith("c:")) { - if (!Options.CATEGORIES_ENABLED.getBooleanValue()) { - return "Categories Disabled"; - } - Category category = this.plugin.getQuestManager().getCategoryById(key[0].substring(key[0].lastIndexOf(":") + 1)); - if (key.length < 2) { - if (category != null) { - return category.getId(); - } else { - return "null"; - } - } else if (key.length == 2) { - switch (key[1]) { - case "all": - case "a": - return String.valueOf(category.getRegisteredQuestIds().size()); - case "completed": - case "c": - return String.valueOf(getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED).size()); - case "completedbefore": - case "completedBefore": - case "cB": - return String.valueOf(getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE).size()); - case "started": - case "s": - return String.valueOf(getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.STARTED).size()); - } - } else if (key[2].equals("list") || key[2].equals("l")) { - String separator = ","; - if (!(key.length == 3)) { - separator = key[3]; - } + if (args.length == 1) { + result = quest.getId(); + } else { + switch (args[1].toLowerCase()) { + case "started": + case "s": + result = (qPlayer.getQuestProgressFile().getQuestProgress(quest).isStarted() ? "true" : "false"); + break; + case "completed": + case "c": + result = (qPlayer.getQuestProgressFile().getQuestProgress(quest).isCompleted() ? "true" : "false"); + break; + case "completedbefore": + case "cb": + result = (qPlayer.getQuestProgressFile().getQuestProgress(quest).isCompletedBefore() ? "true" : "false"); + break; + case "completiondate": + case "cd": + if (qPlayer.getQuestProgressFile().getQuestProgress(quest).isCompleted()) { + result = parseDate(args, qPlayer.getQuestProgressFile().getQuestProgress(quest).getCompletionDate()); + } else { + result = "Never"; + } + break; + case "cooldown": + if (qPlayer.getQuestProgressFile().getQuestProgress(quest).isCompleted()) { + final String time = plugin.convertToFormat(TimeUnit.SECONDS.convert(qPlayer.getQuestProgressFile().getCooldownFor(quest), TimeUnit.MILLISECONDS)); + if (!time.startsWith("-")) result = time; + } else { + result = "0"; + } + break; + case "canaccept": + result = (qPlayer.getQuestProgressFile().canStartQuest(quest) == QuestStartResult.QUEST_SUCCESS ? "true" : "false"); + break; + case "meetsrequirements": + result = (qPlayer.getQuestProgressFile().hasMetRequirements(quest) ? "true" : "false"); + break; + default: + if (!args[1].contains(":")) return args[0] + "_" + args[1] + "is not a valid placeholder"; - switch (key[1]) { - case "all": - case "a": - List listAll = new ArrayList<>(); - for (Quest qCompleted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.ALL)) { - listAll.add(qCompleted.getDisplayNameStripped()); - } - return String.join(separator, listAll); - case "completed": - case "c": - List listCompleted = new ArrayList<>(); - for (Quest qCompleted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED)) { - listCompleted.add(qCompleted.getDisplayNameStripped()); - } - return String.join(separator, listCompleted); - case "completedbefore": - case "completedBefore": - case "cB": - List listCompletedBefore = new ArrayList<>(); - for (Quest qCompletedBefore : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE)) { - listCompletedBefore.add(qCompletedBefore.getDisplayNameStripped()); - } - return String.join(separator, listCompletedBefore); - case "started": - case "s": - List listStarted = new ArrayList<>(); - for (Quest qStarted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.STARTED)) { - listStarted.add(qStarted.getDisplayNameStripped()); - } - return String.join(separator, listStarted); - } - } else if (key[2].equals("listid") || key[2].equals("lid")) { - String separator = ","; - if (!(key.length == 3)) { - separator = key[3]; - } + final String[] t = args[1].split(":"); + if (!t[0].toLowerCase().equals("task") && !t[0].toLowerCase().equals("t")) return args[0] + "_" + args[1] + "is not a valid placeholder"; + if (t.length == 1) return "Please specify task name"; - switch (key[1]) { - case "all": - case "a": - List listAll = new ArrayList<>(); - for (Quest qCompleted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.ALL)) { - listAll.add(qCompleted.getId()); - } - return String.join(separator, listAll); - case "completed": - case "c": - List listCompleted = new ArrayList<>(); - for (Quest qCompleted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED)) { - listCompleted.add(qCompleted.getId()); + if (args.length == 2) { + result = qPlayer.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).getTaskId(); + } else { + switch (args[2].toLowerCase()) { + case "progress": + case "p": + final Object progress = qPlayer.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).getProgress(); + result = (progress == null ? "0" : String.valueOf(progress)); + break; + case "completed": + case "c": + result = String.valueOf(qPlayer.getQuestProgressFile().getQuestProgress(quest).getTaskProgress(t[1]).isCompleted()); + break; + default: + return args[0] + "_" + args[1] + "_" + args[2] + "is not a valid placeholder"; + } + } } - return String.join(separator, listCompleted); - case "completedbefore": - case "completedBefore": - case "cB": - List listCompletedBefore = new ArrayList<>(); - for (Quest qCompletedBefore : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE)) { - listCompletedBefore.add(qCompletedBefore.getId()); - } - return String.join(separator, listCompletedBefore); - case "started": - case "s": - List listStarted = new ArrayList<>(); - for (Quest qStarted : getCategoryQuests(questP, category, QuestProgressFile.QuestsProgressFilter.STARTED)) { - listStarted.add(qStarted.getId()); + } + break; + case "category": + case "c": + if (!Options.CATEGORIES_ENABLED.getBooleanValue()) return "Categories Disabled"; + if (key.length == 1) return "Please specify category name"; + + final Category category = plugin.getQuestManager().getCategoryById(key[1]); + if (category == null) return key[1] + "is not a category"; + + if (args.length == 1) { + result = category.getId(); + } else { + if (args.length > 2 && split.equals(args[2])) split = ","; + switch (args[1].toLowerCase()) { + case "all": + case "a": + final List listAll = getCategoryQuests(qPlayer, category, QuestProgressFile.QuestsProgressFilter.ALL); + result = (key.length == 2 ? String.valueOf(listAll.size()) : parseList(listAll, args[2], split)); + break; + case "completed": + case "c": + final List listCompleted = getCategoryQuests(qPlayer, category, QuestProgressFile.QuestsProgressFilter.COMPLETED); + result = (key.length == 2 ? String.valueOf(listCompleted.size()) : parseList(listCompleted, args[2], split)); + break; + case "completedbefore": + case "cb": + final List listCompletedB = getCategoryQuests(qPlayer, category, QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE); + result = (key.length == 2 ? String.valueOf(listCompletedB.size()) : parseList(listCompletedB, args[2], split)); + break; + case "started": + case "s": + final List listStarted = getCategoryQuests(qPlayer, category, QuestProgressFile.QuestsProgressFilter.STARTED); + result = (key.length == 2 ? String.valueOf(listStarted.size()) : parseList(listStarted, args[2], split)); + break; + default: + return args[0] + "_" + args[1] + "is not a valid placeholder"; } - return String.join(separator, listStarted); - } + } + break; + default: + return args[0] + "is not a valid placeholder"; } - return "null"; } - return null; + return (save ? cache(p, params, result) : result); } - private List getCategoryQuests(QPlayer questP, Category category, QuestProgressFile.QuestsProgressFilter filter) { - List categoryQuests = new ArrayList<>(); - for (String cQuests : category.getRegisteredQuestIds()) { - Quest quest = plugin.getQuestManager().getQuestById(cQuests); - if (quest == null) continue; + private String cache(Player player, String params, String result) { + final Map map = new HashMap<>(); + map.put(String.join("_", params), result); + cache.put(player, map); + Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> cache.remove(player), plugin.getConfig().getInt("options.placeholder-cache-time", 10) * 20); + return result; + } - boolean condition = false; - if (filter == QuestProgressFile.QuestsProgressFilter.STARTED) { - condition = questP.getQuestProgressFile().getQuestProgress(quest).isStarted(); - } else if (filter == QuestProgressFile.QuestsProgressFilter.COMPLETED_BEFORE) { - condition = questP.getQuestProgressFile().getQuestProgress(quest).isCompletedBefore(); - } else if (filter == QuestProgressFile.QuestsProgressFilter.COMPLETED) { - condition = questP.getQuestProgressFile().getQuestProgress(quest).isCompleted(); - } else if (filter == QuestProgressFile.QuestsProgressFilter.ALL) { - condition = true; - } + private String parseDate(String[] args, Long date) { + final String format = (args[args.length-1].equals(args[1]) ? "dd/MM/yyyy" : args[args.length-1]); + SimpleDateFormat sdf; + if (formats.containsKey(format)) { + sdf = formats.get(format); + } else { + sdf = new SimpleDateFormat(format); + formats.put(format, sdf); + } + return sdf.format(date); + } - if (condition) { - categoryQuests.add(quest); - } + private String parseList(List list, String type, String separator) { + final List quests = new ArrayList<>(); + switch (type.toLowerCase()) { + case "list": + case "l": + list.forEach(q -> quests.add(q.getDisplayNameStripped())); + break; + case "listid": + case "lid": + list.forEach(q -> quests.add(q.getId())); + break; + default: + return type + "is not a valid placeholder"; } + return String.join(separator, quests); + } + + private List getCategoryQuests(QPlayer questP, Category category, QuestProgressFile.QuestsProgressFilter filter) { + final List categoryQuests = new ArrayList<>(); + category.getRegisteredQuestIds().forEach(q -> { + Quest quest = plugin.getQuestManager().getQuestById(q); + if (quest != null) { + switch (filter) { + case STARTED: + if (questP.getQuestProgressFile().getQuestProgress(quest).isStarted()) categoryQuests.add(quest); + break; + case COMPLETED: + if (questP.getQuestProgressFile().getQuestProgress(quest).isCompleted()) categoryQuests.add(quest); + break; + case COMPLETED_BEFORE: + if (questP.getQuestProgressFile().getQuestProgress(quest).isCompletedBefore()) categoryQuests.add(quest); + break; + default: + categoryQuests.add(quest); + } + } + }); return categoryQuests; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 21a7ec83..bee451fa 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -170,6 +170,8 @@ options: # Allow quests to be loaded if they contain errors # This may lead to errors in the console! override-errors: false + # How many time (in seconds) plugin save placeholders + placeholder-cache-time: 10 # This switches up the entire quest system. # By enabling daily-quests, players will no longer be presented with the standard Quest GUI. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 9a96f719..f49e6360 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,11 +1,15 @@ -name: Quests +# This will be replaced with the property "rootProject.name" in settings.gradle +name: ${name} -# This will be replaced with the property "release.version" in pom.xml upon build. -version: %PLUGIN_VERSION% +# This will be replaced with the property "version" in build.gradle +version: ${version} + +# This will be replaced with the property "group" in build.gradle + plugin name +# See "processResources" in build.gradle for more info +main: ${main} -main: com.leonardobishop.quests.Quests author: LMBishop -softdepend: [ASkyBlock, uSkyBlock, Citizens, PlaceholderAPI] +softdepend: [ASkyBlock, BentoBox, IridiumSkyblock, uSkyBlock, Citizens, MythicMobs, PlaceholderAPI] prefix: Quests api-version: "1.13" # allows new API features but Quests will still work pre-1.13 -- cgit v1.2.3-70-g09d2