diff --git a/.gitattributes b/.gitattributes index 412eeda7..00a51aff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,22 +1,6 @@ -# Auto detect text files and perform LF normalization -* text=auto +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index bde8e30c..e74b5fed 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,12 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build +/MCCore.jar +/Spigot.jar +/spigot-api-1.16.1-R0.1-SNAPSHOT-shaded.jar diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..d1e8bbd5 --- /dev/null +++ b/build.gradle @@ -0,0 +1,43 @@ +plugins { + id 'java' + id 'eclipse' +} + +configurations.compileClasspath { + exclude group: 'org.spigotmc', module: 'spigot' + exclude group: 'org.spigotmc', module: 'spigot-api' + exclude group: 'org.bukkit', module: 'bukkit' +} + +repositories { + // NMS Paper Repo + maven { url = 'https://repo.codemc.io/repository/nms-local/' } + + // Hooks repos + maven { url = 'https://jitpack.io' } + maven { url = 'https://maven.enginehub.org/repo/' } + maven { url = 'https://repo.dmulloy2.net/repository/public/' } + maven { url = 'https://repo.md-5.net/content/groups/public/' } + maven { url = 'https://mvn.lumine.io/repository/maven-public/' } + maven { url = 'https://papermc.io/repo/repository/maven-public/' } + maven { url = 'https://repo.md-5.net/content/repositories/releases/' } + maven { url = 'https://repo.md-5.net/content/repositories/snapshots/' } + maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' } + maven { url = 'https://repo.codemc.org/repository/maven-public/' } + +} + +dependencies { + compileOnly 'io.papermc.paper:paper:1.17.1-R0.1-SNAPSHOT' + + // Hooks + compileOnly 'io.github.waterfallmc:waterfall-api:1.17-R0.1-SNAPSHOT' + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.0' + compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.0.0' + compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT' + compileOnly fileTree(dir: 'libs', include: '*.jar') + compileOnly 'LibsDisguises:LibsDisguises:10.0.21' + compileOnly 'com.github.MilkBowl:VaultAPI:1.7' + compileOnly 'me.clip:placeholderapi:2.10.9' + compileOnly 'de.tr7zw:item-nbt-api-plugin:2.6.0' +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..7454180f 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..69a97150 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..744e882e --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/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 + ;; + MSYS* | 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..107acd32 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@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 Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@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 execute + +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 execute + +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 + +: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 %* + +: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/modules/SkillAPIModule.jar b/legacy/SkillAPIModule.jar similarity index 100% rename from modules/SkillAPIModule.jar rename to legacy/SkillAPIModule.jar diff --git a/modules/SkillAPIPlaceholders.jar b/legacy/SkillAPIPlaceholders.jar similarity index 100% rename from modules/SkillAPIPlaceholders.jar rename to legacy/SkillAPIPlaceholders.jar diff --git a/legacy/files/META-INF/MANIFEST.MF b/legacy/files/META-INF/MANIFEST.MF new file mode 100644 index 00000000..fa5c41b8 --- /dev/null +++ b/legacy/files/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.sucy.skill.SkillAPI + diff --git a/editor/builderStyle.css b/legacy/files/editor/builderStyle.css similarity index 100% rename from editor/builderStyle.css rename to legacy/files/editor/builderStyle.css diff --git a/editor/img/delete.png b/legacy/files/editor/img/delete.png similarity index 100% rename from editor/img/delete.png rename to legacy/files/editor/img/delete.png diff --git a/editor/img/duplicate.png b/legacy/files/editor/img/duplicate.png similarity index 100% rename from editor/img/duplicate.png rename to legacy/files/editor/img/duplicate.png diff --git a/editor/img/eye.png b/legacy/files/editor/img/eye.png similarity index 100% rename from editor/img/eye.png rename to legacy/files/editor/img/eye.png diff --git a/editor/img/eyeShaded.png b/legacy/files/editor/img/eyeShaded.png similarity index 100% rename from editor/img/eyeShaded.png rename to legacy/files/editor/img/eyeShaded.png diff --git a/editor/js/class.js b/legacy/files/editor/js/class.js similarity index 100% rename from editor/js/class.js rename to legacy/files/editor/js/class.js diff --git a/editor/js/component.js b/legacy/files/editor/js/component.js similarity index 100% rename from editor/js/component.js rename to legacy/files/editor/js/component.js diff --git a/editor/js/filter.js b/legacy/files/editor/js/filter.js similarity index 100% rename from editor/js/filter.js rename to legacy/files/editor/js/filter.js diff --git a/editor/js/input.js b/legacy/files/editor/js/input.js similarity index 100% rename from editor/js/input.js rename to legacy/files/editor/js/input.js diff --git a/editor/js/loader.js b/legacy/files/editor/js/loader.js similarity index 100% rename from editor/js/loader.js rename to legacy/files/editor/js/loader.js diff --git a/editor/js/main.js b/legacy/files/editor/js/main.js similarity index 100% rename from editor/js/main.js rename to legacy/files/editor/js/main.js diff --git a/editor/js/material.js b/legacy/files/editor/js/material.js similarity index 100% rename from editor/js/material.js rename to legacy/files/editor/js/material.js diff --git a/editor/js/skill.js b/legacy/files/editor/js/skill.js similarity index 100% rename from editor/js/skill.js rename to legacy/files/editor/js/skill.js diff --git a/editor/js/sounds.js b/legacy/files/editor/js/sounds.js similarity index 100% rename from editor/js/sounds.js rename to legacy/files/editor/js/sounds.js diff --git a/editor/js/yaml.js b/legacy/files/editor/js/yaml.js similarity index 100% rename from editor/js/yaml.js rename to legacy/files/editor/js/yaml.js diff --git a/editor/mojave-webfont.eot b/legacy/files/editor/mojave-webfont.eot similarity index 100% rename from editor/mojave-webfont.eot rename to legacy/files/editor/mojave-webfont.eot diff --git a/editor/mojave-webfont.ttf b/legacy/files/editor/mojave-webfont.ttf similarity index 100% rename from editor/mojave-webfont.ttf rename to legacy/files/editor/mojave-webfont.ttf diff --git a/editor/sertig-webfont.eot b/legacy/files/editor/sertig-webfont.eot similarity index 100% rename from editor/sertig-webfont.eot rename to legacy/files/editor/sertig-webfont.eot diff --git a/editor/sertig-webfont.ttf b/legacy/files/editor/sertig-webfont.ttf similarity index 100% rename from editor/sertig-webfont.ttf rename to legacy/files/editor/sertig-webfont.ttf diff --git a/editor/ss/additions.png b/legacy/files/editor/ss/additions.png similarity index 100% rename from editor/ss/additions.png rename to legacy/files/editor/ss/additions.png diff --git a/editor/ss/binaryListOption.png b/legacy/files/editor/ss/binaryListOption.png similarity index 100% rename from editor/ss/binaryListOption.png rename to legacy/files/editor/ss/binaryListOption.png diff --git a/editor/ss/booleanOption.png b/legacy/files/editor/ss/booleanOption.png similarity index 100% rename from editor/ss/booleanOption.png rename to legacy/files/editor/ss/booleanOption.png diff --git a/editor/ss/castBars.png b/legacy/files/editor/ss/castBars.png similarity index 100% rename from editor/ss/castBars.png rename to legacy/files/editor/ss/castBars.png diff --git a/editor/ss/castBook.png b/legacy/files/editor/ss/castBook.png similarity index 100% rename from editor/ss/castBook.png rename to legacy/files/editor/ss/castBook.png diff --git a/editor/ss/castItem.png b/legacy/files/editor/ss/castItem.png similarity index 100% rename from editor/ss/castItem.png rename to legacy/files/editor/ss/castItem.png diff --git a/editor/ss/classFolder.png b/legacy/files/editor/ss/classFolder.png similarity index 100% rename from editor/ss/classFolder.png rename to legacy/files/editor/ss/classFolder.png diff --git a/editor/ss/classSave.png b/legacy/files/editor/ss/classSave.png similarity index 100% rename from editor/ss/classSave.png rename to legacy/files/editor/ss/classSave.png diff --git a/editor/ss/compatible.png b/legacy/files/editor/ss/compatible.png similarity index 100% rename from editor/ss/compatible.png rename to legacy/files/editor/ss/compatible.png diff --git a/editor/ss/dependencies.png b/legacy/files/editor/ss/dependencies.png similarity index 100% rename from editor/ss/dependencies.png rename to legacy/files/editor/ss/dependencies.png diff --git a/editor/ss/donate.png b/legacy/files/editor/ss/donate.png similarity index 100% rename from editor/ss/donate.png rename to legacy/files/editor/ss/donate.png diff --git a/editor/ss/dragAndDrop.png b/legacy/files/editor/ss/dragAndDrop.png similarity index 100% rename from editor/ss/dragAndDrop.png rename to legacy/files/editor/ss/dragAndDrop.png diff --git a/editor/ss/dropdownOption.png b/legacy/files/editor/ss/dropdownOption.png similarity index 100% rename from editor/ss/dropdownOption.png rename to legacy/files/editor/ss/dropdownOption.png diff --git a/editor/ss/dynamicFolder.png b/legacy/files/editor/ss/dynamicFolder.png similarity index 100% rename from editor/ss/dynamicFolder.png rename to legacy/files/editor/ss/dynamicFolder.png diff --git a/editor/ss/extensions.png b/legacy/files/editor/ss/extensions.png similarity index 100% rename from editor/ss/extensions.png rename to legacy/files/editor/ss/extensions.png diff --git a/editor/ss/fair.png b/legacy/files/editor/ss/fair.png similarity index 100% rename from editor/ss/fair.png rename to legacy/files/editor/ss/fair.png diff --git a/editor/ss/flagChannel.png b/legacy/files/editor/ss/flagChannel.png similarity index 100% rename from editor/ss/flagChannel.png rename to legacy/files/editor/ss/flagChannel.png diff --git a/editor/ss/flagTargets.png b/legacy/files/editor/ss/flagTargets.png similarity index 100% rename from editor/ss/flagTargets.png rename to legacy/files/editor/ss/flagTargets.png diff --git a/editor/ss/flagTemp.png b/legacy/files/editor/ss/flagTemp.png similarity index 100% rename from editor/ss/flagTemp.png rename to legacy/files/editor/ss/flagTemp.png diff --git a/editor/ss/flagToggle.png b/legacy/files/editor/ss/flagToggle.png similarity index 100% rename from editor/ss/flagToggle.png rename to legacy/files/editor/ss/flagToggle.png diff --git a/editor/ss/free.png b/legacy/files/editor/ss/free.png similarity index 100% rename from editor/ss/free.png rename to legacy/files/editor/ss/free.png diff --git a/editor/ss/guiEditor.png b/legacy/files/editor/ss/guiEditor.png similarity index 100% rename from editor/ss/guiEditor.png rename to legacy/files/editor/ss/guiEditor.png diff --git a/editor/ss/integerOption.png b/legacy/files/editor/ss/integerOption.png similarity index 100% rename from editor/ss/integerOption.png rename to legacy/files/editor/ss/integerOption.png diff --git a/editor/ss/loadingFiles.png b/legacy/files/editor/ss/loadingFiles.png similarity index 100% rename from editor/ss/loadingFiles.png rename to legacy/files/editor/ss/loadingFiles.png diff --git a/editor/ss/overview.png b/legacy/files/editor/ss/overview.png similarity index 100% rename from editor/ss/overview.png rename to legacy/files/editor/ss/overview.png diff --git a/editor/ss/premium.png b/legacy/files/editor/ss/premium.png similarity index 100% rename from editor/ss/premium.png rename to legacy/files/editor/ss/premium.png diff --git a/editor/ss/saveAll.png b/legacy/files/editor/ss/saveAll.png similarity index 100% rename from editor/ss/saveAll.png rename to legacy/files/editor/ss/saveAll.png diff --git a/editor/ss/saveButton.png b/legacy/files/editor/ss/saveButton.png similarity index 100% rename from editor/ss/saveButton.png rename to legacy/files/editor/ss/saveButton.png diff --git a/editor/ss/scalingNumberOption.png b/legacy/files/editor/ss/scalingNumberOption.png similarity index 100% rename from editor/ss/scalingNumberOption.png rename to legacy/files/editor/ss/scalingNumberOption.png diff --git a/editor/ss/scalingNumbers.png b/legacy/files/editor/ss/scalingNumbers.png similarity index 100% rename from editor/ss/scalingNumbers.png rename to legacy/files/editor/ss/scalingNumbers.png diff --git a/editor/ss/skillsFolder.png b/legacy/files/editor/ss/skillsFolder.png similarity index 100% rename from editor/ss/skillsFolder.png rename to legacy/files/editor/ss/skillsFolder.png diff --git a/editor/ss/stringOption.png b/legacy/files/editor/ss/stringOption.png similarity index 100% rename from editor/ss/stringOption.png rename to legacy/files/editor/ss/stringOption.png diff --git a/editor/ss/title.PNG b/legacy/files/editor/ss/title.PNG similarity index 100% rename from editor/ss/title.PNG rename to legacy/files/editor/ss/title.PNG diff --git a/editor/ss/titleWide.png b/legacy/files/editor/ss/titleWide.png similarity index 100% rename from editor/ss/titleWide.png rename to legacy/files/editor/ss/titleWide.png diff --git a/editor/ss/tooltip.png b/legacy/files/editor/ss/tooltip.png similarity index 100% rename from editor/ss/tooltip.png rename to legacy/files/editor/ss/tooltip.png diff --git a/editor/ss/value.png b/legacy/files/editor/ss/value.png similarity index 100% rename from editor/ss/value.png rename to legacy/files/editor/ss/value.png diff --git a/editor/ss/valueAdd.png b/legacy/files/editor/ss/valueAdd.png similarity index 100% rename from editor/ss/valueAdd.png rename to legacy/files/editor/ss/valueAdd.png diff --git a/editor/ss/valueRandom.png b/legacy/files/editor/ss/valueRandom.png similarity index 100% rename from editor/ss/valueRandom.png rename to legacy/files/editor/ss/valueRandom.png diff --git a/editor/ss/valueWave.png b/legacy/files/editor/ss/valueWave.png similarity index 100% rename from editor/ss/valueWave.png rename to legacy/files/editor/ss/valueWave.png diff --git a/editor/ss/wiki.png b/legacy/files/editor/ss/wiki.png similarity index 100% rename from editor/ss/wiki.png rename to legacy/files/editor/ss/wiki.png diff --git a/editor/style.css b/legacy/files/editor/style.css similarity index 100% rename from editor/style.css rename to legacy/files/editor/style.css diff --git a/editor/tooltips.css b/legacy/files/editor/tooltips.css similarity index 100% rename from editor/tooltips.css rename to legacy/files/editor/tooltips.css diff --git a/exp.html b/legacy/files/exp.html similarity index 100% rename from exp.html rename to legacy/files/exp.html diff --git a/index.html b/legacy/files/index.html similarity index 100% rename from index.html rename to legacy/files/index.html diff --git a/javadoc/data.js b/legacy/files/javadoc/data.js similarity index 100% rename from javadoc/data.js rename to legacy/files/javadoc/data.js diff --git a/javadoc/index.html b/legacy/files/javadoc/index.html similarity index 100% rename from javadoc/index.html rename to legacy/files/javadoc/index.html diff --git a/javadoc/nav.js b/legacy/files/javadoc/nav.js similarity index 100% rename from javadoc/nav.js rename to legacy/files/javadoc/nav.js diff --git a/javadoc/style.css b/legacy/files/javadoc/style.css similarity index 100% rename from javadoc/style.css rename to legacy/files/javadoc/style.css diff --git a/modules/hamcrest-core-1.3.jar b/legacy/hamcrest-core-1.3.jar similarity index 100% rename from modules/hamcrest-core-1.3.jar rename to legacy/hamcrest-core-1.3.jar diff --git a/modules/junit-4.12.jar b/legacy/junit-4.12.jar similarity index 100% rename from modules/junit-4.12.jar rename to legacy/junit-4.12.jar diff --git a/modules/mockito-core-1.10.19.jar b/legacy/mockito-core-1.10.19.jar similarity index 100% rename from modules/mockito-core-1.10.19.jar rename to legacy/mockito-core-1.10.19.jar diff --git a/modules/objenesis-2.4.jar b/legacy/objenesis-2.4.jar similarity index 100% rename from modules/objenesis-2.4.jar rename to legacy/objenesis-2.4.jar diff --git a/tst/com/sucy/skill/TestUtils.java b/legacy/tst/com/sucy/skill/TestUtils.java similarity index 100% rename from tst/com/sucy/skill/TestUtils.java rename to legacy/tst/com/sucy/skill/TestUtils.java diff --git a/tst/com/sucy/skill/api/util/BuffDataTest.java b/legacy/tst/com/sucy/skill/api/util/BuffDataTest.java similarity index 100% rename from tst/com/sucy/skill/api/util/BuffDataTest.java rename to legacy/tst/com/sucy/skill/api/util/BuffDataTest.java diff --git a/tst/com/sucy/skill/cmd/CmdExpTest.java b/legacy/tst/com/sucy/skill/cmd/CmdExpTest.java similarity index 100% rename from tst/com/sucy/skill/cmd/CmdExpTest.java rename to legacy/tst/com/sucy/skill/cmd/CmdExpTest.java diff --git a/tst/com/sucy/skill/dynamic/EffectComponentTest.java b/legacy/tst/com/sucy/skill/dynamic/EffectComponentTest.java similarity index 100% rename from tst/com/sucy/skill/dynamic/EffectComponentTest.java rename to legacy/tst/com/sucy/skill/dynamic/EffectComponentTest.java diff --git a/tst/com/sucy/skill/dynamic/ItemCheckerTest.java b/legacy/tst/com/sucy/skill/dynamic/ItemCheckerTest.java similarity index 92% rename from tst/com/sucy/skill/dynamic/ItemCheckerTest.java rename to legacy/tst/com/sucy/skill/dynamic/ItemCheckerTest.java index be7f536c..374238be 100644 --- a/tst/com/sucy/skill/dynamic/ItemCheckerTest.java +++ b/legacy/tst/com/sucy/skill/dynamic/ItemCheckerTest.java @@ -18,6 +18,5 @@ public void testLore() { final Pattern compiled = Pattern.compile(pattern); final Matcher matcher = compiled.matcher("Test prefix -123,456 and suffix"); Assert.assertEquals(matcher.find(), true); - System.out.println(matcher.group(1)); } } \ No newline at end of file diff --git a/tst/com/sucy/skill/listener/ItemListenerTest.java b/legacy/tst/com/sucy/skill/listener/ItemListenerTest.java similarity index 100% rename from tst/com/sucy/skill/listener/ItemListenerTest.java rename to legacy/tst/com/sucy/skill/listener/ItemListenerTest.java diff --git a/tst/com/sucy/skill/thread/TaskListTest.java b/legacy/tst/com/sucy/skill/thread/TaskListTest.java similarity index 100% rename from tst/com/sucy/skill/thread/TaskListTest.java rename to legacy/tst/com/sucy/skill/thread/TaskListTest.java diff --git a/tst/com/sucy/skill/util/FileReader.java b/legacy/tst/com/sucy/skill/util/FileReader.java similarity index 94% rename from tst/com/sucy/skill/util/FileReader.java rename to legacy/tst/com/sucy/skill/util/FileReader.java index c4c72e02..85ab2742 100644 --- a/tst/com/sucy/skill/util/FileReader.java +++ b/legacy/tst/com/sucy/skill/util/FileReader.java @@ -34,7 +34,7 @@ public static String readText(InputStream stream) throws Exception { try { stream.close(); } catch (final IOException ex) { - System.out.println("Failed to close stream"); + ex.printStackTrace(); } } } diff --git a/modules/MCCore.jar b/libs/MCCore.jar similarity index 100% rename from modules/MCCore.jar rename to libs/MCCore.jar diff --git a/modules/BungeeCord.jar b/libs/MythicMobs-5.0.3-SNAPSHOT.jar similarity index 52% rename from modules/BungeeCord.jar rename to libs/MythicMobs-5.0.3-SNAPSHOT.jar index c3b73809..4ba01372 100644 Binary files a/modules/BungeeCord.jar and b/libs/MythicMobs-5.0.3-SNAPSHOT.jar differ diff --git a/libs/NeoCore-0.0.1-SNAPSHOT.jar b/libs/NeoCore-0.0.1-SNAPSHOT.jar new file mode 100644 index 00000000..cad49fe5 Binary files /dev/null and b/libs/NeoCore-0.0.1-SNAPSHOT.jar differ diff --git a/modules/Parties.jar b/libs/Parties.jar similarity index 100% rename from modules/Parties.jar rename to libs/Parties.jar diff --git a/modules/RPGInventory.jar b/libs/RPGInventory.jar similarity index 100% rename from modules/RPGInventory.jar rename to libs/RPGInventory.jar diff --git a/libs/spigot-api-1.18.2-R0.1-SNAPSHOT-shaded.jar b/libs/spigot-api-1.18.2-R0.1-SNAPSHOT-shaded.jar new file mode 100644 index 00000000..cf8a33b3 Binary files /dev/null and b/libs/spigot-api-1.18.2-R0.1-SNAPSHOT-shaded.jar differ diff --git a/modules/LibsDisguises.jar b/modules/LibsDisguises.jar deleted file mode 100644 index a1cb8993..00000000 Binary files a/modules/LibsDisguises.jar and /dev/null differ diff --git a/modules/MythicMobs-4.2.0.jar b/modules/MythicMobs-4.2.0.jar deleted file mode 100644 index 70121bc6..00000000 Binary files a/modules/MythicMobs-4.2.0.jar and /dev/null differ diff --git a/modules/NoCheatPlus.jar b/modules/NoCheatPlus.jar deleted file mode 100644 index 52b84663..00000000 Binary files a/modules/NoCheatPlus.jar and /dev/null differ diff --git a/modules/PlaceholderAPI-2.8.2.jar b/modules/PlaceholderAPI-2.8.2.jar deleted file mode 100644 index 8f727228..00000000 Binary files a/modules/PlaceholderAPI-2.8.2.jar and /dev/null differ diff --git a/modules/ProtocolLib-3.3.1.jar b/modules/ProtocolLib-3.3.1.jar deleted file mode 100644 index 6c1df99d..00000000 Binary files a/modules/ProtocolLib-3.3.1.jar and /dev/null differ diff --git a/modules/Vault.jar b/modules/Vault.jar deleted file mode 100644 index 99dc6843..00000000 Binary files a/modules/Vault.jar and /dev/null differ diff --git a/modules/WorldEdit.jar b/modules/WorldEdit.jar deleted file mode 100644 index 101f5336..00000000 Binary files a/modules/WorldEdit.jar and /dev/null differ diff --git a/modules/WorldGuard.jar b/modules/WorldGuard.jar deleted file mode 100644 index e4821f00..00000000 Binary files a/modules/WorldGuard.jar and /dev/null differ diff --git a/modules/craftbukkit-1.13.jar b/modules/craftbukkit-1.13.jar deleted file mode 100644 index 96ef215c..00000000 Binary files a/modules/craftbukkit-1.13.jar and /dev/null differ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..bbab6498 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'SkillAPI' diff --git a/src/com/sucy/skill/api/particle/SpigotParticles.java b/src/com/sucy/skill/api/particle/SpigotParticles.java deleted file mode 100644 index 04119ceb..00000000 --- a/src/com/sucy/skill/api/particle/SpigotParticles.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.sucy.skill.api.particle; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; - -import java.util.Map; - -/** - * SkillAPI © 2018 - * com.sucy.skill.api.particle.SpigotParticles - */ -public class SpigotParticles { - private static boolean error = true; - - public static void play(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance) { - play(loc, particle, dx, dy, dz, count, speed, distance, null); - } - - public static void playItem(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { - play(loc, particle, dx, dy, dz, count, speed, distance, material); - } - - public static void playBlock(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { - play(loc, particle, dx, dy, dz, count, speed, distance, material); - } - - private static void play(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { - final String key = particle.toLowerCase().replace('_', ' '); - final Particle effect = CONVERSION.get(key); - if (effect == null) return; - - try { - final Object packet = com.sucy.skill.api.particle.Particle.make( - effect.name(), loc.getX(), loc.getY(), loc.getZ(), dx, dy, dz, speed, count, material, 0); - com.sucy.skill.api.particle.Particle.send(loc, ImmutableList.of(packet), distance); - } catch (final Exception ex) { - if (error) { - ex.printStackTrace(); - error = false; - } - } - } - - private static final Map CONVERSION = ImmutableMap.builder() - .put("angry villager", Particle.VILLAGER_ANGRY) - .put("barrier", Particle.BARRIER) - .put("block crack", Particle.BLOCK_CRACK) - .put("bubble", Particle.WATER_BUBBLE) - .put("cloud", Particle.CLOUD) - .put("crit", Particle.CRIT) - .put("damage indicator", Particle.DAMAGE_INDICATOR) - .put("death", Particle.SUSPENDED) - .put("death suspend", Particle.SUSPENDED_DEPTH) - .put("dragon breath", Particle.DRAGON_BREATH) - .put("drip lava", Particle.DRIP_LAVA) - .put("drip water", Particle.DRIP_WATER) - .put("enchantment table", Particle.ENCHANTMENT_TABLE) - .put("end rod", Particle.END_ROD) - .put("ender signal", Particle.PORTAL) - .put("explode", Particle.EXPLOSION_NORMAL) - .put("firework spark", Particle.FIREWORKS_SPARK) - .put("flame", Particle.FLAME) - .put("footstep", Particle.CLOUD) - .put("happy villager", Particle.VILLAGER_HAPPY) - .put("heart", Particle.HEART) - .put("huge explosion", Particle.EXPLOSION_HUGE) - .put("hurt", Particle.DAMAGE_INDICATOR) - .put("icon crack", Particle.ITEM_CRACK) - .put("instant spell", Particle.SPELL_INSTANT) - .put("large explode", Particle.EXPLOSION_LARGE) - .put("large smoke", Particle.SMOKE_LARGE) - .put("lava", Particle.LAVA) - .put("magic crit", Particle.CRIT_MAGIC) - .put("mob spell", Particle.SPELL_MOB) - .put("mob spell ambient", Particle.SPELL_MOB_AMBIENT) - .put("mobspawner flames", Particle.FLAME) - .put("note", Particle.NOTE) - .put("portal", Particle.PORTAL) - .put("potion break", Particle.SPELL) - .put("red dust", Particle.REDSTONE) - .put("sheep eat", Particle.MOB_APPEARANCE) - .put("slime", Particle.SLIME) - .put("smoke", Particle.SMOKE_NORMAL) - .put("snowball poof", Particle.SNOWBALL) - .put("snow shovel", Particle.SNOW_SHOVEL) - .put("spell", Particle.SPELL) - .put("splash", Particle.WATER_SPLASH) - .put("sweep attack", Particle.SWEEP_ATTACK) - .put("suspend", Particle.SUSPENDED) - .put("town aura", Particle.TOWN_AURA) - .put("water drop", Particle.WATER_DROP) - .put("water wake", Particle.WATER_WAKE) - .put("witch magic", Particle.SPELL_WITCH) - .put("wolf hearts", Particle.HEART) - .build(); -} diff --git a/src/com/sucy/skill/api/player/PlayerData.java b/src/com/sucy/skill/api/player/PlayerData.java deleted file mode 100644 index 42fbb7b5..00000000 --- a/src/com/sucy/skill/api/player/PlayerData.java +++ /dev/null @@ -1,1894 +0,0 @@ -/** - * SkillAPI - * com.sucy.skill.api.player.PlayerData - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.api.player; - -import com.rit.sucy.config.Filter; -import com.rit.sucy.config.FilterType; -import com.rit.sucy.config.parse.DataSection; -import com.rit.sucy.player.TargetHelper; -import com.rit.sucy.version.VersionManager; -import com.rit.sucy.version.VersionPlayer; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.enums.*; -import com.sucy.skill.api.event.*; -import com.sucy.skill.api.skills.PassiveSkill; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.api.skills.SkillShot; -import com.sucy.skill.api.skills.TargetSkill; -import com.sucy.skill.cast.PlayerCastBars; -import com.sucy.skill.data.GroupSettings; -import com.sucy.skill.data.PlayerEquips; -import com.sucy.skill.dynamic.EffectComponent; -import com.sucy.skill.gui.handlers.AttributeHandler; -import com.sucy.skill.gui.handlers.DetailsHandler; -import com.sucy.skill.gui.handlers.ProfessHandler; -import com.sucy.skill.gui.handlers.SkillHandler; -import com.sucy.skill.gui.tool.GUITool; -import com.sucy.skill.language.ErrorNodes; -import com.sucy.skill.language.GUINodes; -import com.sucy.skill.language.RPGFilter; -import com.sucy.skill.listener.AttributeListener; -import com.sucy.skill.log.LogType; -import com.sucy.skill.log.Logger; -import com.sucy.skill.manager.AttributeManager; -import com.sucy.skill.task.ScoreboardTask; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeInstance; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -import java.util.*; - -import static com.sucy.skill.api.event.PlayerSkillCastFailedEvent.Cause.*; - -/** - * Represents one account for a player which can contain one class from each group - * and the skills in each of those classes. You should not instantiate this class - * yourself and instead get it from the SkillAPI static methods. - * - * In order to get a player's data, use "SkillAPI.getPlayerData(...)". Do NOT - * try to instantaite your own PlayerData object. - */ -public class PlayerData { - private final HashMap classes = new HashMap<>(); - private final HashMap skills = new HashMap<>(); - private final HashMap binds = new HashMap<>(); - private final HashMap attributes = new HashMap<>(); - private final HashMap bonusAttrib = new HashMap<>(); - - private DataSection extraData = new DataSection(); - private OfflinePlayer player; - private PlayerSkillBar skillBar; - private PlayerCastBars castBars; - private PlayerCombos combos; - private PlayerEquips equips; - private String scheme; - private String menuClass; - private double mana; - private double maxMana; - private double bonusHealth; - private double bonusMana; - private double lastHealth; - private double hunger; - private boolean init; - private boolean passive; - private int attribPoints; - private long skillTimer; - - /** - * Initializes a new account data representation for a player. - * - * @param player player to store the data for - */ - PlayerData(OfflinePlayer player, boolean init) { - this.player = player; - this.skillBar = new PlayerSkillBar(this); - this.castBars = new PlayerCastBars(this); - this.combos = new PlayerCombos(this); - this.equips = new PlayerEquips(this); - this.init = SkillAPI.isLoaded() && init; - this.scheme = "default"; - this.hunger = 1; - for (String group : SkillAPI.getGroups()) { - GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); - RPGClass rpgClass = settings.getDefault(); - - if (rpgClass != null && settings.getPermission() == null) { - setClass(rpgClass); - } - } - } - - /** - * Retrieves the Bukkit player object of the owner - * - * @return Bukkit player object of the owner or null if offline - */ - public Player getPlayer() { - return new VersionPlayer(player).getPlayer(); - } - - /** - * Retrieves the name of the owner - * - * @return name of the owner - */ - public String getPlayerName() { - return player.getName(); - } - - public UUID getUUID() { - return player.getUniqueId(); - } - - /** - * Retrieves the skill bar data for the owner - * - * @return skill bar data of the owner - */ - public PlayerSkillBar getSkillBar() { - return skillBar; - } - - /** - * @return cast bars data for the player - */ - public PlayerCastBars getCastBars() { - return castBars; - } - - /** - * Returns the data for the player's combos - * - * @return combo data for the player - */ - public PlayerCombos getComboData() { - return combos; - } - - /** - * @return extra data attached to the player's account - */ - public DataSection getExtraData() { - return extraData; - } - - /** - * @return equipped item data - */ - public PlayerEquips getEquips() { - return equips; - } - - /** - * @return health during last logout - */ - public double getLastHealth() { - return lastHealth; - } - - /** - * Used by the API for restoring health - do not use this. - * - * @param health health logged off with - */ - public void setLastHealth(double health) { - lastHealth = health; - } - - /** - * The hunger value here is not representative of the player's total hunger, - * rather the amount left of the next hunger point. This is manipulated by - * attributes were if an attribute says a player has twice as much "hunger" - * as normal, this will go down by decimals to slow the decay of hunger. - * - * @return amount of the next hunger point the player has - */ - public double getHungerValue() { - return hunger; - } - - /** - * @param hungerValue new hunger value - * @see PlayerData#getHungerValue - */ - public void setHungerValue(final double hungerValue) { - this.hunger = hungerValue; - } - - public int subtractHungerValue(final double amount) { - final double scaled = amount / scaleStat(AttributeManager.HUNGER, amount); - final int lost = scaled >= hunger ? (int) (scaled - hunger) + 1 : 0; - this.hunger += lost - amount; - return lost; - } - - /** - * Ends the initialization flag for the data. Used by the - * API to avoid async issues. Do not use this in other - * plugins. - */ - public void endInit() { - init = false; - } - - /** - * Retrieves the name of the active map menu scheme for the player - * - * @return map menu scheme name - */ - public String getScheme() { - return scheme; - } - - /** - * Sets the active scheme name for the player - * - * @param name name of the scheme - */ - public void setScheme(String name) { - scheme = name; - } - - /////////////////////////////////////////////////////// - // // - // Attributes // - // // - /////////////////////////////////////////////////////// - - /** - * Retrieves a map of all player attribute totals. Modifying - * the map will not change actual player attributes. - * - * @return attribute totals - */ - public HashMap getAttributes() { - HashMap map = new HashMap<>(); - for (String key : SkillAPI.getAttributeManager().getKeys()) { map.put(key, getAttribute(key)); } - return map; - } - - /** - * Retrieves a map of all attributes the player invested. - * This doesn't count base attributes from classes or - * bonus attributes from effects. Modifying the map will - * not change actual player attributes. - * - * @return attribute totals - */ - public HashMap getInvestedAttributes() { - return new HashMap<>(attributes); - } - - /** - * Gets the number of attribute points the player has - * between invested and bonus sources. - * - * @param key attribute key - * - * @return number of total points - */ - public int getAttribute(String key) { - key = key.toLowerCase(); - int total = 0; - if (attributes.containsKey(key)) { total += attributes.get(key); } - if (bonusAttrib.containsKey(key)) { total += bonusAttrib.get(key); } - for (PlayerClass playerClass : classes.values()) { - total += playerClass.getData().getAttribute(key, playerClass.getLevel()); - } - return Math.max(0, total); - } - - /** - * Gets the number of attribute points invested in the - * given attribute - * - * @param key attribute key - * - * @return number of invested points - */ - public int getInvestedAttribute(String key) { - return attributes.getOrDefault(key.toLowerCase(), 0); - } - - /** - * Checks whether or not the player has any - * points invested in a given attribute - * - * @param key attribute key - * - * @return true if any points are invested, false otherwise - */ - public boolean hasAttribute(String key) { - return getAttribute(key) > 0; - } - - /** - * Invests a point in the attribute if the player - * has any remaining attribute points. If the player - * has no remaining points, this will do nothing. - * - * @param key attribute key - * - * @return whether or not it was successfully upgraded - */ - public boolean upAttribute(String key) { - key = key.toLowerCase(); - int current = getInvestedAttribute(key); - int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); - if (attribPoints > 0 && current < max) { - attributes.put(key, current + 1); - attribPoints--; - - PlayerUpAttributeEvent event = new PlayerUpAttributeEvent(this, key); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - attributes.put(key, current); - attribPoints++; - } else { return true; } - } - return false; - } - - /** - * Gives the player attribute points without costing - * attribute points. - * - * @param key attribute to give points for - * @param amount amount to give - */ - public void giveAttribute(String key, int amount) { - key = key.toLowerCase(); - int current = getInvestedAttribute(key); - int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); - amount = Math.min(amount + current, max); - if (amount > current) { - attributes.put(key, amount); - AttributeListener.updatePlayer(this); - } - } - - /** - * Adds bonus attributes to the player. These do not count towards - * the max invest amount and cannot be refunded. - * - * @param key attribute key - * @param amount amount to add - */ - public void addBonusAttributes(String key, int amount) { - key = SkillAPI.getAttributeManager().normalize(key); - amount += bonusAttrib.getOrDefault(key, 0); - bonusAttrib.put(key, amount); - AttributeListener.updatePlayer(this); - } - - /** - * Refunds an attribute point from the given attribute - * if there are any points invested in it. If there are - * none, this will do nothing. - * - * @param key attribute key - */ - public boolean refundAttribute(String key) { - key = key.toLowerCase(); - int current = getInvestedAttribute(key); - if (current > 0) { - PlayerRefundAttributeEvent event = new PlayerRefundAttributeEvent(this, key); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { return false; } - - attribPoints += 1; - attributes.put(key, current - 1); - if (current - 1 <= 0) { attributes.remove(key); } - AttributeListener.updatePlayer(this); - - return true; - } - return false; - } - - /** - * Refunds all spent attribute points for a specific attribute - */ - public void refundAttributes(String key) { - key = key.toLowerCase(); - attribPoints += getInvestedAttribute(key); - attributes.remove(key); - AttributeListener.updatePlayer(this); - } - - /** - * Refunds all spent attribute points - */ - public void refundAttributes() { - ArrayList keys = new ArrayList<>(attributes.keySet()); - for (String key : keys) { - refundAttributes(key); - } - } - - /** - * Retrieves the current number of attribute points the player has - * - * @return attribute point total - */ - public int getAttributePoints() { - return attribPoints; - } - - /** - * Gives the player attribute points - * - * @param amount amount of attribute points - */ - public void giveAttribPoints(int amount) { - attribPoints += amount; - } - - /** - * Sets the current amount of attribute points - * - * @param amount amount of points to have - */ - public void setAttribPoints(int amount) { - attribPoints = amount; - } - - /** - * Scales a stat value using the player's attributes - * - * @param stat stat key - * @param value base value - * - * @return modified value - */ - public double scaleStat(final String stat, final double value) { - final AttributeManager manager = SkillAPI.getAttributeManager(); - if (manager == null) { return value; } - - final List matches = manager.forStat(stat); - if (matches == null) { return value; } - - double modified = value; - for (final AttributeManager.Attribute attribute : matches) { - int amount = getAttribute(attribute.getKey()); - if (amount > 0) { - modified = attribute.modifyStat(stat, modified, amount); - } - } - return modified; - } - - /** - * Scales a dynamic skill's value using global modifiers - * - * @param component component holding the value - * @param key key of the value - * @param value unmodified value - * - * @return the modified value - */ - public double scaleDynamic(EffectComponent component, String key, double value) { - final AttributeManager manager = SkillAPI.getAttributeManager(); - if (manager == null) { return value; } - - final List matches = manager.forComponent(component, key); - if (matches == null) { return value; } - - for (final AttributeManager.Attribute attribute : matches) { - int amount = getAttribute(attribute.getKey()); - if (amount > 0) { - value = attribute.modify(component, key, value, amount); - } - } - return value; - } - - /** - * Opens the attribute menu for the player - * - * @return true if successfully opened, false if conditions weren't met - */ - public boolean openAttributeMenu() { - Player player = getPlayer(); - if (SkillAPI.getSettings().isAttributesEnabled() && player != null) { - GUITool.getAttributesMenu().show( - new AttributeHandler(), - this, - SkillAPI.getLanguage().getMessage( - GUINodes.ATTRIB_TITLE, - true, - FilterType.COLOR, - RPGFilter.POINTS.setReplacement(attribPoints + ""), - Filter.PLAYER.setReplacement(player.getName()) - ).get(0), - SkillAPI.getAttributeManager().getAttributes() - ); - return true; - } - return false; - } - - /** - * Retrieves the player's attribute data. - * Modifying this will modify the player's - * actual data. - * - * @return the player's attribute data - */ - public HashMap getAttributeData() { - return attributes; - } - - /////////////////////////////////////////////////////// - // // - // Skills // - // // - /////////////////////////////////////////////////////// - - /** - * Checks if the owner has a skill by name. This is not case-sensitive - * and does not check to see if the skill is unlocked. It only checks if - * the skill is available to upgrade/use. - * - * @param name name of the skill - * - * @return true if has the skill, false otherwise - */ - public boolean hasSkill(String name) { - return name != null && skills.containsKey(name.toLowerCase()); - } - - /** - * Retrieves a skill of the owner by name. This is not case-sensitive. - * - * @param name name of the skill - * - * @return data for the skill or null if the player doesn't have the skill - */ - public PlayerSkill getSkill(String name) { - if (name == null) { return null; } - return skills.get(name.toLowerCase()); - } - - public int getInvestedSkillPoints() { - int total = 0; - for (PlayerSkill playerSkill : skills.values()) { - total += playerSkill.getInvestedCost(); - } - return total; - } - - /** - * Retrieves all of the skill data the player has. Modifying this - * collection will not modify the player's owned skills but modifying - * one of the elements will change that element's data for the player. - * - * @return collection of skill data for the owner - */ - public Collection getSkills() { - return skills.values(); - } - - /** - * Retrieves the level of a skill for the owner. This is not case-sensitive. - * - * @param name name of the skill - * - * @return level of the skill or 0 if not found - */ - public int getSkillLevel(String name) { - PlayerSkill skill = getSkill(name); - return skill == null ? 0 : skill.getLevel(); - } - - /** - * Gives the player a skill outside of the normal class skills. - * This skill will not show up in a skill tree. - * - * @param skill skill to give the player - */ - public void giveSkill(Skill skill) { - giveSkill(skill, null); - } - - /** - * Gives the player a skill using the class data as a parent. This - * skill will not show up in a skill tree. - * - * @param skill skill to give the player - * @param parent parent class data - */ - public void giveSkill(Skill skill, PlayerClass parent) { - String key = skill.getKey(); - if (!skills.containsKey(key)) { - PlayerSkill data = new PlayerSkill(this, skill, parent); - combos.addSkill(skill); - skills.put(key, data); - autoLevel(skill); - } - } - - /** - * Attempts to auto-level any skills that are able to do so - */ - public void autoLevel() { - if (init) { return; } - - final Player player = getPlayer(); - if (player == null) { return; } - - for (PlayerSkill skill : skills.values()) { - if (skill.getData().isAllowed(player)) { - autoLevel(skill.getData()); - } - } - } - - private void autoLevel(Skill skill) { - PlayerSkill data = skills.get(skill.getKey()); - if (data == null || getPlayer() == null || !skill.isAllowed(getPlayer())) { return; } - - int lastLevel = data.getLevel(); - while (data.getData().canAutoLevel(lastLevel) - && !data.isMaxed() - && data.getLevelReq() <= data.getPlayerClass().getLevel()) { - upgradeSkill(skill); - if (lastLevel == data.getLevel()) { - break; - } - lastLevel++; - } - } - - /** - * Upgrades a skill owned by the player. The player must own the skill, - * have enough skill points, meet the level and skill requirements, and - * not have maxed out the skill already in order to upgrade the skill. - * This will consume the skill point cost while upgrading the skill. - * - * @param skill skill to upgrade - * - * @return true if successfully was upgraded, false otherwise - */ - public boolean upgradeSkill(Skill skill) { - // Cannot be null - if (skill == null) { - return false; - } - - // Must be a valid available skill - PlayerSkill data = skills.get(skill.getName().toLowerCase()); - if (data == null) { - return false; - } - - // Must meet any skill requirements - if (!skill.isCompatible(this) || !skill.hasInvestedEnough(this) || !skill.hasDependency(this)) { - return false; - } - - int level = data.getPlayerClass().getLevel(); - int points = data.getPlayerClass().getPoints(); - int cost = data.getCost(); - if (!data.isMaxed() && level >= data.getLevelReq() && points >= cost) { - // Upgrade event - PlayerSkillUpgradeEvent event = new PlayerSkillUpgradeEvent(this, data, cost); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; - } - - // Apply upgrade - data.getPlayerClass().usePoints(cost); - forceUpSkill(data); - - return true; - } else { - return false; - } - } - - /** - * Forcefully upgrades a skill, not letting other plugins - * cancel it and ignoring any requirements to do so - * - * @param skill skill to forcefully upgrade - */ - public void forceUpSkill(PlayerSkill skill) { - skill.addLevels(1); - - // Passive calls - if (passive) { - Player player = getPlayer(); - if (player != null && skill.getData() instanceof PassiveSkill) { - if (skill.getLevel() == 1) { - ((PassiveSkill) skill.getData()).initialize(player, skill.getLevel()); - } else { - ((PassiveSkill) skill.getData()).update(player, skill.getLevel() - 1, skill.getLevel()); - } - } - - // Unlock event - if (skill.getLevel() == 1) { - Bukkit.getPluginManager().callEvent(new PlayerSkillUnlockEvent(this, skill)); - this.autoLevel(); - } - } - } - - /** - * Downgrades a skill owned by the player. The player must own the skill and it must - * not currently be level 0 for the player to downgrade the skill. This will refund - * the skill point cost when downgrading the skill. - * - * @param skill skill to downgrade - * - * @return true if successfully downgraded, false otherwise - */ - public boolean downgradeSkill(Skill skill) { - // Cannot be null - if (skill == null) { - return false; - } - - // Must be a valid available skill - PlayerSkill data = skills.get(skill.getName().toLowerCase()); - if (data == null) { - return false; - } - - // Must not be a free skill - if (data.getCost() == 0) { - return false; - } - - // Must not be required by another skill - for (PlayerSkill s : skills.values()) { - if (s.getData().getSkillReq() != null - && s.getData().getSkillReq().equalsIgnoreCase(skill.getName()) - && data.getLevel() <= s.getData().getSkillReqLevel() - && s.getLevel() > 0) { - return false; - } - } - - int cost = skill.getCost(data.getLevel() - 1); - if (data.getLevel() > 0) { - // Upgrade event - PlayerSkillDowngradeEvent event = new PlayerSkillDowngradeEvent(this, data, cost); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; - } - - // Apply upgrade - data.getPlayerClass().givePoints(cost, PointSource.REFUND); - forceDownSkill(data); - - return true; - } else { - return false; - } - } - - /** - * Forcefully downgrades a skill, not letting other plugins - * stop it and ignoring any skill requirements to do so. - * - * @param skill skill to forcefully downgrade - */ - public void forceDownSkill(PlayerSkill skill) { - skill.addLevels(-1); - - // Passive calls - Player player = getPlayer(); - if (player != null && skill.getData() instanceof PassiveSkill) { - if (skill.getLevel() == 0) { - ((PassiveSkill) skill.getData()).stopEffects(player, 1); - } else { - ((PassiveSkill) skill.getData()).update(player, skill.getLevel() + 1, skill.getLevel()); - } - } - - // Clear bindings - if (skill.getLevel() == 0) { - clearBinds(skill.getData()); - } - } - - /** - * Refunds a skill for the player, resetting it down - * to level 0 and giving back any invested skill points. - * - * @param skill skill to refund - */ - public void refundSkill(PlayerSkill skill) { - Player player = getPlayer(); - - if (skill.getCost() == 0 || skill.getLevel() == 0) { return; } - - skill.getPlayerClass().givePoints(skill.getInvestedCost(), PointSource.REFUND); - skill.setLevel(0); - - if (player != null && (skill.getData() instanceof PassiveSkill)) { - ((PassiveSkill) skill.getData()).stopEffects(player, 1); - } - } - - /** - * Refunds all skills for the player - */ - public void refundSkills() { - for (PlayerSkill skill : skills.values()) { refundSkill(skill); } - - clearAllBinds(); - } - - /** - * Shows the skill tree for the player. If the player has multiple trees, - * this will show the list of skill trees they can view. - */ - public void showSkills() { - showSkills(getPlayer()); - } - - /** - * Shows the class details for the player - * - * @param player player to show to - * - * @return true if shown, false if nothing to show - */ - public boolean showDetails(Player player) { - if (classes.size() > 0 && player != null) { - HashMap iconMap = new HashMap<>(); - for (Map.Entry entry : classes.entrySet()) { - iconMap.put(entry.getKey().toLowerCase(), entry.getValue().getData()); - } - - GUITool.getDetailsMenu().show( - new DetailsHandler(), - this, - SkillAPI.getLanguage().getMessage( - GUINodes.CLASS_LIST, - true, - FilterType.COLOR, - Filter.PLAYER.setReplacement(player.getName()) - ).get(0), - iconMap - ); - return true; - } else { return false; } - } - - /** - * Shows profession options of the first class group available - * - * @param player player to show profession options for - * - * @return true if shown profession options, false if none available - */ - public boolean showProfession(Player player) { - for (String group : SkillAPI.getGroups()) { - PlayerClass c = getClass(group); - if (c == null || (c.getLevel() == c.getData().getMaxLevel() && c.getData().getOptions().size() > 0)) { - GUITool.getProfessMenu(c == null ? null : c.getData()).show( - new ProfessHandler(), - this, - SkillAPI.getLanguage().getMessage( - GUINodes.PROFESS_TITLE, - true, - FilterType.COLOR, - Filter.PLAYER.setReplacement(player.getName()), - RPGFilter.GROUP.setReplacement(group) - ).get(0), - SkillAPI.getClasses() - ); - return true; - } - } - return false; - } - - /** - * Shows the skill tree for the player. If the player has multiple trees, - * this will show the list of skill trees they can view. - * - * @param player player to show the skill tree for - * - * @return true if able to show the player, false otherwise - */ - public boolean showSkills(Player player) { - // Cannot show an invalid player, and cannot show no skills - if (player == null || classes.size() == 0 || skills.size() == 0) { - return false; - } - - // Show list of classes that have skill trees - if (classes.size() > 1) { return showDetails(player); } - - // Show only class's skill tree otherwise - else { return showSkills(player, classes.values().iterator().next()); } - } - - /** - * Shows the skill tree to the player for the given class - * - * @param player player to show - * @param playerClass class to look for - * - * @return true if succeeded, false otherwise - */ - public boolean showSkills(Player player, PlayerClass playerClass) { - // Cannot show an invalid player, and cannot show no skills - if (player == null || playerClass.getData().getSkills().size() == 0) { - return false; - } - - // Show skill tree of the class - this.menuClass = playerClass.getData().getName(); - GUITool.getSkillTree(playerClass.getData()).show( - new SkillHandler(), - this, - SkillAPI.getLanguage().getMessage( - GUINodes.SKILL_TREE, - true, - FilterType.COLOR, - RPGFilter.POINTS.setReplacement(playerClass.getPoints() + ""), - RPGFilter.LEVEL.setReplacement(playerClass.getLevel() + ""), - RPGFilter.CLASS.setReplacement(playerClass.getData().getName()), - Filter.PLAYER.setReplacement(getPlayerName()) - ).get(0), - playerClass.getData().getSkillMap() - ); - return true; - } - - /** - * Retrieves the name of the class shown in the skill tree - * - * @return class name - */ - public String getShownClassName() { - return menuClass; - } - - /////////////////////////////////////////////////////// - // // - // Classes // - // // - /////////////////////////////////////////////////////// - - /** - * Checks whether or not the player has as least one class they have professed as. - * - * @return true if professed, false otherwise - */ - public boolean hasClass() { - return classes.size() > 0; - } - - /** - * Checks whether or not a player has a class within the given group - * - * @param group class group to check - * - * @return true if has a class in the group, false otherwise - */ - public boolean hasClass(String group) { - return classes.containsKey(group); - } - - /** - * Retrieves the collection of the data for classes the player has professed as. - * - * @return collection of the data for professed classes - */ - public Collection getClasses() { - return classes.values(); - } - - /** - * Retrieves the data of a class the player professed as by group. This is - * case-sensitive. - * - * @param group group to get the profession for - * - * @return professed class data or null if not professed for the group - */ - public PlayerClass getClass(String group) { - return classes.get(group); - } - - /** - * Retrieves the data of the professed class under the main class group. The - * "main" group is determined by the setting in the config. - * - * @return main professed class data or null if not professed for the main group - */ - public PlayerClass getMainClass() { - String main = SkillAPI.getSettings().getMainGroup(); - if (classes.containsKey(main)) { - return classes.get(main); - } else if (classes.size() > 0) { - return classes.values().toArray(new PlayerClass[classes.size()])[0]; - } else { - return null; - } - } - - /** - * Sets the professed class for the player for the corresponding group. This - * will not save any skills, experience, or levels of the previous class if - * there was any. The new class will start at level 1 with 0 experience. - * - * @param rpgClass class to assign to the player - * - * @return the player-specific data for the new class - */ - public PlayerClass setClass(RPGClass rpgClass) { - PlayerClass c = classes.remove(rpgClass.getGroup()); - if (c != null) { - for (Skill skill : c.getData().getSkills()) { - skills.remove(skill.getName().toLowerCase()); - combos.removeSkill(skill); - } - } else { attribPoints += rpgClass.getGroupSettings().getStartingAttribs(); } - - PlayerClass classData = new PlayerClass(this, rpgClass); - classes.put(rpgClass.getGroup(), classData); - - // Add in missing skills - for (Skill skill : rpgClass.getSkills()) { - giveSkill(skill, classData); - } - - updateHealthAndMana(getPlayer()); - updateScoreboard(); - return classes.get(rpgClass.getGroup()); - } - - /** - * Checks whether or not the player is professed as the class - * without checking child classes. - * - * @param rpgClass class to check - * - * @return true if professed as the specific class, false otherwise - */ - public boolean isExactClass(RPGClass rpgClass) { - if (rpgClass == null) { return false; } - PlayerClass c = classes.get(rpgClass.getGroup()); - return (c != null) && (c.getData() == rpgClass); - } - - /** - * Checks whether or not the player is professed as the class - * or any of its children. - * - * @param rpgClass class to check - * - * @return true if professed as the class or one of its children, false otherwise - */ - public boolean isClass(RPGClass rpgClass) { - if (rpgClass == null) { - return false; - } - - PlayerClass pc = classes.get(rpgClass.getGroup()); - if (pc == null) { return false; } - - RPGClass temp = pc.getData(); - while (temp != null) { - if (temp == rpgClass) { - return true; - } - temp = temp.getParent(); - } - - return false; - } - - /** - * Checks whether or not the player can profess into the given class. This - * checks to make sure the player is currently professed as the parent of the - * given class and is high enough of a level to do so. - * - * @param rpgClass class to check - * - * @return true if can profess, false otherwise - */ - public boolean canProfess(RPGClass rpgClass) { - Player p = getPlayer(); - if (p == null || !rpgClass.isAllowed(p)) { - return false; - } - - if (classes.containsKey(rpgClass.getGroup())) { - PlayerClass current = classes.get(rpgClass.getGroup()); - return rpgClass.getParent() == current.getData() && current.getData().getMaxLevel() <= current.getLevel(); - } else { - return !rpgClass.hasParent(); - } - } - - /** - * Resets the class data for the owner under the given group. This will remove - * the profession entirely, leaving no remaining data until the player professes - * again to a starting class. - * - * @param group group to reset - */ - public void reset(String group) { - GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); - if (!settings.canReset()) { return; } - - PlayerClass playerClass = classes.remove(group); - if (playerClass != null) { - // Remove skills - RPGClass data = playerClass.getData(); - for (Skill skill : data.getSkills()) { - PlayerSkill ps = skills.remove(skill.getName().toLowerCase()); - if (ps != null && ps.isUnlocked() && ps.getData() instanceof PassiveSkill) { - ((PassiveSkill) ps.getData()).stopEffects(getPlayer(), ps.getLevel()); - } - combos.removeSkill(skill); - } - - // Update GUI features - updateScoreboard(); - - // Call the event - Bukkit.getPluginManager().callEvent(new PlayerClassChangeEvent(playerClass, data, null)); - } - - // Restore default class if applicable - RPGClass rpgClass = settings.getDefault(); - if (rpgClass != null && settings.getPermission() == null) { - setClass(rpgClass); - } - binds.clear(); - resetAttribs(); - } - - /** - * Resets all profession data for the player. This clears all professions the player - * has, leaving no remaining data until the player professes again to a starting class. - */ - public void resetAll() { - ArrayList keys = new ArrayList<>(classes.keySet()); - for (String key : keys) { reset(key); } - } - - /** - * Resets attributes for the player - */ - public void resetAttribs() { - attributes.clear(); - attribPoints = 0; - for (PlayerClass c : classes.values()) { - GroupSettings s = c.getData().getGroupSettings(); - attribPoints += s.getStartingAttribs() + s.getAttribsForLevels(c.getLevel(), 1); - } - AttributeListener.updatePlayer(this); - updateHealthAndMana(getPlayer()); - } - - /** - * Professes the player into the class if they are able to. This will - * reset the class data if the group options are set to reset upon - * profession. Otherwise, all skills, experience, and levels of the - * current class under the group will be retained and carried over into - * the new profession. - * - * @param rpgClass class to profess into - * - * @return true if successfully professed, false otherwise - */ - public boolean profess(RPGClass rpgClass) { - if (rpgClass != null && canProfess(rpgClass)) { - final PlayerClass previousData = classes.get(rpgClass.getGroup()); - final RPGClass previous = previousData == null ? null : previousData.getData(); - - // Pre-class change event in case someone wants to stop it - final PlayerPreClassChangeEvent event = new PlayerPreClassChangeEvent( - this, - previousData, - previous, - rpgClass); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; - } - - // Reset data if applicable - final boolean isResetting = SkillAPI.getSettings().getGroupSettings(rpgClass.getGroup()).isProfessReset(); - if (isResetting) { - reset(rpgClass.getGroup()); - } - - // Inherit previous class data if any - final PlayerClass current; - if (previousData == null || isResetting) { - current = new PlayerClass(this, rpgClass); - classes.put(rpgClass.getGroup(), current); - attribPoints += rpgClass.getGroupSettings().getStartingAttribs(); - } else { - current = previousData; - previousData.setClassData(rpgClass); - } - - // Add skills - for (Skill skill : rpgClass.getSkills()) { - if (!skills.containsKey(skill.getKey())) { - skills.put(skill.getKey(), new PlayerSkill(this, skill, current)); - combos.addSkill(skill); - } - } - - Bukkit.getPluginManager().callEvent(new PlayerClassChangeEvent(current, previous, current.getData())); - resetAttribs(); - updateScoreboard(); - return true; - } else { - return false; - } - } - - /** - * Gives experience to the player from the given source - * - * @param amount amount of experience to give - * @param source source of the experience - */ - public void giveExp(double amount, ExpSource source) { - giveExp(amount, source, true); - } - - /** - * Gives experience to the player from the given source - * - * @param amount amount of experience to give - * @param source source of the experience - * @param message whether or not to show the configured message if enabled - */ - public void giveExp(double amount, ExpSource source, boolean message) { - for (PlayerClass playerClass : classes.values()) { - playerClass.giveExp(amount, source, message); - } - } - - /** - * Causes the player to lose experience as a penalty (generally for dying) - */ - public void loseExp() { - for (PlayerClass playerClass : classes.values()) { - double penalty = playerClass.getData().getGroupSettings().getDeathPenalty(); - if (penalty > 0) { - playerClass.loseExp(penalty); - } - } - } - - /** - * Gives levels to the player for all classes matching the experience source - * - * @param amount amount of levels to give - * @param source source of the levels - */ - public boolean giveLevels(int amount, ExpSource source) { - boolean success = false; - for (PlayerClass playerClass : classes.values()) { - RPGClass data = playerClass.getData(); - if (data.receivesExp(source)) { - success = true; - playerClass.giveLevels(amount); - } - } - updateHealthAndMana(getPlayer()); - return success; - } - - /** - * Gives skill points to the player for all classes matching the experience source - * - * @param amount amount of levels to give - * @param source source of the levels - */ - public void givePoints(int amount, ExpSource source) { - for (PlayerClass playerClass : classes.values()) { - if (playerClass.getData().receivesExp(source)) { - playerClass.givePoints(amount); - } - } - } - - /////////////////////////////////////////////////////// - // // - // Health and Mana // - // // - /////////////////////////////////////////////////////// - - /** - * Updates the player's max health and mana using class data. - * - * @param player player to update the health and mana for - */ - public void updateHealthAndMana(Player player) { - if (player == null) { - return; - } - - // Update maxes - double health = bonusHealth; - maxMana = bonusMana; - for (PlayerClass c : classes.values()) { - health += c.getHealth(); - maxMana += c.getMana(); - } - if (health == bonusHealth) { - health += SkillAPI.getSettings().getDefaultHealth(); - } - if (health <= 0) { - health = SkillAPI.getSettings().getDefaultHealth(); - } - if (SkillAPI.getSettings().isModifyHealth()) { player.setMaxHealth(health); } - mana = Math.min(mana, maxMana); - - // Health scaling is available starting with 1.6.2 - if (SkillAPI.getSettings().isOldHealth()) { - player.setHealthScaled(true); - player.setHealthScale(20); - } else { - player.setHealthScaled(false); - } - } - - /** - * Gives max health to the player. This does not carry over to other accounts - * and will reset when SkillAPI is disabled. This does however carry over through - * death and professions. This will accept negative values. - * - * @param amount amount of bonus health to give - */ - public void addMaxHealth(double amount) { - bonusHealth += amount; - final Player player = getPlayer(); - if (player != null) { - if (VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { - final AttributeInstance attribute = player.getAttribute(Attribute.GENERIC_MAX_HEALTH); - attribute.setBaseValue(attribute.getBaseValue() + amount); - } else { - final double newHealth = player.getMaxHealth() + amount; - player.setMaxHealth(newHealth); - if (player.getMaxHealth() > newHealth) { - player.setMaxHealth(newHealth * 2 - player.getMaxHealth()); - } - } - } - } - - /** - * Gives max mana to the player. This does not carry over to other accounts - * and will reset when SkillAPI is disabled. This does however carry over through - * death and professions. This will accept negative values. - * - * @param amount amount of bonus mana to give - */ - public void addMaxMana(double amount) { - bonusMana += amount; - maxMana += amount; - mana += amount; - } - - /** - * Retrieves the amount of mana the player currently has. - * - * @return current player mana - */ - public double getMana() { - return mana; - } - - /** - * Checks whether or not the player has at least the specified amount of mana - * - * @param amount required mana amount - * - * @return true if has the amount of mana, false otherwise - */ - public boolean hasMana(double amount) { - return mana >= amount; - } - - /** - * Retrieves the max amount of mana the player can have including bonus mana - * - * @return max amount of mana the player can have - */ - public double getMaxMana() { - return maxMana; - } - - /** - * Regenerates mana for the player based on the regen amounts of professed classes - */ - public void regenMana() { - double amount = 0; - for (PlayerClass c : classes.values()) { - if (c.getData().hasManaRegen()) { - amount += c.getData().getManaRegen(); - } - } - if (amount > 0) { - giveMana(amount, ManaSource.REGEN); - } - } - - /** - * Sets the player's amount of mana without launching events - * - * @param amount current mana - */ - public void setMana(double amount) { - this.mana = amount; - } - - /** - * Gives mana to the player from an unknown source. This will not - * cause the player's mana to go above their max amount. - * - * @param amount amount of mana to give - */ - public void giveMana(double amount) { - giveMana(amount, ManaSource.SPECIAL); - } - - /** - * Gives mana to the player from the given mana source. This will not - * cause the player's mana to go above the max amount. - * - * @param amount amount of mana to give - * @param source source of the mana - */ - public void giveMana(double amount, ManaSource source) { - PlayerManaGainEvent event = new PlayerManaGainEvent(this, amount, source); - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { - Logger.log( - LogType.MANA, - 2, - getPlayerName() + " gained " + amount + " mana due to " + event.getSource().name()); - - mana += event.getAmount(); - if (mana > maxMana) { - mana = maxMana; - } - if (mana < 0) { - mana = 0; - } - } else { Logger.log(LogType.MANA, 2, getPlayerName() + " had their mana gain cancelled"); } - } - - /** - * Takes mana away from the player for an unknown reason. This will not - * cause the player to fall below 0 mana. - * - * @param amount amount of mana to take away - */ - public void useMana(double amount) { - useMana(amount, ManaCost.SPECIAL); - } - - /** - * Takes mana away from the player for the specified reason. This will not - * cause the player to fall below 0 mana. - * - * @param amount amount of mana to take away - * @param cost source of the mana cost - */ - public void useMana(double amount, ManaCost cost) { - PlayerManaLossEvent event = new PlayerManaLossEvent(this, amount, cost); - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { - Logger.log( - LogType.MANA, - 2, - getPlayerName() + " used " + amount + " mana due to " + event.getSource().name()); - - mana -= event.getAmount(); - if (mana < 0) { - mana = 0; - } - } - } - - /** - * Clears bonus health/mana - */ - public void clearBonuses() { - bonusMana = 0; - bonusHealth = 0; - bonusAttrib.clear(); - equips = new PlayerEquips(this); - } - - /////////////////////////////////////////////////////// - // // - // Skill Binding // - // // - /////////////////////////////////////////////////////// - - /** - * Retrieves a skill the player has bound by material - * - * @param mat material to get the bind for - * - * @return skill bound to the material or null if none are bound - */ - public PlayerSkill getBoundSkill(Material mat) { - return binds.get(mat); - } - - /** - * Retrieves the bound data for the player. Modifying this map will - * modify the bindings the player has. - * - * @return the skill binds data for the player - */ - public HashMap getBinds() { - return binds; - } - - /** - * Checks whether or not the material has a skill bound to it - * - * @param mat material to check - * - * @return true if a skill is bound to it, false otherwise - */ - public boolean isBound(Material mat) { - return binds.containsKey(mat); - } - - /** - * Binds a skill to a material for the player. The bind will not work if the skill - * was already bound to the material. - * - * @param mat material to bind the skill to - * @param skill skill to bind to the material - * - * @return true if was able to bind the skill, false otherwise - */ - public boolean bind(Material mat, PlayerSkill skill) { - // Special cases - if (mat == null || (skill != null && skill.getPlayerData() != this)) { - return false; - } - - PlayerSkill bound = getBoundSkill(mat); - if (bound != skill) { - // Apply the binding - if (skill == null) { - binds.remove(mat); - } else { - binds.put(mat, skill); - } - - // Update the old skill's bind - if (bound != null) { - bound.setBind(null); - } - - // Update the new skill's bind - if (skill != null) { - skill.setBind(mat); - } - - return true; - } - - // The skill was already bound - else { - return false; - } - } - - /** - * Clears a skill binding on the material. If there is no binding on the - * material, this will do nothing. - * - * @param mat material to clear bindings from - * - * @return true if a binding was cleared, false otherwise - */ - public boolean clearBind(Material mat) { - return binds.remove(mat) != null; - } - - /** - * Clears the skill binding for the given skill. This will remove the bindings - * on all materials involving the skill. - * - * @param skill skill to unbind - */ - public void clearBinds(Skill skill) { - ArrayList keys = new ArrayList<>(binds.keySet()); - for (Material key : keys) { - PlayerSkill bound = binds.get(key); - if (bound.getData() == skill) { - binds.remove(key); - } - } - } - - /** - * Clears all binds the player currently has - */ - public void clearAllBinds() { - binds.clear(); - } - - /////////////////////////////////////////////////////// - // // - // Functions // - // // - /////////////////////////////////////////////////////// - - /** - * Records any data to save with class data - * - * @param player player to record for - */ - public void record(Player player) { - this.lastHealth = player.getHealth(); - } - - /** - * Updates the scoreboard with the player's current class. - * This is already done by the API and doesn't need to be - * done by other plugins. - */ - public void updateScoreboard() { - if (SkillAPI.getSettings().isShowScoreboard()) { SkillAPI.schedule(new ScoreboardTask(this), 2); } - } - - /** - * Starts passive abilities for the player if they are online. This is - * already called by the API and shouldn't be called by other plugins. - * - * @param player player to set the passive skills up for - */ - public void startPassives(Player player) { - if (player == null) { - return; - } - passive = true; - for (PlayerSkill skill : skills.values()) { - if (skill.isUnlocked() && (skill.getData() instanceof PassiveSkill)) { - ((PassiveSkill) skill.getData()).initialize(player, skill.getLevel()); - } - } - } - - /** - * Stops passive abilities for the player if they are online. This is already - * called by the API and shouldn't be called by other plugins. - * - * @param player player to stop the passive skills for - */ - public void stopPassives(Player player) { - if (player == null) { - return; - } - passive = false; - for (PlayerSkill skill : skills.values()) { - if (skill.isUnlocked() && (skill.getData() instanceof PassiveSkill)) { - try { - ((PassiveSkill) skill.getData()).stopEffects(player, skill.getLevel()); - } catch (Exception ex) { - Logger.bug("Failed to stop passive skill " + skill.getData().getName()); - ex.printStackTrace(); - } - } - } - } - - /** - * Casts a skill by name for the player. In order to cast the skill, - * the player must be online, have the skill unlocked, have enough mana, - * have the skill off cooldown, and have a proper target if applicable. - * - * @param skillName name of the skill ot cast - * - * @return true if successfully cast the skill, false otherwise - */ - public boolean cast(String skillName) { - return cast(skills.get(skillName.toLowerCase())); - } - - /** - * Casts a skill for the player. In order to cast the skill, - * the player must be online, have the skill unlocked, have enough mana, - * have the skill off cooldown, and have a proper target if applicable. - * - * @param skill skill to cast - * - * @return true if successfully cast the skill, false otherwise - */ - public boolean cast(PlayerSkill skill) { - // Invalid skill - if (skill == null) { throw new IllegalArgumentException("Skill cannot be null"); } - - int level = skill.getLevel(); - - // Not unlocked or on cooldown - if (!check(skill, true, true)) { return false; } - - // Dead players can't cast skills - Player p = getPlayer(); - if (p.isDead()) { return PlayerSkillCastFailedEvent.invoke(skill, CASTER_DEAD); } - - // Disable casting in spectator mode - if (p.getGameMode().name().equals("SPECTATOR")) { return PlayerSkillCastFailedEvent.invoke(skill, SPECTATOR); } - - // Skill Shots - if (skill.getData() instanceof SkillShot) { - PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); - Bukkit.getPluginManager().callEvent(event); - - // Make sure it isn't cancelled - if (!event.isCancelled()) { - try { - if (((SkillShot) skill.getData()).cast(p, level)) { - return applyUse(p, skill, event.getManaCost()); - } else { - return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); - } - } catch (Exception ex) { - Logger.bug("Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); - ex.printStackTrace(); - return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); - } - } else { return PlayerSkillCastFailedEvent.invoke(skill, CANCELED); } - } - - // Target Skills - else if (skill.getData() instanceof TargetSkill) { - LivingEntity target = TargetHelper.getLivingTarget(p, skill.getData().getRange(level)); - - // Must have a target - if (target == null) { return PlayerSkillCastFailedEvent.invoke(skill, NO_TARGET); } - - PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); - Bukkit.getPluginManager().callEvent(event); - - // Make sure it isn't cancelled - if (!event.isCancelled()) { - try { - final boolean canAttack = !SkillAPI.getSettings().canAttack(p, target); - if (((TargetSkill) skill.getData()).cast(p, target, level, canAttack)) { - return applyUse(p, skill, event.getManaCost()); - } else { - return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); - } - } catch (Exception ex) { - Logger.bug("Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); - ex.printStackTrace(); - return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); - } - } else { PlayerSkillCastFailedEvent.invoke(skill, CANCELED); } - } - - return false; - } - - private boolean applyUse(final Player player, final PlayerSkill skill, final double manaCost) { - skill.startCooldown(); - if (SkillAPI.getSettings().isShowSkillMessages()) { - skill.getData().sendMessage(player, SkillAPI.getSettings().getMessageRadius()); - } - if (SkillAPI.getSettings().isManaEnabled()) { - useMana(manaCost, ManaCost.SKILL_CAST); - } - skillTimer = System.currentTimeMillis() + SkillAPI.getSettings().getCastCooldown(); - return true; - } - - /** - * Checks the cooldown and mana requirements for a skill - * - * @param skill skill to check for - * @param cooldown whether or not to check cooldowns - * @param mana whether or not to check mana requirements - * - * @return true if can use - */ - public boolean check(PlayerSkill skill, boolean cooldown, boolean mana) { - if (skill == null || System.currentTimeMillis() < skillTimer) { return false; } - - SkillStatus status = skill.getStatus(); - int level = skill.getLevel(); - double cost = skill.getData().getManaCost(level); - - // Not unlocked - if (level <= 0) { - return PlayerSkillCastFailedEvent.invoke(skill, NOT_UNLOCKED); - } - - // On Cooldown - if (status == SkillStatus.ON_COOLDOWN && cooldown) { - SkillAPI.getLanguage().sendMessage( - ErrorNodes.COOLDOWN, - getPlayer(), - FilterType.COLOR, - RPGFilter.COOLDOWN.setReplacement(skill.getCooldown() + ""), - RPGFilter.SKILL.setReplacement(skill.getData().getName()) - ); - return PlayerSkillCastFailedEvent.invoke(skill, ON_COOLDOWN); - } - - // Not enough mana - else if (status == SkillStatus.MISSING_MANA && mana) { - SkillAPI.getLanguage().sendMessage( - ErrorNodes.MANA, - getPlayer(), - FilterType.COLOR, - RPGFilter.SKILL.setReplacement(skill.getData().getName()), - RPGFilter.MANA.setReplacement(getMana() + ""), - RPGFilter.COST.setReplacement((int) Math.ceil(cost) + ""), - RPGFilter.MISSING.setReplacement((int) Math.ceil(cost - getMana()) + "") - ); - return PlayerSkillCastFailedEvent.invoke(skill, NO_MANA); - } else { return true; } - } - - /** - * Initializes the application of the data for the player - * - * @param player player to set up for - */ - public void init(Player player) { - if (!SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { return; } - - AttributeListener.updatePlayer(this); - getEquips().update(player); - this.updateHealthAndMana(player); - this.startPassives(player); - this.updateScoreboard(); - if (this.getLastHealth() > 0 && !player.isDead()) { - player.setHealth(Math.min(this.getLastHealth(), player.getMaxHealth())); - } - } -} diff --git a/src/com/sucy/skill/api/util/ParticleHelper.java b/src/com/sucy/skill/api/util/ParticleHelper.java deleted file mode 100644 index ac443c08..00000000 --- a/src/com/sucy/skill/api/util/ParticleHelper.java +++ /dev/null @@ -1,389 +0,0 @@ -/** - * SkillAPI - * com.sucy.skill.api.util.ParticleHelper - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.api.util; - -import com.google.common.collect.ImmutableSet; -import com.rit.sucy.reflect.Particle; -import com.rit.sucy.version.VersionManager; -import com.sucy.skill.api.Settings; -import com.sucy.skill.api.enums.Direction; -import com.sucy.skill.api.particle.SpigotParticles; -import com.sucy.skill.log.Logger; -import org.bukkit.Effect; -import org.bukkit.EntityEffect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Wolf; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.util.HashMap; -import java.util.Random; -import java.util.Set; - -/** - * Helper class for playing particles via config strings in various ways. - */ -public class ParticleHelper { - /** - * Settings key for the arrangement type of particles - */ - public static final String ARRANGEMENT_KEY = "arrangement"; - - /** - * Number of particles - */ - public static final String PARTICLES_KEY = "particles"; - - /** - * The level to use for scaling values - */ - public static final String LEVEL = "level"; - - /** - * Settings key for the type of particle - */ - public static final String PARTICLE_KEY = "particle"; - - /** - * Settings key for the material used by the particle (for block crack, icon crack, and block dust) - */ - public static final String MATERIAL_KEY = "material"; - - /** - * Settings key for the material data used by the particle (for block crack, icon crack, and block dust) - */ - public static final String TYPE_KEY = "type"; - - /** - * Settings key for the radius of the particle arrangement - */ - public static final String RADIUS_KEY = "radius"; - - /** - * Settings key for the amount of particles to play - */ - public static final String AMOUNT_KEY = "amount"; - - /** - * Settings key for the particle arrangement direction (circles only) - */ - public static final String DIRECTION_KEY = "direction"; - - /** - * Settings key for the Bukkit effects' data (default 0) - */ - public static final String DATA_KEY = "data"; - - /** - * Settings key for the reflection particles' visible radius (default 25) - */ - public static final String VISIBLE_RADIUS_KEY = "visible-radius"; - - /** - * Settings key for the reflection particles' X-offset (default 0) - */ - public static final String DX_KEY = "dx"; - - /** - * Settings key for the reflection particles' Y-offset (default 0) - */ - public static final String DY_KEY = "dy"; - - /** - * Settings key for the reflection particles' Z-offset (default 0) - */ - public static final String DZ_KEY = "dz"; - - /** - * Settings key for the reflection particles' "speed" value (default 1) - */ - public static final String SPEED_KEY = "speed"; - - private static final Random random = new Random(); - - /** - * Plays an entity effect at the given location - * - * @param loc location to play the effect - * @param effect entity effect to play - */ - public static void play(Location loc, EntityEffect effect) { - Wolf wolf = (Wolf) loc.getWorld().spawnEntity(loc, EntityType.WOLF); - wolf.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 100, 100)); - wolf.playEffect(effect); - wolf.remove(); - } - - /** - * Plays particles about the given location using the given settings - * - * @param loc location to center the effect around - * @param settings data to play the particles with - */ - public static void play(Location loc, Settings settings) { - String particle = settings.getString(PARTICLE_KEY, "invalid"); - if (settings.has(ARRANGEMENT_KEY)) { - int level = settings.getInt(LEVEL, 1); - double radius = settings.getAttr(RADIUS_KEY, level, 3.0); - int amount = (int) settings.getAttr(PARTICLES_KEY, level, 10); - - String arrangement = settings.getString(ARRANGEMENT_KEY).toLowerCase(); - if (arrangement.equals("circle")) { - Direction dir = null; - if (settings.has(DIRECTION_KEY)) { - try { - dir = Direction.valueOf(settings.getString(DIRECTION_KEY)); - } catch (Exception ex) { /* Use default value */ } - } - if (dir == null) { - dir = Direction.XZ; - } - - fillCircle(loc, particle, settings, radius, amount, dir); - } else if (arrangement.equals("sphere")) { - fillSphere(loc, particle, settings, radius, amount); - } else if (arrangement.equals("hemisphere")) { - fillHemisphere(loc, particle, settings, radius, amount); - } - } else { - play(loc, particle, settings); - } - } - - /** - * Plays a particle at the given location based on the string - * - * @param loc location to play the effect - * @param particle particle to play - * @param settings data to play the particle with - */ - public static void play(Location loc, String particle, Settings settings) { - particle = particle.toLowerCase().replace("_", " "); - final int rad = settings.getInt(VISIBLE_RADIUS_KEY, 25); - final float dx = (float)settings.getDouble(DX_KEY, 0.0); - final float dy = (float)settings.getDouble(DY_KEY, 0.0); - final float dz = (float)settings.getDouble(DZ_KEY, 0.0); - final int amount = settings.getInt(AMOUNT_KEY, 1); - final float speed = (float) settings.getDouble(SPEED_KEY, 1.0); - final Material mat = Material.valueOf(settings.getString(MATERIAL_KEY, "DIRT").toUpperCase().replace(" ", "_")); - - try { - // Normal bukkit effects - if (BUKKIT_EFFECTS.containsKey(particle)) { - loc.getWorld().playEffect(loc, BUKKIT_EFFECTS.get(particle), settings.getInt(DATA_KEY, 0)); - } - - // Entity effects - else if (ENTITY_EFFECTS.contains(particle)) { - play(loc, EntityEffect.valueOf(particle.toUpperCase().replace(' ', '_'))); - } - - // v1.13 particles - else if (VersionManager.isVersionAtLeast(11300)) { - if (particle.startsWith("block")) { - SpigotParticles.playBlock(loc, particle, dx, dy, dz, amount, speed, rad, mat); - } else if (particle.startsWith("icon")) { - SpigotParticles.playItem(loc, particle, dx, dy, dz, amount, speed, rad, mat); - } else { - SpigotParticles.play(loc, particle, dx, dy, dz, amount, speed, rad); - } - } - - // Reflection particles - else if (REFLECT_PARTICLES.containsKey(particle)) { - Particle.play(REFLECT_PARTICLES.get(particle), loc, rad, dx, dy, dz, speed, amount); - } - - // Block break particle - else if (particle.equals("block crack")) { - Particle.playBlockCrack(mat, (short) settings.getInt(TYPE_KEY, 0), loc, rad, speed); - } - - // Icon break particle - else if (particle.equals("icon crack")) { - Particle.playIconCrack(mat, (short) settings.getInt(TYPE_KEY, 0), loc, rad, speed); - } - - // 1.9+ particles - else { - Particle.play(particle, loc, rad, dx, dy, dz, speed, amount); - } - } catch (Exception ex) { - Logger.invalid(ex.getCause().getMessage()); - } - } - - /** - * Plays several of a particle type randomly within a circle - * - * @param loc center location of the circle - * @param particle particle to play - * @param settings data to play the particle with - * @param radius radius of the circle - * @param amount amount of particles to play - */ - public static void fillCircle( - Location loc, - String particle, - Settings settings, - double radius, - int amount, - Direction direction) { - Location temp = loc.clone(); - double rSquared = radius * radius; - double twoRadius = radius * 2; - int index = 0; - - // Play the particles - while (index < amount) { - if (direction == Direction.XY || direction == Direction.XZ) { - temp.setX(loc.getX() + random.nextDouble() * twoRadius - radius); - } - if (direction == Direction.XY || direction == Direction.YZ) { - temp.setY(loc.getY() + random.nextDouble() * twoRadius - radius); - } - if (direction == Direction.XZ || direction == Direction.YZ) { - temp.setZ(loc.getZ() + random.nextDouble() * twoRadius - radius); - } - - if (temp.distanceSquared(loc) > rSquared) { - continue; - } - - play(temp, particle, settings); - index++; - } - } - - /** - * Randomly plays particle effects within the sphere - * - * @param loc location to center the effect around - * @param particle the string value for the particle - * @param settings data to play the particle with - * @param radius radius of the sphere - * @param amount amount of particles to use - */ - public static void fillSphere(Location loc, String particle, Settings settings, double radius, int amount) { - Location temp = loc.clone(); - double rSquared = radius * radius; - double twoRadius = radius * 2; - int index = 0; - - // Play the particles - while (index < amount) { - temp.setX(loc.getX() + random.nextDouble() * twoRadius - radius); - temp.setY(loc.getY() + random.nextDouble() * twoRadius - radius); - temp.setZ(loc.getZ() + random.nextDouble() * twoRadius - radius); - - if (temp.distanceSquared(loc) > rSquared) { - continue; - } - - play(temp, particle, settings); - index++; - } - } - - /** - * Randomly plays particle effects within the hemisphere - * - * @param loc location to center the effect around - * @param particle the string value for the particle - * @param settings data to play the particle with - * @param radius radius of the sphere - * @param amount amount of particles to use - */ - public static void fillHemisphere(Location loc, String particle, Settings settings, double radius, int amount) { - Location temp = loc.clone(); - double rSquared = radius * radius; - double twoRadius = radius * 2; - int index = 0; - - // Play the particles - while (index < amount) { - temp.setX(loc.getX() + random.nextDouble() * twoRadius - radius); - temp.setY(loc.getY() + random.nextDouble() * radius); - temp.setZ(loc.getZ() + random.nextDouble() * twoRadius - radius); - - if (temp.distanceSquared(loc) > rSquared) { - continue; - } - - play(temp, particle, settings); - index++; - } - } - - private static final HashMap BUKKIT_EFFECTS = new HashMap() {{ - put("smoke", Effect.SMOKE); - put("ender signal", Effect.ENDER_SIGNAL); - put("mobspawner flames", Effect.MOBSPAWNER_FLAMES); - put("potion break", Effect.POTION_BREAK); - }}; - - private static final Set ENTITY_EFFECTS = ImmutableSet.of( - "death", "hurt", "sheep eat", "wolf hearts", "wolf shake", "wolf smoke"); - - private static final HashMap REFLECT_PARTICLES = new HashMap() {{ - put("angry villager", "angryVillager"); - put("bubble", "bubble"); - put("cloud", "cloud"); - put("crit", "crit"); - put("death suspend", "deathSuspend"); - put("drip lava", "dripLava"); - put("drip water", "dripWater"); - put("enchantment table", "enchantmenttable"); - put("explode", "explode"); - put("firework spark", "fireworksSpark"); - put("flame", "flame"); - put("footstep", "footstep"); - put("happy villager", "happyVillager"); - put("heart", "heart"); - put("huge explosion", "hugeexplosion"); - put("instant spell", "instantSpell"); - put("large explode", "largeexplode"); - put("large smoke", "largesmoke"); - put("lava", "lava"); - put("magic crit", "magicCrit"); - put("mob spell", "mobSpell"); - put("mob spell ambient", "mobSpellAmbient"); - put("note", "note"); - put("portal", "portal"); - put("red dust", "reddust"); - put("slime", "slime"); - put("snowball poof", "snowballpoof"); - put("snow shovel", "snowshovel"); - put("spell", "spell"); - put("splash", "splash"); - put("suspend", "suspend"); - put("town aura", "townaura"); - put("witch magic", "witchMagic"); - }}; -} diff --git a/src/com/sucy/skill/dynamic/mechanic/DamageMechanic.java b/src/com/sucy/skill/dynamic/mechanic/DamageMechanic.java deleted file mode 100644 index 0d8968a9..00000000 --- a/src/com/sucy/skill/dynamic/mechanic/DamageMechanic.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * SkillAPI - * com.sucy.skill.dynamic.mechanic.DamageMechanic - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.dynamic.mechanic; - -import org.bukkit.entity.LivingEntity; - -import java.util.List; - -/** - * Deals damage to each target - */ -public class DamageMechanic extends MechanicComponent { - private static final String TYPE = "type"; - private static final String DAMAGE = "value"; - private static final String TRUE = "true"; - private static final String CLASSIFIER = "classifier"; - - @Override - public String getKey() { - return "damage"; - } - - /** - * Executes the component - * - * @param caster caster of the skill - * @param level level of the skill - * @param targets targets to apply to - * - * @return true if applied to something, false otherwise - */ - @Override - public boolean execute(LivingEntity caster, int level, List targets) { - String pString = settings.getString(TYPE, "damage").toLowerCase(); - boolean percent = pString.equals("multiplier") || pString.equals("percent"); - boolean missing = pString.equals("percent missing"); - boolean left = pString.equals("percent left"); - boolean trueDmg = settings.getBool(TRUE, false); - double damage = parseValues(caster, DAMAGE, level, 1.0); - String classification = settings.getString(CLASSIFIER, "default"); - if (damage < 0) { return false; } - for (LivingEntity target : targets) { - if (target.isDead()) { - continue; - } - - double amount = damage; - if (percent) { - amount = damage * target.getMaxHealth() / 100; - } else if (missing) { - amount = damage * (target.getMaxHealth() - target.getHealth()) / 100; - } else if (left) { - amount = damage * target.getHealth() / 100; - } - if (trueDmg) { skill.trueDamage(target, amount, caster); } else { - skill.damage(target, amount, caster, classification); - } - } - return targets.size() > 0; - } -} diff --git a/src/com/sucy/skill/hook/PlaceholderAPIHook.java b/src/com/sucy/skill/hook/PlaceholderAPIHook.java deleted file mode 100644 index 7f56b202..00000000 --- a/src/com/sucy/skill/hook/PlaceholderAPIHook.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sucy.skill.hook; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -/** - * SkillAPI © 2018 - * com.sucy.skill.hook.PlaceholderAPIHook - */ -public class PlaceholderAPIHook { - - public static String format(final String message, final Player player) { - return PlaceholderAPI.setPlaceholders(player, message); - } -} diff --git a/src/com/sucy/skill/listener/MainListener.java b/src/com/sucy/skill/listener/MainListener.java deleted file mode 100644 index 623b5704..00000000 --- a/src/com/sucy/skill/listener/MainListener.java +++ /dev/null @@ -1,490 +0,0 @@ -/** - * SkillAPI - * com.sucy.skill.listener.MainListener - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.listener; - -import com.rit.sucy.version.VersionManager; -import com.rit.sucy.version.VersionPlayer; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.enums.ExpSource; -import com.sucy.skill.api.event.PhysicalDamageEvent; -import com.sucy.skill.api.event.PlayerLevelUpEvent; -import com.sucy.skill.api.player.PlayerData; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.api.util.BuffManager; -import com.sucy.skill.api.util.Combat; -import com.sucy.skill.api.util.FlagManager; -import com.sucy.skill.data.Permissions; -import com.sucy.skill.dynamic.DynamicSkill; -import com.sucy.skill.dynamic.mechanic.ImmunityMechanic; -import com.sucy.skill.hook.CitizensHook; -import com.sucy.skill.manager.ClassBoardManager; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.attribute.Attribute; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.ExpBottleEvent; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.inventory.FurnaceExtractEvent; -import org.bukkit.event.player.AsyncPlayerPreLoginEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerExpChangeEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.server.ServerCommandEvent; -import org.bukkit.event.world.ChunkUnloadEvent; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -/** - * The main listener for SkillAPI that handles general mechanics - * such as loading/clearing data, controlling experience gains, and - * enabling/disabling passive abilities. - */ -public class MainListener extends SkillAPIListener -{ - private static final List> JOIN_HANDLERS = new ArrayList<>(); - private static final List> CLEAR_HANDLERS = new ArrayList<>(); - - public static void registerJoin(final Consumer joinHandler) { - JOIN_HANDLERS.add(joinHandler); - } - - public static void registerClear(final Consumer joinHandler) { - CLEAR_HANDLERS.add(joinHandler); - } - - @Override - public void cleanup() { - JOIN_HANDLERS.clear(); - } - - /** - * Loads player data asynchronously when a player tries to log in - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onLogin(AsyncPlayerPreLoginEvent event) { - final OfflinePlayer player; - if (VersionManager.isVersionAtLeast(VersionManager.V1_7_5)) - player = Bukkit.getOfflinePlayer(event.getUniqueId()); - else - player = VersionManager.getOfflinePlayer(event.getName()); - - if (SkillAPI.getSettings().isUseSql() && SkillAPI.getSettings().getSqlDelay() > 0) - SkillAPI.initFakeData(player); - else - SkillAPI.loadPlayerData(player); - } - - /** - * Starts passives and applies class data when a player logs in. - */ - @EventHandler - public void onJoin(final PlayerJoinEvent event) { - final Player player = event.getPlayer(); - if (player.hasMetadata("NPC") || !SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - return; - - final int delay = Math.min(100, SkillAPI.getSettings().getSqlDelay()); - if (SkillAPI.getSettings().isUseSql() && delay > 0) { - SkillAPI.schedule(() -> { - SkillAPI.reloadPlayerData(player); - init(player); - }, delay); - } else { - init(player); - } - } - - private void init(final Player player) { - final PlayerData data = SkillAPI.getPlayerData(player); - data.init(player); - data.autoLevel(); - data.updateScoreboard(); - JOIN_HANDLERS.forEach(handler -> handler.accept(player)); - } - - /** - * Saves player data when they log out and stops passives - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR) - public void onQuit(PlayerQuitEvent event) - { - unload(event.getPlayer()); - } - - /** - * Unloads a player's data from the server - * - * @param player player to unload - */ - public static void unload(Player player) - { - if (CitizensHook.isNPC(player)) - return; - - PlayerData data = SkillAPI.getPlayerData(player); - if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - { - data.record(player); - data.stopPassives(player); - } - - FlagManager.clearFlags(player); - BuffManager.clearData(player); - Combat.clearData(player); - DynamicSkill.clearCastData(player); - - player.setDisplayName(player.getName()); - if (VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { - player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(20); - } else { - player.setMaxHealth(20); - } - player.setWalkSpeed(0.2f); - SkillAPI.unloadPlayerData(player); - } - - /** - * Stops passives an applies death penalties when a player dies. - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR) - public void onDeath(PlayerDeathEvent event) - { - FlagManager.clearFlags(event.getEntity()); - BuffManager.clearData(event.getEntity()); - DynamicSkill.clearCastData(event.getEntity()); - - if (event.getEntity().hasMetadata("NPC")) - return; - - PlayerData data = SkillAPI.getPlayerData(event.getEntity()); - if (data.hasClass() && SkillAPI.getSettings().isWorldEnabled(event.getEntity().getWorld())) - { - data.stopPassives(event.getEntity()); - if (!SkillAPI.getSettings().shouldIgnoreExpLoss(event.getEntity().getWorld())) { - data.loseExp(); - } - } - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onDeath(final EntityDeathEvent event) { - DynamicSkill.clearCastData(event.getEntity()); - FlagManager.clearFlags(event.getEntity()); - BuffManager.clearData(event.getEntity()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onUnload(final ChunkUnloadEvent event) { - for (final Entity entity : event.getChunk().getEntities()) { - if (entity instanceof LivingEntity && !(entity instanceof Player)) { - final LivingEntity livingEntity = (LivingEntity) entity; - DynamicSkill.clearCastData(livingEntity); - FlagManager.clearFlags(livingEntity); - BuffManager.clearData(livingEntity); - } - } - } - - /** - * Handles experience when a block is broken - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBreak(BlockBreakEvent event) - { - if (event.getPlayer().hasMetadata("NPC")) - return; - - Player player = event.getPlayer(); - if (SkillAPI.getSettings().isUseOrbs() && player != null && SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - SkillAPI.getPlayerData(player).giveExp(event.getExpToDrop(), ExpSource.BLOCK_BREAK); - } - - /** - * Handles experience when ore is smelted in a furnace - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onSmelt(FurnaceExtractEvent event) - { - Player player = event.getPlayer(); - if (SkillAPI.getSettings().isUseOrbs() && player != null && SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - SkillAPI.getPlayerData(player).giveExp(event.getExpToDrop(), ExpSource.SMELT); - } - - /** - * Handles experience when a Bottle o' Enchanting breaks - * - * @param event event details - */ - @EventHandler - public void onExpBottleBreak(ExpBottleEvent event) - { - if (!(event.getEntity().getShooter() instanceof Player) || !SkillAPI.getSettings().isWorldEnabled(((Player) event.getEntity().getShooter()).getWorld())) - return; - - Player player = (Player) event.getEntity().getShooter(); - if (CitizensHook.isNPC(player)) - return; - - if (SkillAPI.getSettings().isUseOrbs()) - SkillAPI.getPlayerData(player).giveExp(event.getExperience(), ExpSource.EXP_BOTTLE); - } - - /** - * Prevents experience orbs from modifying the level bar when it - * is used for displaying class level. - * - * @param event event details - */ - @EventHandler(priority = EventPriority.HIGHEST) - public void onExpChange(PlayerExpChangeEvent event) - { - // Prevent it from changing the level bar when that is being used to display class level - if (!SkillAPI.getSettings().getLevelBar().equalsIgnoreCase("none") - && event.getPlayer().hasPermission(Permissions.EXP) - && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - { - event.setAmount(0); - } - } - - /** - * Handles updating level displays for players - * - * @param event event details - */ - @EventHandler - public void onLevelUp(final PlayerLevelUpEvent event) { - if (SkillAPI.getSettings().isShowClassLevel()) { - ClassBoardManager.updateLevel(event.getPlayerData()); - } - } - - /** - * Starts passive abilities again after respawning - * - * @param event event details - */ - @EventHandler - public void onRespawn(PlayerRespawnEvent event) - { - if (event.getPlayer().hasMetadata("NPC")) - return; - - PlayerData data = SkillAPI.getPlayerData(event.getPlayer()); - if (data.hasClass() && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - { - data.startPassives(event.getPlayer()); - data.updateScoreboard(); - } - } - - /** - * Damage type immunities - * - * @param event event details - */ - @EventHandler(ignoreCancelled = true) - public void onDamage(EntityDamageEvent event) - { - if (event.getEntity() instanceof LivingEntity && FlagManager.hasFlag((LivingEntity) event.getEntity(), "immune:" + event.getCause().name())) { - double multiplier = SkillAPI.getMetaDouble(event.getEntity(), ImmunityMechanic.META_KEY); - if (multiplier <= 0) - event.setCancelled(true); - else - event.setDamage(event.getDamage() * multiplier); - } - } - - /** - * Cancels food damaging the player when the bar is being used - * for GUI features instead of normal hunger. - * - * @param event event details - */ - @EventHandler - public void onStarve(EntityDamageEvent event) - { - if (event.getCause() == EntityDamageEvent.DamageCause.STARVATION - && !SkillAPI.getSettings().getFoodBar().equalsIgnoreCase("none")) - { - event.setCancelled(true); - } - } - - /** - * Cancels saturation heal - * - * @param event event details - */ - @EventHandler - public void onSaturationHeal(EntityRegainHealthEvent event) - { - String foodBar = SkillAPI.getSettings().getFoodBar().toLowerCase(); - if ((foodBar.equals("mana") || foodBar.equals("exp")) - && event.getRegainReason() == EntityRegainHealthEvent.RegainReason.SATIATED) - { - event.setCancelled(true); - } - } - - /** - * Launches physical damage events to differentiate skill damage from physical damage - * - * @param event event details - */ - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPhysicalDamage(EntityDamageByEntityEvent event) - { - if (Skill.isSkillDamage() - || event.getCause() == EntityDamageEvent.DamageCause.CUSTOM - || !(event.getEntity() instanceof LivingEntity) - || event.getDamage() <= 0) - { - return; - } - - PhysicalDamageEvent e = new PhysicalDamageEvent(ListenerUtil.getDamager(event), (LivingEntity) event.getEntity(), event.getDamage(), event.getDamager() instanceof Projectile); - Bukkit.getPluginManager().callEvent(e); - event.setDamage(e.getDamage()); - event.setCancelled(e.isCancelled()); - } - - /** - * Handles marking players as in combat - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onCombat(EntityDamageByEntityEvent event) - { - if (event.getCause() == EntityDamageEvent.DamageCause.CUSTOM - || !(event.getEntity() instanceof LivingEntity)) return; - - if (event.getEntity() instanceof Player) - { - Combat.applyCombat((Player) event.getEntity()); - } - - LivingEntity damager = ListenerUtil.getDamager(event); - if (damager instanceof Player) - { - Combat.applyCombat((Player) damager); - } - } - - /** - * Applies or removes SkillAPI features from a player upon switching worlds - * - * @param event event details - */ - @EventHandler - public void onWorldChange(PlayerChangedWorldEvent event) - { - if (event.getPlayer().hasMetadata("NPC")) - return; - - boolean oldEnabled = SkillAPI.getSettings().isWorldEnabled(event.getFrom()); - boolean newEnabled = SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld()); - if (oldEnabled && !newEnabled) - { - PlayerData data = SkillAPI.getPlayerData(event.getPlayer()); - data.clearBonuses(); - data.stopPassives(event.getPlayer()); - ClassBoardManager.clear(new VersionPlayer(event.getPlayer())); - event.getPlayer().setMaxHealth(SkillAPI.getSettings().getDefaultHealth()); - event.getPlayer().setHealth(SkillAPI.getSettings().getDefaultHealth()); - if (!SkillAPI.getSettings().getLevelBar().equalsIgnoreCase("none")) - { - event.getPlayer().setLevel(0); - event.getPlayer().setExp(0); - } - if (!SkillAPI.getSettings().getFoodBar().equalsIgnoreCase("none")) - { - event.getPlayer().setFoodLevel(20); - } - } - else if (!oldEnabled && newEnabled) { - init(event.getPlayer()); - } - } - - @EventHandler(ignoreCancelled = true) - public void onCommand(final PlayerCommandPreprocessEvent event) { - if (!SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - return; - - if (event.getMessage().equals("/clear")) { - handleClear(event.getPlayer()); - } - else if (event.getMessage().startsWith("/clear ")) { - handleClear(VersionManager.getPlayer(event.getMessage().substring(7))); - } - } - - @EventHandler - public void onCommand(final ServerCommandEvent event) { - if (event.getCommand().startsWith("clear ")) { - handleClear(VersionManager.getPlayer(event.getCommand().substring(6))); - } - } - - private void handleClear(final Player player) { - if (player != null) { - SkillAPI.schedule(() -> { - final PlayerData data = SkillAPI.getPlayerData(player); - data.getEquips().update(player); - - CLEAR_HANDLERS.forEach(handler -> handler.accept(player)); - }, 1); - } - } -} diff --git a/src/com/sucy/skill/manager/ResourceManager.java b/src/com/sucy/skill/manager/ResourceManager.java deleted file mode 100644 index 4cd2f650..00000000 --- a/src/com/sucy/skill/manager/ResourceManager.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * SkillAPI - * com.sucy.skill.manager.ResourceManager - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.manager; - -import com.sucy.skill.log.Logger; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Manages embedded resources within the .jar - */ -public class ResourceManager -{ - public static final String - QUESTS_FOLDER = "plugins" + File.separator + "Quests" + File.separator + "modules", - PLACEHOLDERS_FOLDER = "plugins" + File.separator + "PlaceholderAPI" + File.separator + "expansions"; - - /** - * Copies a resource embedded in the jar into the given folder - * - * @param name name of the file - * @param folder folder to put the file in - */ - public static void copyResource(String name, String folder) - { - try - { - // Prepare to copy the file - InputStream stream = ResourceManager.class.getResourceAsStream("/" + name); - OutputStream resStreamOut; - int readBytes; - byte[] buffer = new byte[4096]; - File dir = new File(folder); - dir.mkdirs(); - resStreamOut = new FileOutputStream(new File(dir + File.separator + name)); - - // Copy to the file - while ((readBytes = stream.read(buffer)) > 0) - { - resStreamOut.write(buffer, 0, readBytes); - } - - // Close the streams - stream.close(); - resStreamOut.close(); - } - catch (Exception ex) - { - Logger.bug("Failed to copy resource: " + name); - } - } - - /** - *

Places the SkillAPI module for Quests into the proper directory

- */ - public static void copyQuestsModule() - { - copyResource("SkillAPIModule.jar", QUESTS_FOLDER); - } - - public static void copyPlaceholdersModule() { - copyResource("SkillAPIPlaceholders.jar", PLACEHOLDERS_FOLDER); - } -} diff --git a/src/com/sucy/skill/SkillAPI.java b/src/main/java/com/sucy/skill/SkillAPI.java similarity index 81% rename from src/com/sucy/skill/SkillAPI.java rename to src/main/java/com/sucy/skill/SkillAPI.java index db352d9d..abf4d187 100644 --- a/src/com/sucy/skill/SkillAPI.java +++ b/src/main/java/com/sucy/skill/SkillAPI.java @@ -1,769 +1,833 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.sucy.skill; - -import com.rit.sucy.config.CommentedConfig; -import com.rit.sucy.config.CommentedLanguageConfig; -import com.rit.sucy.version.VersionManager; -import com.rit.sucy.version.VersionPlayer; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.particle.EffectManager; -import com.sucy.skill.api.particle.Particle; -import com.sucy.skill.api.player.PlayerAccounts; -import com.sucy.skill.api.player.PlayerClass; -import com.sucy.skill.api.player.PlayerData; -import com.sucy.skill.api.player.PlayerSkill; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.data.PlayerStats; -import com.sucy.skill.data.Settings; -import com.sucy.skill.data.io.ConfigIO; -import com.sucy.skill.data.io.IOManager; -import com.sucy.skill.data.io.SQLIO; -import com.sucy.skill.dynamic.DynamicClass; -import com.sucy.skill.dynamic.DynamicSkill; -import com.sucy.skill.gui.tool.GUITool; -import com.sucy.skill.hook.BungeeHook; -import com.sucy.skill.hook.PluginChecker; -import com.sucy.skill.listener.AddonListener; -import com.sucy.skill.listener.AttributeListener; -import com.sucy.skill.listener.BarListener; -import com.sucy.skill.listener.BindListener; -import com.sucy.skill.listener.BuffListener; -import com.sucy.skill.listener.CastCombatListener; -import com.sucy.skill.listener.CastItemListener; -import com.sucy.skill.listener.CastListener; -import com.sucy.skill.listener.CastOffhandListener; -import com.sucy.skill.listener.ComboListener; -import com.sucy.skill.listener.DeathListener; -import com.sucy.skill.listener.ExperienceListener; -import com.sucy.skill.listener.ClickListener; -import com.sucy.skill.listener.ItemListener; -import com.sucy.skill.listener.KillListener; -import com.sucy.skill.listener.LingeringPotionListener; -import com.sucy.skill.listener.MainListener; -import com.sucy.skill.listener.MechanicListener; -import com.sucy.skill.listener.PacketListener; -import com.sucy.skill.listener.SkillAPIListener; -import com.sucy.skill.listener.StatusListener; -import com.sucy.skill.listener.ToolListener; -import com.sucy.skill.manager.AttributeManager; -import com.sucy.skill.manager.ClassBoardManager; -import com.sucy.skill.manager.CmdManager; -import com.sucy.skill.manager.ComboManager; -import com.sucy.skill.manager.RegistrationManager; -import com.sucy.skill.manager.ResourceManager; -import com.sucy.skill.packet.PacketInjector; -import com.sucy.skill.task.CooldownTask; -import com.sucy.skill.task.GUITask; -import com.sucy.skill.task.ManaTask; -import com.sucy.skill.task.SaveTask; -import com.sucy.skill.thread.MainThread; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.metadata.MetadataValue; -import org.bukkit.metadata.Metadatable; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - *

The main class of the plugin which has the accessor methods into most of the API.

- *

You can retrieve a reference to this through Bukkit the same way as any other plugin.

- */ -public class SkillAPI extends JavaPlugin { - private static SkillAPI singleton; - - private final HashMap skills = new HashMap<>(); - private final HashMap classes = new HashMap<>(); - private final HashMap players = new HashMap<>(); - private final ArrayList groups = new ArrayList<>(); - - private final List listeners = new ArrayList<>(); - - private CommentedLanguageConfig language; - private Settings settings; - - private IOManager io; - private CmdManager cmd; - private ComboManager comboManager; - private RegistrationManager registrationManager; - private AttributeManager attributeManager; - - private MainThread mainThread; - - private boolean loaded = false; - private boolean disabling = false; - - /** - *

Enables SkillAPI, setting up listeners, managers, and loading data. This - * should not be called by other plugins.

- */ - @Override - public void onEnable() { - // Set up the singleton - if (singleton != null) { throw new IllegalStateException("Cannot enable SkillAPI twice!"); } - singleton = this; - - mainThread = new MainThread(); - Particle.init(); - EffectManager.init(); - - // Load settings - settings = new Settings(this); - language = new CommentedLanguageConfig(this, "language"); - language.checkDefaults(); - language.trim(); - language.save(); - - // Hook plugins - if (PluginChecker.isBungeeActive()) { BungeeHook.init(this); } - - // Set up managers - comboManager = new ComboManager(); - registrationManager = new RegistrationManager(this); - cmd = new CmdManager(this); - io = settings.isUseSql() ? new SQLIO(this) : new ConfigIO(this); - PlayerStats.init(); - ClassBoardManager.registerText(); - if (settings.isAttributesEnabled()) { attributeManager = new AttributeManager(this); } - - // Load classes and skills - registrationManager.initialize(); - - // Load group settings after groups are determined - settings.loadGroupSettings(); - - // Set up listeners - listen(new BindListener(), true); - listen(new BuffListener(), true); - listen(new MainListener(), true); - listen(new MechanicListener(), true); - listen(new StatusListener(), true); - listen(new ToolListener(), true); - listen(new KillListener(), true); - listen(new AddonListener(), true); - listen(new ItemListener(), settings.isCheckLore()); - listen(new BarListener(), settings.isSkillBarEnabled()); - if (VersionManager.isVersionAtLeast(VersionManager.V1_8_0)) { - final PacketInjector injector = new PacketInjector(this); - listen(new PacketListener(injector), true); - listen(new ClickListener(), settings.isCombosEnabled()); - } - listen(new ComboListener(), settings.isCombosEnabled()); - listen(new AttributeListener(), settings.isAttributesEnabled()); - listen(new CastListener(), settings.isUsingBars()); - listen( - new CastOffhandListener(), - settings.isCastEnabled() && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)); - listen(new CastItemListener(), settings.isUsingWand()); - listen(new CastCombatListener(), settings.isUsingCombat()); - listen(new DeathListener(), !VersionManager.isVersionAtLeast(11000)); - listen(new LingeringPotionListener(), VersionManager.isVersionAtLeast(VersionManager.V1_9_0)); - listen(new ExperienceListener(), settings.yieldsEnabled()); - - // Set up tasks - if (settings.isManaEnabled()) { MainThread.register(new ManaTask()); } - if (settings.isSkillBarCooldowns()) { MainThread.register(new CooldownTask()); } - if (settings.isAutoSave()) { MainThread.register(new SaveTask(this)); } - MainThread.register(new GUITask(this)); - - GUITool.init(); - - // Load player data - players.putAll(io.loadAll()); - for (PlayerAccounts accounts : players.values()) { accounts.getActiveData().init(accounts.getPlayer()); } - - // Must initialize listeners AFTER player data is loaded since the - // player objects would otherwise change and mess a lot of things up. - for (SkillAPIListener listener : listeners) { - listener.init(); - } - - ResourceManager.copyQuestsModule(); - ResourceManager.copyPlaceholdersModule(); - - loaded = true; - } - - private void listen(SkillAPIListener listener, boolean enabled) { - if (enabled) { - Bukkit.getPluginManager().registerEvents(listener, this); - listeners.add(listener); - } - } - - /** - *

Disables SkillAPI, saving data before unloading everything and disconnecting - * listeners. This should not be called by other plugins.

- */ - @Override - public void onDisable() { - // Validate instance - if (singleton != this) { throw new IllegalStateException("This is not a valid, enabled SkillAPI copy!"); } - - disabling = true; - - GUITool.cleanUp(); - EffectManager.cleanUp(); - - mainThread.disable(); - mainThread = null; - - for (SkillAPIListener listener : listeners) { listener.cleanup(); } - listeners.clear(); - - // Clear scoreboards - ClassBoardManager.clearAll(); - - // Clear skill bars and stop passives before disabling - for (Player player : VersionManager.getOnlinePlayers()) { - MainListener.unload(player); - } - - io.saveAll(); - - skills.clear(); - classes.clear(); - players.clear(); - - HandlerList.unregisterAll(this); - cmd.clear(); - - loaded = false; - disabling = false; - singleton = null; - } - - /** - * Checks whether or not SkillAPI has all its - * data loaded and running. - * - * @return true if loaded and set up, false otherwise - */ - public static boolean isLoaded() { - return singleton != null && singleton.loaded; - } - - /** - * @return SkillAPI singleton if available - * - * @throws IllegalStateException if SkillAPI isn't enabled - */ - private static SkillAPI singleton() { - if (singleton == null) { - throw new IllegalStateException( - "Cannot use SkillAPI methods before it is enabled - add it to your plugin.yml as a dependency"); - } - return singleton; - } - - /** - * Retrieves the settings data controlling SkillAPI - * - * @return SkillAPI settings data - */ - public static Settings getSettings() { - return singleton().settings; - } - - /** - * Retrieves the language file data for SkillAPI - * - * @return SkillAPI language file data - */ - public static CommentedLanguageConfig getLanguage() { - return singleton().language; - } - - /** - * Retrieves the manager for click cast combos - * - * @return click combo manager - */ - public static ComboManager getComboManager() { - return singleton().comboManager; - } - - /** - * Retrieves the attribute manager for SkillAPI - * - * @return attribute manager - */ - public static AttributeManager getAttributeManager() { - return singleton().attributeManager; - } - - /** - * Retrieves a skill by name. If no skill is found with the name, null is - * returned instead. - * - * @param name name of the skill - * - * @return skill with the name or null if not found - */ - public static Skill getSkill(String name) { - if (name == null) { return null; } - return singleton().skills.get(name.toLowerCase()); - } - - /** - * Retrieves the registered skill data for SkillAPI. It is recommended that you - * don't edit this map. Instead, use "addSkill" and "addSkills" instead. - * - * @return the map of registered skills - */ - public static HashMap getSkills() { - return singleton().skills; - } - - /** - * Checks whether or not a skill is registered. - * - * @param name name of the skill - * - * @return true if registered, false otherwise - */ - public static boolean isSkillRegistered(String name) { - return getSkill(name) != null; - } - - /** - * Checks whether or not a skill is registered - * - * @param skill the skill to check - * - * @return true if registered, false otherwise - */ - public static boolean isSkillRegistered(PlayerSkill skill) { - return isSkillRegistered(skill.getData().getName()); - } - - /** - * Checks whether or not a skill is registered - * - * @param skill the skill to check - * - * @return true if registered, false otherwise - */ - public static boolean isSkillRegistered(Skill skill) { - return isSkillRegistered(skill.getName()); - } - - /** - * Retrieves a class by name. If no skill is found with the name, null is - * returned instead. - * - * @param name name of the class - * - * @return class with the name or null if not found - */ - public static RPGClass getClass(String name) { - if (name == null) { return null; } - return singleton().classes.get(name.toLowerCase()); - } - - /** - * Retrieves the registered class data for SkillAPI. It is recommended that you - * don't edit this map. Instead, use "addClass" and "addClasses" instead. - * - * @return the map of registered skills - */ - public static HashMap getClasses() { - return singleton().classes; - } - - /** - * Retrieves a list of base classes that don't profess from another class - * - * @return the list of base classes - */ - public static ArrayList getBaseClasses(String group) { - ArrayList list = new ArrayList<>(); - for (RPGClass c : singleton.classes.values()) { - if (!c.hasParent() && c.getGroup().equals(group)) { list.add(c); } - } - return list; - } - - /** - * Checks whether or not a class is registered. - * - * @param name name of the class - * - * @return true if registered, false otherwise - */ - public static boolean isClassRegistered(String name) { - return getClass(name) != null; - } - - /** - * Checks whether or not a class is registered. - * - * @param playerClass the class to check - * - * @return true if registered, false otherwise - */ - public static boolean isClassRegistered(PlayerClass playerClass) { - return isClassRegistered(playerClass.getData().getName()); - } - - /** - * Checks whether or not a class is registered. - * - * @param rpgClass the class to check - * - * @return true if registered, false otherwise - */ - public static boolean isClassRegistered(RPGClass rpgClass) { - return isClassRegistered(rpgClass.getName()); - } - - /** - * Retrieves the active class data for the player. If no data is found for the - * player, a new set of data will be created and returned. - * - * @param player player to get the data for - * - * @return the class data of the player - */ - public static PlayerData getPlayerData(OfflinePlayer player) { - if (player == null) { return null; } - return getPlayerAccountData(player).getActiveData(); - } - - /** - * Loads the data for a player when they join the server. This is handled - * by the API and doesn't need to be used elsewhere unless you want to - * load a player's data without them logging on. This should be run - * asynchronously since it is loading configuration files. - * - * @param player player to load the data for - */ - public static PlayerAccounts loadPlayerData(OfflinePlayer player) { - if (player == null) { return null; } - - // Already loaded for some reason, no need to load again - String id = new VersionPlayer(player).getIdString(); - if (singleton().players.containsKey(id)) { return singleton.players.get(id); } - - // Load the data - PlayerAccounts data = singleton.io.loadData(player); - singleton.players.put(id, data); - return data; - } - - /** - * Used to fake player data until SQL data is loaded when both SQL and the SQL delay are enabled. - * This should not be used by other plugins. If the player data already exists, this does nothing. - * - * @param player player to fake data for - */ - public static void initFakeData(final OfflinePlayer player) { - singleton().players.computeIfAbsent(player.getUniqueId().toString(), id -> new PlayerAccounts(player)); - } - - /** - * Do not use this method outside of onJoin. This will delete any progress a player - * has made since joining. - */ - public static void reloadPlayerData(final Player player) { - singleton().players.remove(player.getUniqueId().toString()); - loadPlayerData(player); - } - - /** - * Saves all player data to the configs. This - * should be called asynchronously to avoid problems - * with the main server loop. - */ - public static void saveData() { - singleton().io.saveAll(); - } - - /** - * Checks whether or not SkillAPI currently has loaded data for the - * given player. This returning false doesn't necessarily mean the - * player doesn't have any data at all, just not data that is - * currently loaded. - * - * @param player player to check for - * - * @return true if has loaded data, false otherwise - */ - public static boolean hasPlayerData(OfflinePlayer player) { - return singleton != null && player != null && singleton.players.containsKey(new VersionPlayer(player).getIdString()); - } - - /** - * Unloads player data from memory, saving it to the config - * first and then removing it from the map. - * - * @param player player to unload data for - */ - public static void unloadPlayerData(final OfflinePlayer player) { - if (singleton == null || player == null || singleton.disabling || !singleton.players.containsKey(new VersionPlayer(player).getIdString())) { - return; - } - - singleton.getServer().getScheduler().runTaskAsynchronously(singleton, () -> { - PlayerAccounts accounts = getPlayerAccountData(player); - singleton.io.saveData(accounts); - singleton.players.remove(new VersionPlayer(player).getIdString()); - }); - } - - /** - * Retrieves all class data for the player. This includes the active and - * all inactive accounts the player has. If no data is found, a new set - * of data will be created and returned. - * - * @param player player to get the data for - * - * @return the class data of the player - */ - public static PlayerAccounts getPlayerAccountData(OfflinePlayer player) { - if (player == null) { return null; } - - String id = new VersionPlayer(player).getIdString(); - if (!singleton().players.containsKey(id)) { - PlayerAccounts data = loadPlayerData(player); - singleton.players.put(id, data); - return data; - } else { return singleton.players.get(id); } - } - - /** - * Retrieves all the player data of SkillAPI. It is recommended not to - * modify this map. Instead, use helper methods within individual player data. - * - * @return all SkillAPI player data - */ - public static HashMap getPlayerAccountData() { - return singleton().players; - } - - /** - * Retrieves the list of active class groups used by - * registered classes - * - * @return list of active class groups - */ - public static List getGroups() { - return singleton().groups; - } - - /** - * This adds a dynamic skill to the skill list. This should - * not be called by other plugins. - * - * @param skill the dynamic skill to register - */ - public void addDynamicSkill(DynamicSkill skill) { - if (registrationManager.isAddingDynamicSkills()) { skills.put(skill.getName().toLowerCase(), skill); } else { - throw new IllegalStateException("Cannot add dynamic skills from outside SkillAPI"); - } - } - - /** - * Registers a new skill with SkillAPI. If this is called outside of the method - * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin - * in your main class and call this from the provided "registerSkills" method. - * - * @param skill skill to register - */ - public void addSkill(Skill skill) { - skill = registrationManager.validate(skill); - if (skill != null) { skills.put(skill.getName().toLowerCase(), skill); } - } - - /** - * Registers multiple new skills with SkillAPI. If this is called outside of the method - * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin - * in your main class and call this from the provided "registerSkills" method. - * - * @param skills skills to register - */ - public void addSkills(Skill... skills) { - for (Skill skill : skills) { addSkill(skill); } - } - - /** - * Registers a new class with SkillAPI. If this is called outside of the method - * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin - * in your main class and call this from the provided "registerClasses" method. - * - * @param rpgClass class to register - */ - public void addClass(RPGClass rpgClass) { - rpgClass = registrationManager.validate(rpgClass); - if (rpgClass != null) { - classes.put(rpgClass.getName().toLowerCase(), rpgClass); - ClassBoardManager.registerClass(rpgClass); - if (!groups.contains(rpgClass.getGroup())) { groups.add(rpgClass.getGroup()); } - } - } - - /** - * Adds a dynamic class which ignores validation. This should only - * be used by the API as other plugins should use the regular addClass. - * - * @param rpgClass dynamic class to add - */ - public void addDynamicClass(DynamicClass rpgClass) { - String key; - if (rpgClass != null && !classes.containsKey(key = rpgClass.getName().toLowerCase())) { - classes.put(key, rpgClass); - ClassBoardManager.registerClass(rpgClass); - if (!groups.contains(rpgClass.getGroup())) { groups.add(rpgClass.getGroup()); } - } - } - - /** - * Registers a new class with SkillAPI. If this is called outside of the method - * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin - * in your main class and call this from the provided "registerClasses" method. - * - * @param classes classes to register - */ - public void addClasses(RPGClass... classes) { - for (RPGClass rpgClass : classes) { addClass(rpgClass); } - } - - /** - * Schedules a delayed task - * - * @param runnable the task to schedule - * @param delay the delay in ticks - */ - public static BukkitTask schedule(BukkitRunnable runnable, int delay) { - return runnable.runTaskLater(singleton(), delay); - } - - /** - * Schedules a delayed task - * - * @param runnable the task to schedule - * @param delay the delay in ticks - */ - public static BukkitTask schedule(Runnable runnable, int delay) { - return Bukkit.getScheduler().runTaskLater(singleton, runnable, delay); - } - - /** - * Schedules a repeating task - * - * @param runnable the task to schedule - * @param delay the delay in ticks before the first tick - * @param period how often to run in ticks - */ - public static BukkitTask schedule(BukkitRunnable runnable, int delay, int period) { - return runnable.runTaskTimer(singleton(), delay, period); - } - - /** - * Sets a value to an entity's metadata - * - * @param target entity to set to - * @param key key to store under - * @param value value to store - */ - public static void setMeta(Metadatable target, String key, Object value) { - target.setMetadata(key, new FixedMetadataValue(singleton(), value)); - } - - /** - * Retrieves metadata from an entity - * - * @param target entity to retrieve from - * @param key key the value was stored under - * - * @return the stored value - */ - public static Object getMeta(Metadatable target, String key) { - List meta = target.getMetadata(key); - return meta == null || meta.size() == 0 ? null : meta.get(0).value(); - } - - /** - * Retrieves metadata from an entity - * - * @param target entity to retrieve from - * @param key key the value was stored under - * - * @return the stored value - */ - public static int getMetaInt(Metadatable target, String key) { - return target.getMetadata(key).get(0).asInt(); - } - - /** - * Retrieves metadata from an entity - * - * @param target entity to retrieve from - * @param key key the value was stored under - * - * @return the stored value - */ - public static double getMetaDouble(Metadatable target, String key) { - return target.getMetadata(key).get(0).asDouble(); - } - - /** - * Removes metadata from an entity - * - * @param target entity to remove from - * @param key key metadata was stored under - */ - public static void removeMeta(Metadatable target, String key) { - target.removeMetadata(key, singleton()); - } - - /** - * Grabs a config for SkillAPI - * - * @param name config file name - * - * @return config data - */ - public static CommentedConfig getConfig(String name) { - return new CommentedConfig(singleton, name); - } - - /** - * Reloads the plugin - */ - public static void reload() { - SkillAPI inst = singleton(); - inst.onDisable(); - inst.onEnable(); - } -} +/** + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.sucy.skill; + +import com.rit.sucy.config.CommentedConfig; +import com.rit.sucy.config.CommentedLanguageConfig; +import com.rit.sucy.version.VersionManager; +import com.sucy.skill.api.classes.RPGClass; +import com.sucy.skill.api.event.PlayerSaveEvent; +import com.sucy.skill.api.particle.EffectManager; +import com.sucy.skill.api.particle.Particle; +import com.sucy.skill.api.player.PlayerAccounts; +import com.sucy.skill.api.player.PlayerClass; +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.api.player.PlayerSkill; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.data.PlayerStats; +import com.sucy.skill.data.Settings; +import com.sucy.skill.data.io.ConfigIO; +import com.sucy.skill.data.io.IOManager; +import com.sucy.skill.data.io.SQLIO; +import com.sucy.skill.dynamic.DynamicClass; +import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.gui.tool.GUITool; +import com.sucy.skill.hook.BungeeHook; +import com.sucy.skill.hook.PlaceholderAPIHook; +import com.sucy.skill.hook.PluginChecker; +import com.sucy.skill.listener.*; +import com.sucy.skill.manager.*; +import com.sucy.skill.packet.PacketInjector; +import com.sucy.skill.task.CooldownTask; +import com.sucy.skill.task.GUITask; +import com.sucy.skill.task.RegenTask; +import com.sucy.skill.task.RegenTask; +import com.sucy.skill.task.SaveTask; +import com.sucy.skill.thread.MainThread; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.metadata.MetadataValue; +import org.bukkit.metadata.Metadatable; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + *

The main class of the plugin which has the accessor methods into most of the API.

+ *

You can retrieve a reference to this through Bukkit the same way as any other plugin.

+ */ +public class SkillAPI extends JavaPlugin { + private static SkillAPI singleton; + + private final HashMap skills = new HashMap<>(); + private final HashMap classes = new HashMap<>(); + public final HashMap players = new HashMap<>(); + private final ArrayList groups = new ArrayList<>(); + + private final List listeners = new ArrayList<>(); + + private CommentedLanguageConfig language; + private Settings settings; + + private IOManager io; + private CmdManager cmd; + private ComboManager comboManager; + private RegistrationManager registrationManager; + private AttributeManager attributeManager; + + private MainThread mainThread; + private BukkitTask regenTask; + + private boolean loaded = false; + private boolean disabling = false; + private boolean enabledSkillBars = true; + public static boolean debug = false; + + public boolean isSkillBarsEnabled() { + return enabledSkillBars; + } + + public void setSkillBarsEnabled(boolean newValue) { + enabledSkillBars = newValue; + } + + /** + *

Enables SkillAPI, setting up listeners, managers, and loading data. This + * should not be called by other plugins.

+ */ + @Override + public void onEnable() { + // Set up the singleton + if (singleton != null) { throw new IllegalStateException("Cannot enable SkillAPI twice!"); } + singleton = this; + + mainThread = new MainThread(); + Particle.init(); + EffectManager.init(); + + // Load settings + settings = new Settings(this); + language = new CommentedLanguageConfig(this, "language"); + language.checkDefaults(); + language.trim(); + language.save(); + + // Hook plugins + if (PluginChecker.isBungeeActive()) { BungeeHook.init(this); } + + // Set up managers + comboManager = new ComboManager(); + registrationManager = new RegistrationManager(this); + cmd = new CmdManager(this); + this.getCommand("class").setExecutor(cmd); + io = settings.isUseSql() ? new SQLIO(this) : new ConfigIO(this); + PlayerStats.init(); + // ClassBoardManager.registerText(); + if (settings.isAttributesEnabled()) { attributeManager = new AttributeManager(this); } + + // Load classes and skills + registrationManager.initialize(); + + // Load group settings after groups are determined + settings.loadGroupSettings(); + + // Set up listeners + listen(new BindListener(), true); + listen(new BuffListener(), true); + listen(new MainListener(this), true); + listen(new MechanicListener(), true); + listen(new StatusListener(), true); + listen(new ToolListener(), true); + // listen(new KillListener(), true); + listen(new AddonListener(), true); + listen(new ItemListener(this), settings.isCheckLore()); + listen(new BarListener(), settings.isSkillBarEnabled()); + listen(new ClickListener(), true); + //if (VersionManager.isVersionAtLeast(VersionManager.V1_8_0)) { + // final PacketInjector injector = new PacketInjector(this); + // listen(new PacketListener(injector), true); + //} + listen(new NeoComboListener(), true); + listen(new ComboListener(), settings.isCombosEnabled()); + listen(new AttributeListener(), settings.isAttributesEnabled()); + listen(new CastListener(), settings.isUsingBars()); + listen( + new CastOffhandListener(), + settings.isCastEnabled() && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)); + listen(new CastItemListener(), settings.isUsingWand()); + listen(new CastCombatListener(), settings.isUsingCombat()); + listen(new DeathListener(), !VersionManager.isVersionAtLeast(11000)); + listen(new LingeringPotionListener(), VersionManager.isVersionAtLeast(VersionManager.V1_9_0)); + listen(new ExperienceListener(), settings.yieldsEnabled()); + + // Set up tasks (Mana task disabled because it must be async) + // if (settings.isManaEnabled()) { MainThread.register(new ManaTask()); } + if (settings.isSkillBarCooldowns()) { MainThread.register(new CooldownTask()); } + if (settings.isAutoSave()) { MainThread.register(new SaveTask(this)); } + MainThread.register(new GUITask(this)); + + GUITool.init(); + + // Load player data + players.putAll(io.loadAll()); + for (PlayerAccounts accounts : players.values()) { accounts.getActiveData().init(accounts.getPlayer()); } + + // Must initialize listeners AFTER player data is loaded since the + // player objects would otherwise change and mess a lot of things up. + for (SkillAPIListener listener : listeners) { + listener.init(); + } + + + // Non-task mana gain + if (settings.isManaEnabled()) { + regenTask = Bukkit.getScheduler().runTaskTimer( + this, + new RegenTask(), + SkillAPI.getSettings().getGainFreq(), + SkillAPI.getSettings().getGainFreq() + ); + } + + // Removed due des-use +// ResourceManager.copyQuestsModule(); + PlaceholderAPIHook.registerPlaceholder(this); + + loaded = true; + } + + private void listen(SkillAPIListener listener, boolean enabled) { + if (enabled) { + Bukkit.getPluginManager().registerEvents(listener, this); + listeners.add(listener); + } + } + + /** + *

Disables SkillAPI, saving data before unloading everything and disconnecting + * listeners. This should not be called by other plugins.

+ */ + @Override + public void onDisable() { + // Validate instance + if (singleton != this) { throw new IllegalStateException("This is not a valid, enabled SkillAPI copy!"); } + + disabling = true; + + GUITool.cleanUp(); + EffectManager.cleanUp(); + + mainThread.disable(); + mainThread = null; + + if (regenTask != null) { + regenTask.cancel(); + regenTask = null; + } + + + for (SkillAPIListener listener : listeners) { listener.cleanup(); } + listeners.clear(); + + // Clear scoreboards + // ClassBoardManager.clearAll(); + + // Clear skill bars and stop passives before disabling + for (Player player : Bukkit.getOnlinePlayers()) { + MainListener.unload(player); + } + + // Only save on disable if not an instance + // Currently disabled because it takes so long + //if (!settings.isInstance()) { + // io.saveAll(); + //} + + skills.clear(); + classes.clear(); + players.clear(); + + HandlerList.unregisterAll(this); + cmd.clear(); + + loaded = false; + disabling = false; + singleton = null; + } + + /** + * Checks whether or not SkillAPI has all its + * data loaded and running. + * + * @return true if loaded and set up, false otherwise + */ + public static boolean isLoaded() { + return singleton != null && singleton.loaded; + } + + /** + * @return SkillAPI singleton if available + * + * @throws IllegalStateException if SkillAPI isn't enabled + */ + private static SkillAPI singleton() { + if (singleton == null) { + throw new IllegalStateException( + "Cannot use SkillAPI methods before it is enabled - add it to your plugin.yml as a dependency"); + } + return singleton; + } + + /** + * Retrieves the settings data controlling SkillAPI + * + * @return SkillAPI settings data + */ + public static Settings getSettings() { + return singleton().settings; + } + + /** + * Retrieves the language file data for SkillAPI + * + * @return SkillAPI language file data + */ + public static CommentedLanguageConfig getLanguage() { + return singleton().language; + } + + /** + * Retrieves the manager for click cast combos + * + * @return click combo manager + */ + public static ComboManager getComboManager() { + return singleton().comboManager; + } + + /** + * Retrieves the attribute manager for SkillAPI + * + * @return attribute manager + */ + public static AttributeManager getAttributeManager() { + return singleton().attributeManager; + } + + /** + * Retrieves a skill by name. If no skill is found with the name, null is + * returned instead. + * + * @param name name of the skill + * + * @return skill with the name or null if not found + */ + public static Skill getSkill(String name) { + if (name == null) { return null; } + return singleton().skills.get(name.toLowerCase()); + } + + /** + * Retrieves the registered skill data for SkillAPI. It is recommended that you + * don't edit this map. Instead, use "addSkill" and "addSkills" instead. + * + * @return the map of registered skills + */ + public static HashMap getSkills() { + return singleton().skills; + } + + /** + * Checks whether or not a skill is registered. + * + * @param name name of the skill + * + * @return true if registered, false otherwise + */ + public static boolean isSkillRegistered(String name) { + return getSkill(name) != null; + } + + /** + * Checks whether or not a skill is registered + * + * @param skill the skill to check + * + * @return true if registered, false otherwise + */ + public static boolean isSkillRegistered(PlayerSkill skill) { + return isSkillRegistered(skill.getData().getName()); + } + + /** + * Checks whether or not a skill is registered + * + * @param skill the skill to check + * + * @return true if registered, false otherwise + */ + public static boolean isSkillRegistered(Skill skill) { + return isSkillRegistered(skill.getName()); + } + + /** + * Retrieves a class by name. If no skill is found with the name, null is + * returned instead. + * + * @param name name of the class + * + * @return class with the name or null if not found + */ + public static RPGClass getClass(String name) { + if (name == null) { return null; } + return singleton().classes.get(name.toLowerCase()); + } + + /** + * Retrieves the registered class data for SkillAPI. It is recommended that you + * don't edit this map. Instead, use "addClass" and "addClasses" instead. + * + * @return the map of registered skills + */ + public static HashMap getClasses() { + return singleton().classes; + } + + /** + * Retrieves a list of base classes that don't profess from another class + * + * @return the list of base classes + */ + public static ArrayList getBaseClasses(String group) { + ArrayList list = new ArrayList<>(); + for (RPGClass c : singleton.classes.values()) { + if (!c.hasParent() && c.getGroup().equals(group)) { list.add(c); } + } + return list; + } + + /** + * Checks whether or not a class is registered. + * + * @param name name of the class + * + * @return true if registered, false otherwise + */ + public static boolean isClassRegistered(String name) { + return getClass(name) != null; + } + + /** + * Checks whether or not a class is registered. + * + * @param playerClass the class to check + * + * @return true if registered, false otherwise + */ + public static boolean isClassRegistered(PlayerClass playerClass) { + return isClassRegistered(playerClass.getData().getName()); + } + + /** + * Checks whether or not a class is registered. + * + * @param rpgClass the class to check + * + * @return true if registered, false otherwise + */ + public static boolean isClassRegistered(RPGClass rpgClass) { + return isClassRegistered(rpgClass.getName()); + } + + /** + * Retrieves the active class data for the player. If no data is found for the + * player, a new set of data will be created and returned. + * + * @param player player to get the data for + * + * @return the class data of the player + */ + public static PlayerData getPlayerData(OfflinePlayer player) { + if (player == null) { return null; } + PlayerAccounts account = getPlayerAccountData(player); + return account == null ? null : account.getActiveData(); + } + + public static PlayerAccounts loadPlayerDataSQL(OfflinePlayer player) { + if (player == null) { return null; } + + // Load the data + return doLoad(player); + } + + /** + * Loads the data for a player when they join the server. This is handled + * by the API and doesn't need to be used elsewhere unless you want to + * load a player's data without them logging on. This should be run + * asynchronously since it is loading configuration files. + * + * @param player player to load the data for + */ + public static PlayerAccounts loadPlayerData(OfflinePlayer player) { + if (player == null) { return null; } + + // Already loaded for some reason, no need to load again + String id = player.getUniqueId().toString(); + if (singleton().players.containsKey(id)) { return singleton.players.get(id); } + + // Load the data + return doLoad(player); + } + + private static PlayerAccounts doLoad(OfflinePlayer player) { + // Load the data + PlayerAccounts data = singleton.io.loadData(player); + + // Only place players if the data successfully loaded + // This stops saving null data if failed load + if (data != null) { + singleton.players.put(player.getUniqueId().toString(), data); + } + return data; + } + + /** + * Used to fake player data until SQL data is loaded when both SQL and the SQL delay are enabled. + * This should not be used by other plugins. If the player data already exists, this does nothing. + * + * @param player player to fake data for + */ + public static void initFakeData(final OfflinePlayer player) { + singleton().players.computeIfAbsent(player.getUniqueId().toString(), id -> new PlayerAccounts(player)); + } + + /** + * Do not use this method outside of onJoin. This will delete any progress a player + * has made since joining. + */ + public static void reloadPlayerData(final Player player) { + doLoad(player); + } + + /** + * Saves all player data to the configs. This + * should be called asynchronously to avoid problems + * with the main server loop. + */ + public static void saveData() { + singleton().io.saveAll(); + } + + public static void saveSingle(Player p) { + if (p != null) { + PlayerAccounts data = getPlayerAccountData(p); + singleton().io.saveData(data); + Bukkit.getPluginManager().callEvent(new PlayerSaveEvent(p)); + } + } + + public static boolean isLoaded(Player p) { + return !MainListener.loadingPlayers.contains(p.getUniqueId()); + } + + /** + * Checks whether or not SkillAPI currently has loaded data for the + * given player. This returning false doesn't necessarily mean the + * player doesn't have any data at all, just not data that is + * currently loaded. + * + * @param player player to check for + * + * @return true if has loaded data, false otherwise + */ + public static boolean hasPlayerData(OfflinePlayer player) { + return singleton != null && player != null && singleton.players.containsKey(player.getUniqueId().toString()); + } + + /** + * Unloads player data from memory, saving it to the config + * first and then removing it from the map. + * + * @param player player to unload data for + */ + public static void unloadPlayerData(final OfflinePlayer player) { + unloadPlayerData(player, false); + } + + public static void unloadPlayerData(final OfflinePlayer player, final boolean skipSaving) { + if (singleton == null || player == null || singleton.disabling || !singleton.players.containsKey(player.getUniqueId().toString())) { + return; + } + + singleton.getServer().getScheduler().runTaskAsynchronously(singleton, () -> { + PlayerAccounts accounts = getPlayerAccountData(player); + singleton.io.saveData(accounts); + singleton.players.remove(player.getUniqueId().toString()); + }); + } + + /** + * Retrieves all class data for the player. This includes the active and + * all inactive accounts the player has. If no data is found, a new set + * of data will be created and returned. + * + * @param player player to get the data for + * + * @return the class data of the player + */ + public static PlayerAccounts getPlayerAccountData(OfflinePlayer player) { + if (player == null) { return null; } + + String id = player.getUniqueId().toString(); + if (!singleton().players.containsKey(id)) { + PlayerAccounts data = loadPlayerData(player); + singleton.players.put(id, data); + return data; + } else { return singleton.players.get(id); } + } + + /** + * Retrieves all the player data of SkillAPI. It is recommended not to + * modify this map. Instead, use helper methods within individual player data. + * + * @return all SkillAPI player data + */ + public static HashMap getPlayerAccountData() { + return singleton().players; + } + + /** + * Retrieves the list of active class groups used by + * registered classes + * + * @return list of active class groups + */ + public static List getGroups() { + return singleton().groups; + } + + /** + * This adds a dynamic skill to the skill list. This should + * not be called by other plugins. + * + * @param skill the dynamic skill to register + */ + public void addDynamicSkill(DynamicSkill skill) { + if (registrationManager.isAddingDynamicSkills()) { skills.put(skill.getName().toLowerCase(), skill); } else { + throw new IllegalStateException("Cannot add dynamic skills from outside SkillAPI"); + } + } + + /** + * Registers a new skill with SkillAPI. If this is called outside of the method + * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin + * in your main class and call this from the provided "registerSkills" method. + * + * @param skill skill to register + */ + public void addSkill(Skill skill) { + skill = registrationManager.validate(skill); + if (skill != null) { skills.put(skill.getName().toLowerCase(), skill); } + } + + /** + * Registers multiple new skills with SkillAPI. If this is called outside of the method + * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin + * in your main class and call this from the provided "registerSkills" method. + * + * @param skills skills to register + */ + public void addSkills(Skill... skills) { + for (Skill skill : skills) { addSkill(skill); } + } + + /** + * Registers a new class with SkillAPI. If this is called outside of the method + * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin + * in your main class and call this from the provided "registerClasses" method. + * + * @param rpgClass class to register + */ + public void addClass(RPGClass rpgClass) { + rpgClass = registrationManager.validate(rpgClass); + if (rpgClass != null) { + classes.put(rpgClass.getName().toLowerCase(), rpgClass); + // ClassBoardManager.registerClass(rpgClass); + if (!groups.contains(rpgClass.getGroup())) { groups.add(rpgClass.getGroup()); } + } + } + + /** + * Adds a dynamic class which ignores validation. This should only + * be used by the API as other plugins should use the regular addClass. + * + * @param rpgClass dynamic class to add + */ + public void addDynamicClass(DynamicClass rpgClass) { + String key; + if (rpgClass != null && !classes.containsKey(key = rpgClass.getName().toLowerCase())) { + classes.put(key, rpgClass); + // ClassBoardManager.registerClass(rpgClass); + if (!groups.contains(rpgClass.getGroup())) { groups.add(rpgClass.getGroup()); } + } + } + + /** + * Registers a new class with SkillAPI. If this is called outside of the method + * provided in SkillPlugin, this will throw an error. You should implement SkillPlugin + * in your main class and call this from the provided "registerClasses" method. + * + * @param classes classes to register + */ + public void addClasses(RPGClass... classes) { + for (RPGClass rpgClass : classes) { addClass(rpgClass); } + } + + /** + * Schedules a delayed task + * + * @param runnable the task to schedule + * @param delay the delay in ticks + */ + public static BukkitTask schedule(BukkitRunnable runnable, int delay) { + return runnable.runTaskLater(singleton(), delay); + } + + /** + * Schedules a delayed task + * + * @param runnable the task to schedule + * @param delay the delay in ticks + */ + public static BukkitTask schedule(Runnable runnable, int delay) { + return Bukkit.getScheduler().runTaskLater(singleton, runnable, delay); + } + + /** + * Schedules an async delayed task + * + * @param runnable the task to schedule + * @param delay the delay in ticks + */ + public static BukkitTask scheduleAsync(Runnable runnable, int delay) { + return Bukkit.getScheduler().runTaskLaterAsynchronously(singleton, runnable, delay); + } + /** + * Schedules an async delayed task + * + * @param runnable the task to schedule + * @param delay the delay in ticks + */ + public static BukkitTask scheduleAsyncRepeat(Runnable runnable, int delay) { + return Bukkit.getScheduler().runTaskTimerAsynchronously(singleton, runnable, delay, delay); + } + + /** + * Schedules a repeating task + * + * @param runnable the task to schedule + * @param delay the delay in ticks before the first tick + * @param period how often to run in ticks + */ + public static BukkitTask schedule(BukkitRunnable runnable, int delay, int period) { + return runnable.runTaskTimer(singleton(), delay, period); + } + + /** + * Sets a value to an entity's metadata + * + * @param target entity to set to + * @param key key to store under + * @param value value to store + */ + public static void setMeta(Metadatable target, String key, Object value) { + target.setMetadata(key, new FixedMetadataValue(singleton(), value)); + } + + /** + * Retrieves metadata from an entity + * + * @param target entity to retrieve from + * @param key key the value was stored under + * + * @return the stored value + */ + public static Object getMeta(Metadatable target, String key) { + List meta = target.getMetadata(key); + return meta == null || meta.size() == 0 ? null : meta.get(0).value(); + } + + /** + * Retrieves metadata from an entity + * + * @param target entity to retrieve from + * @param key key the value was stored under + * + * @return the stored value + */ + public static int getMetaInt(Metadatable target, String key) { + return target.getMetadata(key).get(0).asInt(); + } + + /** + * Retrieves metadata from an entity + * + * @param target entity to retrieve from + * @param key key the value was stored under + * + * @return the stored value + */ + public static double getMetaDouble(Metadatable target, String key) { + return target.getMetadata(key).get(0).asDouble(); + } + + /** + * Removes metadata from an entity + * + * @param target entity to remove from + * @param key key metadata was stored under + */ + public static void removeMeta(Metadatable target, String key) { + target.removeMetadata(key, singleton()); + } + + /** + * Grabs a config for SkillAPI + * + * @param name config file name + * + * @return config data + */ + public static CommentedConfig getConfig(String name) { + return new CommentedConfig(singleton, name); + } + + /** + * Reloads the plugin + */ + public static void reload() { + SkillAPI inst = singleton(); + inst.onDisable(); + inst.onEnable(); + } +} diff --git a/src/com/sucy/skill/api/CombatProtection.java b/src/main/java/com/sucy/skill/api/CombatProtection.java similarity index 100% rename from src/com/sucy/skill/api/CombatProtection.java rename to src/main/java/com/sucy/skill/api/CombatProtection.java diff --git a/src/com/sucy/skill/api/DefaultCombatProtection.java b/src/main/java/com/sucy/skill/api/DefaultCombatProtection.java similarity index 100% rename from src/com/sucy/skill/api/DefaultCombatProtection.java rename to src/main/java/com/sucy/skill/api/DefaultCombatProtection.java diff --git a/src/main/java/com/sucy/skill/api/ParticleBuilder.java b/src/main/java/com/sucy/skill/api/ParticleBuilder.java new file mode 100644 index 00000000..a23a2836 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/ParticleBuilder.java @@ -0,0 +1,94 @@ +package com.sucy.skill.api; + +import java.util.Collections; +import java.util.ArrayList; +import org.bukkit.Particle; +import org.bukkit.entity.Entity; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class ParticleBuilder { + private Particle particle; + private Location loc; + private float dx, dy, dz, extra; + private int count; + private Particle.DustOptions dustData; + private BlockData blockData; + private ItemStack itemData; + private ArrayList receivers = new ArrayList(); + + public ParticleBuilder(Particle particle) { + this.particle = particle; + } + + public ParticleBuilder location(Location loc) { + this.loc = loc; + return this; + } + + public ParticleBuilder offset(float dx, float dy, float dz) { + this.dx = dx; + this.dy = dy; + this.dz = dz; + return this; + } + + public ParticleBuilder count(int count) { + this.count = count; + return this; + } + + public ParticleBuilder extra(float extra) { + this.extra = extra; + return this; + } + + public ParticleBuilder data(Color color) { + dustData = new Particle.DustOptions(color, 1.0F); + return this; + } + + public ParticleBuilder data(BlockData data) { + this.blockData = data; + return this; + } + + public ParticleBuilder data(ItemStack data) { + this.itemData = data; + return this; + } + + public ParticleBuilder receivers(Player p) { + receivers.add(p); + return this; + } + + public ParticleBuilder receivers(int rad) { + for (Entity e : loc.getWorld().getNearbyEntities(loc, rad, rad, rad)) { + if (e instanceof Player) { + receivers.add((Player) e); + } + } + return this; + } + + public void spawn() { + Object data = null; + if (dustData != null) { + data = dustData; + } + else if (blockData != null) { + data = blockData; + } + else if (itemData != null) { + data = itemData; + } + for (Player p : receivers) { + p.spawnParticle(particle, loc, count, dx, dy, dz, extra, data); + } + } +} diff --git a/src/main/java/com/sucy/skill/api/ParticleSettings.java b/src/main/java/com/sucy/skill/api/ParticleSettings.java new file mode 100644 index 00000000..aecf0bca --- /dev/null +++ b/src/main/java/com/sucy/skill/api/ParticleSettings.java @@ -0,0 +1,141 @@ +package com.sucy.skill.api; + +import com.rit.sucy.version.VersionManager; +import com.sucy.skill.api.util.ParticleHelper; +import net.minecraft.world.entity.Entity; +import org.bukkit.*; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wolf; +import org.bukkit.inventory.ItemStack; + +import java.util.Locale; +import java.util.logging.Level; + +public class ParticleSettings { + + private final Settings originalSettings; + private ParticleBuilder particleBuilder; + private EntityEffect entityEffect; + private Effect effect; + + public ParticleSettings(LivingEntity caster, Settings settings) { + this.originalSettings = settings; + + configureParticle(caster); + } + + public void spawn(Location location) { + + if (particleBuilder != null) { + particleBuilder.location(location).spawn(); + } + + if (effect != null) { + location.getWorld().playEffect(location, effect, originalSettings.getInt(ParticleHelper.DATA_KEY, 0)); + } + + if (entityEffect != null) { + CraftWorld cw = (CraftWorld) location.getWorld(); + Entity fake = cw.createEntity(location, Wolf.class); + cw.getHandle().broadcastEntityEffect(fake, entityEffect.getData()); + } + + } + + public Settings getOriginalSettings() { + return originalSettings; + } + + private void configureParticle(LivingEntity caster) { + String particle = originalSettings.getString(ParticleHelper.PARTICLE_KEY, "invalid"); + particle = fixKey(particle); + + final boolean onlyCaster = originalSettings.getBool("onlycaster", true); + final int rad = originalSettings.getInt(ParticleHelper.VISIBLE_RADIUS_KEY, 25); + + final float dx = (float) originalSettings.getDouble(ParticleHelper.DX_KEY, 0.0); + final float dy = (float) originalSettings.getDouble(ParticleHelper.DY_KEY, 0.0); + final float dz = (float) originalSettings.getDouble(ParticleHelper.DZ_KEY, 0.0); + + final int amount = originalSettings.getInt(ParticleHelper.AMOUNT_KEY, 1); + final float speed = (float) originalSettings.getDouble(ParticleHelper.SPEED_KEY, 1.0); + final Material mat = Material.matchMaterial(originalSettings.getString(ParticleHelper.MATERIAL_KEY, "DIRT")); + + try { + + boolean isParticle = isValidEnum(Particle.class, particle); + + if (isValidEnum(Effect.class, particle) && !isParticle) { + effect = Effect.valueOf(particle); + } else if (isValidEnum(EntityEffect.class, particle) && !isParticle) { + entityEffect = EntityEffect.valueOf(particle); + } else if (VersionManager.isVersionAtLeast(11300)) { + + ParticleBuilder builder = new ParticleBuilder(Particle.valueOf(particle)) + .location(caster.getLocation()) + .offset(dx, dy, dz) + .count(amount) + .extra(speed); + + if (particle.toLowerCase().startsWith("block")) { + builder.data(mat.createBlockData()); + } + + else if (particle.toLowerCase().startsWith("icon")) { + builder.data(new ItemStack(mat)); + } + + else if (particle.equalsIgnoreCase("redstone")) { + String hexColor = originalSettings.getString(ParticleHelper.RGB_KEY, null); + + builder.data(Color.RED); + + if (hexColor != null) { + hexColor = hexColor.startsWith("#") ? hexColor : "#" + hexColor; + builder.data(Color.fromRGB(Integer.decode(hexColor))); + } + + builder.extra(speed == 0 ? 0.001F : speed); + } + + if (onlyCaster) { + builder.receivers((Player) caster); + } else { + builder.receivers(rad); + } + + particleBuilder = builder; + } + + } catch (Exception ex) { + Bukkit.getLogger().log(Level.INFO, "SkillAPI Error: " + caster.getName()); + originalSettings.dumpToConsole(); + } + } + + private > boolean isValidEnum(Class enumClass, String enumName) { + if (enumName == null) { + return false; + } else { + try { + Enum.valueOf(enumClass, enumName); + return true; + } catch (IllegalArgumentException var3) { + return false; + } + } + } + + private String fixKey(String name) { + String filtered = name; + if (name.startsWith("minecraft:")) { + filtered = name.substring("minecraft:".length()); + } + + filtered = filtered.toUpperCase(Locale.ENGLISH); + return filtered.replaceAll("\\s+", "_").replaceAll("\\W", ""); + } + +} diff --git a/src/com/sucy/skill/api/ReadOnlySettings.java b/src/main/java/com/sucy/skill/api/ReadOnlySettings.java similarity index 100% rename from src/com/sucy/skill/api/ReadOnlySettings.java rename to src/main/java/com/sucy/skill/api/ReadOnlySettings.java diff --git a/src/com/sucy/skill/api/Settings.java b/src/main/java/com/sucy/skill/api/Settings.java similarity index 98% rename from src/com/sucy/skill/api/Settings.java rename to src/main/java/com/sucy/skill/api/Settings.java index b974a088..4cdc3df6 100644 --- a/src/com/sucy/skill/api/Settings.java +++ b/src/main/java/com/sucy/skill/api/Settings.java @@ -52,6 +52,10 @@ public Settings() { public Settings(final Settings settings) { this.settings = new HashMap<>(settings.settings); } + + public String toString() { + return settings.toString(); + } /** * Sets the value for a setting. You should only provide a @@ -396,6 +400,10 @@ public void save(DataSection config) { config.set(key, settings.get(key)); } } + + public HashMap getHashMap() { + return settings; + } /** *

Loads attributes from a configuration section

diff --git a/src/com/sucy/skill/api/SkillPlugin.java b/src/main/java/com/sucy/skill/api/SkillPlugin.java similarity index 100% rename from src/com/sucy/skill/api/SkillPlugin.java rename to src/main/java/com/sucy/skill/api/SkillPlugin.java diff --git a/src/com/sucy/skill/api/classes/ClassAttribute.java b/src/main/java/com/sucy/skill/api/classes/ClassAttribute.java similarity index 100% rename from src/com/sucy/skill/api/classes/ClassAttribute.java rename to src/main/java/com/sucy/skill/api/classes/ClassAttribute.java diff --git a/src/main/java/com/sucy/skill/api/classes/Click.java b/src/main/java/com/sucy/skill/api/classes/Click.java new file mode 100644 index 00000000..c5104bb6 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/classes/Click.java @@ -0,0 +1,26 @@ +package com.sucy.skill.api.classes; + +import com.sucy.skill.api.event.KeyPressEvent.Key; + +public class Click { + private long time; + private Key key; + + public Click (long time, Key key) { + this.time = time; + this.key = key; + } + + public long getTime() { + return time; + } + public void setTime(long time) { + this.time = time; + } + public Key getKey() { + return key; + } + public void setKey(Key key) { + this.key = key; + } +} diff --git a/src/com/sucy/skill/api/classes/DefaultTreeType.java b/src/main/java/com/sucy/skill/api/classes/DefaultTreeType.java similarity index 100% rename from src/com/sucy/skill/api/classes/DefaultTreeType.java rename to src/main/java/com/sucy/skill/api/classes/DefaultTreeType.java diff --git a/src/com/sucy/skill/api/classes/RPGClass.java b/src/main/java/com/sucy/skill/api/classes/RPGClass.java similarity index 100% rename from src/com/sucy/skill/api/classes/RPGClass.java rename to src/main/java/com/sucy/skill/api/classes/RPGClass.java diff --git a/src/com/sucy/skill/api/classes/TreeType.java b/src/main/java/com/sucy/skill/api/classes/TreeType.java similarity index 100% rename from src/com/sucy/skill/api/classes/TreeType.java rename to src/main/java/com/sucy/skill/api/classes/TreeType.java diff --git a/src/com/sucy/skill/api/enums/Direction.java b/src/main/java/com/sucy/skill/api/enums/Direction.java similarity index 100% rename from src/com/sucy/skill/api/enums/Direction.java rename to src/main/java/com/sucy/skill/api/enums/Direction.java diff --git a/src/com/sucy/skill/api/enums/ExpSource.java b/src/main/java/com/sucy/skill/api/enums/ExpSource.java similarity index 100% rename from src/com/sucy/skill/api/enums/ExpSource.java rename to src/main/java/com/sucy/skill/api/enums/ExpSource.java diff --git a/src/com/sucy/skill/api/enums/ManaCost.java b/src/main/java/com/sucy/skill/api/enums/ManaCost.java similarity index 100% rename from src/com/sucy/skill/api/enums/ManaCost.java rename to src/main/java/com/sucy/skill/api/enums/ManaCost.java diff --git a/src/com/sucy/skill/api/enums/ManaSource.java b/src/main/java/com/sucy/skill/api/enums/ManaSource.java similarity index 100% rename from src/com/sucy/skill/api/enums/ManaSource.java rename to src/main/java/com/sucy/skill/api/enums/ManaSource.java diff --git a/src/com/sucy/skill/api/enums/PointSource.java b/src/main/java/com/sucy/skill/api/enums/PointSource.java similarity index 100% rename from src/com/sucy/skill/api/enums/PointSource.java rename to src/main/java/com/sucy/skill/api/enums/PointSource.java diff --git a/src/com/sucy/skill/api/enums/SkillStatus.java b/src/main/java/com/sucy/skill/api/enums/SkillStatus.java similarity index 100% rename from src/com/sucy/skill/api/enums/SkillStatus.java rename to src/main/java/com/sucy/skill/api/enums/SkillStatus.java diff --git a/src/com/sucy/skill/api/enums/TreeType.java b/src/main/java/com/sucy/skill/api/enums/TreeType.java similarity index 100% rename from src/com/sucy/skill/api/enums/TreeType.java rename to src/main/java/com/sucy/skill/api/enums/TreeType.java diff --git a/src/com/sucy/skill/api/event/FlagApplyEvent.java b/src/main/java/com/sucy/skill/api/event/FlagApplyEvent.java similarity index 90% rename from src/com/sucy/skill/api/event/FlagApplyEvent.java rename to src/main/java/com/sucy/skill/api/event/FlagApplyEvent.java index d943297a..5be36b4b 100644 --- a/src/com/sucy/skill/api/event/FlagApplyEvent.java +++ b/src/main/java/com/sucy/skill/api/event/FlagApplyEvent.java @@ -31,6 +31,8 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import com.sucy.skill.api.player.PlayerData; + /** * Event called when a flag is applied to an entity */ @@ -38,6 +40,7 @@ public class FlagApplyEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); private LivingEntity entity; + private LivingEntity caster; private String flag; private boolean cancelled; private int ticks; @@ -48,13 +51,18 @@ public class FlagApplyEvent extends Event implements Cancellable * @param entity the entity the flag was on * @param flag the flag that is to be applied */ - public FlagApplyEvent(LivingEntity entity, String flag, int ticks) + public FlagApplyEvent(LivingEntity caster, LivingEntity entity, String flag, int ticks) { + this.caster = caster; this.entity = entity; this.flag = flag; this.ticks = ticks; this.cancelled = false; } + + public LivingEntity getCaster() { + return this.caster; + } /** * Retrieves the entity that the flag is being applied to @@ -85,6 +93,10 @@ public int getTicks() { return ticks; } + + public void setTicks(int ticks) { + this.ticks = ticks; + } /** * Checks whether or not the event is cancelled diff --git a/src/com/sucy/skill/api/event/FlagExpireEvent.java b/src/main/java/com/sucy/skill/api/event/FlagExpireEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/FlagExpireEvent.java rename to src/main/java/com/sucy/skill/api/event/FlagExpireEvent.java diff --git a/src/com/sucy/skill/api/event/ItemProjectileHitEvent.java b/src/main/java/com/sucy/skill/api/event/ItemProjectileHitEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ItemProjectileHitEvent.java rename to src/main/java/com/sucy/skill/api/event/ItemProjectileHitEvent.java diff --git a/src/com/sucy/skill/api/event/ItemProjectileLandEvent.java b/src/main/java/com/sucy/skill/api/event/ItemProjectileLandEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ItemProjectileLandEvent.java rename to src/main/java/com/sucy/skill/api/event/ItemProjectileLandEvent.java diff --git a/src/com/sucy/skill/api/event/ItemProjectileLaunchEvent.java b/src/main/java/com/sucy/skill/api/event/ItemProjectileLaunchEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ItemProjectileLaunchEvent.java rename to src/main/java/com/sucy/skill/api/event/ItemProjectileLaunchEvent.java diff --git a/src/com/sucy/skill/api/event/KeyPressEvent.java b/src/main/java/com/sucy/skill/api/event/KeyPressEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/KeyPressEvent.java rename to src/main/java/com/sucy/skill/api/event/KeyPressEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/NeoClickComboEvent.java b/src/main/java/com/sucy/skill/api/event/NeoClickComboEvent.java new file mode 100644 index 00000000..9586ecc6 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/NeoClickComboEvent.java @@ -0,0 +1,106 @@ +/** + * SkillAPI + * com.sucy.skill.api.event. + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a flag is applied to an entity + */ +public class NeoClickComboEvent extends Event implements Cancellable +{ + public enum ClickType {LR, RL}; + private static final HandlerList handlers = new HandlerList(); + private Player p; + private ClickType type; + private boolean cancelled; + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public NeoClickComboEvent(Player p, ClickType type) + { + this.p = p; + this.type = type; + this.cancelled = false; + } + + public Player getPlayer() + { + return p; + } + + public ClickType getType() + { + return type; + } + + /** + * Checks whether or not the event is cancelled + * + * @return true if cancelled, false otherwise + */ + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/ParticleProjectileExpireEvent.java b/src/main/java/com/sucy/skill/api/event/ParticleProjectileExpireEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ParticleProjectileExpireEvent.java rename to src/main/java/com/sucy/skill/api/event/ParticleProjectileExpireEvent.java diff --git a/src/com/sucy/skill/api/event/ParticleProjectileHitEvent.java b/src/main/java/com/sucy/skill/api/event/ParticleProjectileHitEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ParticleProjectileHitEvent.java rename to src/main/java/com/sucy/skill/api/event/ParticleProjectileHitEvent.java diff --git a/src/com/sucy/skill/api/event/ParticleProjectileLandEvent.java b/src/main/java/com/sucy/skill/api/event/ParticleProjectileLandEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ParticleProjectileLandEvent.java rename to src/main/java/com/sucy/skill/api/event/ParticleProjectileLandEvent.java diff --git a/src/com/sucy/skill/api/event/ParticleProjectileLaunchEvent.java b/src/main/java/com/sucy/skill/api/event/ParticleProjectileLaunchEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/ParticleProjectileLaunchEvent.java rename to src/main/java/com/sucy/skill/api/event/ParticleProjectileLaunchEvent.java diff --git a/src/com/sucy/skill/api/event/PhysicalDamageEvent.java b/src/main/java/com/sucy/skill/api/event/PhysicalDamageEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PhysicalDamageEvent.java rename to src/main/java/com/sucy/skill/api/event/PhysicalDamageEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerAccountChangeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerAccountChangeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerAccountChangeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerAccountChangeEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerAttributeLoadEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerAttributeLoadEvent.java new file mode 100644 index 00000000..2c3877d6 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerAttributeLoadEvent.java @@ -0,0 +1,66 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerClassChangeEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a player changes classes + */ +public class PlayerAttributeLoadEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private Player p; + + public PlayerAttributeLoadEvent(Player player) + { + this.p = player; + } + + public Player getPlayer() + { + return this.p; + } + + /** + * @return gets the handlers for the event + */ + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/com/sucy/skill/api/event/PlayerAttributeUnloadEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerAttributeUnloadEvent.java new file mode 100644 index 00000000..c913968c --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerAttributeUnloadEvent.java @@ -0,0 +1,66 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerClassChangeEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a player changes classes + */ +public class PlayerAttributeUnloadEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private Player p; + + public PlayerAttributeUnloadEvent(Player player) + { + this.p = player; + } + + public Player getPlayer() + { + return this.p; + } + + /** + * @return gets the handlers for the event + */ + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/com/sucy/skill/api/event/PlayerCalculateDamageEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerCalculateDamageEvent.java new file mode 100644 index 00000000..be49ad3d --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerCalculateDamageEvent.java @@ -0,0 +1,125 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerCalculateDamageEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private LivingEntity caster; + private LivingEntity target; + private String[] types; + private double damage; + private double posmult; + private double negmult; + private double flat; + + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerCalculateDamageEvent(LivingEntity caster, LivingEntity target, double damage, double posmult, double negmult, double flat, String[] types) { + this.caster = caster; + this.target = target; + this.damage = damage; + this.posmult = posmult; + this.negmult = negmult; + this.flat = flat; + this.types = types; + } + public String[] getTypes() { + return types; + } + + public LivingEntity getTarget() { + return target; + } + + public void setTarget(LivingEntity target) { + this.target = target; + } + + public double getDamage() { + return damage; + } + + public double getPosmult() { + return posmult; + } + public void setPosmult(double posmult) { + this.posmult = posmult; + } + public double getNegmult() { + return negmult; + } + public void setNegmult(double negmult) { + this.negmult = negmult; + } + public void setDamage(double damage) { + this.damage = damage; + } + public double getFlat() { + return flat; + } + public void setFlat(double flat) { + this.flat = flat; + } + public void setTypes(String[] types) { + this.types = types; + } + public LivingEntity getCaster() { + return caster; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() { + return handlers; + } + public void setCaster(LivingEntity caster) { + this.caster = caster; + } + + +} diff --git a/src/com/sucy/skill/api/event/PlayerCastSkillEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerCastSkillEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerCastSkillEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerCastSkillEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerClassChangeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerClassChangeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerClassChangeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerClassChangeEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerComboFinishEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerComboFinishEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerComboFinishEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerComboFinishEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerCriticalCheckEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerCriticalCheckEvent.java new file mode 100644 index 00000000..7245c138 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerCriticalCheckEvent.java @@ -0,0 +1,97 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.sucy.skill.api.player.PlayerData; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerCriticalCheckEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private PlayerData data; + private double chance; + private boolean cancelled; + + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerCriticalCheckEvent(PlayerData data, double chance) { + this.data = data; + this.chance = chance; + } + + public PlayerData getPlayerData() { + return data; + } + + public double getChance() { + return chance; + } + + public void setChance(double chance) { + this.chance = chance; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/com/sucy/skill/api/event/PlayerCriticalDamageEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerCriticalDamageEvent.java new file mode 100644 index 00000000..a5ceb24a --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerCriticalDamageEvent.java @@ -0,0 +1,108 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.sucy.skill.api.player.PlayerData; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerCriticalDamageEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private LivingEntity caster; + private LivingEntity target; + private double damage; + private boolean cancelled; + + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerCriticalDamageEvent(LivingEntity caster, LivingEntity target, double damage) { + this.caster = caster; + this.target = target; + this.damage = damage; + } + + public LivingEntity getTarget() { + return target; + } + + public void setTarget(LivingEntity target) { + this.target = target; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public LivingEntity getCaster() { + return caster; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/com/sucy/skill/api/event/PlayerCriticalSuccessEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerCriticalSuccessEvent.java new file mode 100644 index 00000000..6d5ab552 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerCriticalSuccessEvent.java @@ -0,0 +1,97 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.sucy.skill.api.player.PlayerData; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerCriticalSuccessEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private PlayerData data; + private double chance; + private boolean cancelled; + + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerCriticalSuccessEvent(PlayerData data, double chance) { + this.data = data; + this.chance = chance; + } + + public PlayerData getPlayerData() { + return data; + } + + public double getChance() { + return chance; + } + + public void setChance(double chance) { + this.chance = chance; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerExperienceGainEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerExperienceGainEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerExperienceGainEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerExperienceGainEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerExperienceLostEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerExperienceLostEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerExperienceLostEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerExperienceLostEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerGainSkillPointsEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerGainSkillPointsEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerGainSkillPointsEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerGainSkillPointsEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerLandEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerLandEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerLandEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerLandEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerLevelUpEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerLevelUpEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerLevelUpEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerLevelUpEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerLoadCompleteEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerLoadCompleteEvent.java new file mode 100644 index 00000000..61ee995f --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerLoadCompleteEvent.java @@ -0,0 +1,66 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerClassChangeEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a player changes classes + */ +public class PlayerLoadCompleteEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private Player p; + + public PlayerLoadCompleteEvent(Player player) + { + this.p = player; + } + + public Player getPlayer() + { + return this.p; + } + + /** + * @return gets the handlers for the event + */ + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerManaGainEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerManaGainEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerManaGainEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerManaGainEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerManaLossEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerManaLossEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerManaLossEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerManaLossEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerPreClassChangeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerPreClassChangeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerPreClassChangeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerPreClassChangeEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerPreLoadCompleteEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerPreLoadCompleteEvent.java new file mode 100644 index 00000000..b909b354 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerPreLoadCompleteEvent.java @@ -0,0 +1,66 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerClassChangeEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; +import java.util.UUID; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a player changes classes + */ +public class PlayerPreLoadCompleteEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private UUID uuid; + + public PlayerPreLoadCompleteEvent(UUID uuid) + { + this.uuid = uuid; + } + + public UUID getUniqueId() + { + return this.uuid; + } + + /** + * @return gets the handlers for the event + */ + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerRefundAttributeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerRefundAttributeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerRefundAttributeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerRefundAttributeEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerRegenEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerRegenEvent.java new file mode 100644 index 00000000..de75dacb --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerRegenEvent.java @@ -0,0 +1,108 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerRegenEvent extends Event implements Cancellable +{ + private static final HandlerList handlers = new HandlerList(); + private Player p; + private boolean cancelled; + private double amount; + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerRegenEvent(Player p, double amount) + { + this.p = p; + this.amount = amount; + this.cancelled = false; + } + + public Player getPlayer() + { + return p; + } + + public double getAmount() { + return this.amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } + + /** + * Checks whether or not the event is cancelled + * + * @return true if cancelled, false otherwise + */ + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/com/sucy/skill/api/event/PlayerSaveEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSaveEvent.java new file mode 100644 index 00000000..67c7bae0 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerSaveEvent.java @@ -0,0 +1,74 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerClassChangeEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import java.util.UUID; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a player saves their class + */ +public class PlayerSaveEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private Player p; + private UUID uuid; + + public PlayerSaveEvent(Player player) + { + this.p = player; + this.uuid = player.getUniqueId(); + } + + public Player getPlayer() + { + return this.p; + } + + public UUID getUUID() { + return this.uuid; + } + + /** + * @return gets the handlers for the event + */ + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerSkillCastFailedEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSkillCastFailedEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerSkillCastFailedEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerSkillCastFailedEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerSkillCastSuccessEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSkillCastSuccessEvent.java new file mode 100644 index 00000000..60e148df --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerSkillCastSuccessEvent.java @@ -0,0 +1,99 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.PlayerCastSkillEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.api.player.PlayerSkill; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PlayerSkillCastSuccessEvent extends Event implements Cancellable +{ + private static final HandlerList handlers = new HandlerList(); + private PlayerData playerData; + private PlayerSkill skill; + private Player player; + private double manaCost; + private boolean cancelled; + + public PlayerSkillCastSuccessEvent(PlayerData playerData, PlayerSkill skill, Player player) + { + this.playerData = playerData; + this.skill = skill; + this.player = player; + this.manaCost = skill.getManaCost(); + this.cancelled = false; + } + + public Player getPlayer() + { + return player; + } + + public PlayerData getPlayerData() + { + return playerData; + } + + public PlayerSkill getSkill() + { + return skill; + } + + public double getManaCost() { + return manaCost; + } + + public void setManaCost(final double manaCost) { + this.manaCost = manaCost; + } + + @Override + public boolean isCancelled() + { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerSkillDowngradeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSkillDowngradeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerSkillDowngradeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerSkillDowngradeEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerSkillUnlockEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSkillUnlockEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerSkillUnlockEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerSkillUnlockEvent.java diff --git a/src/com/sucy/skill/api/event/PlayerSkillUpgradeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerSkillUpgradeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerSkillUpgradeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerSkillUpgradeEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/PlayerTauntEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerTauntEvent.java new file mode 100644 index 00000000..08900225 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/PlayerTauntEvent.java @@ -0,0 +1,125 @@ +/** + * SkillAPI + * com.sucy.skill.api.event.FlagApplyEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called when a flag is applied to an entity + */ +public class PlayerTauntEvent extends Event implements Cancellable +{ + private static final HandlerList handlers = new HandlerList(); + private LivingEntity caster; + private LivingEntity target; + private double amount; + private boolean cancelled; + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public PlayerTauntEvent(LivingEntity caster, LivingEntity target, double amount) + { + this.caster = caster; + this.target = target; + this.amount = amount; + this.cancelled = false; + } + + public LivingEntity getCaster() { + return this.caster; + } + + /** + * Retrieves the entity that the flag is being applied to + * + * @return the entity having the flag applied to + */ + public LivingEntity getTarget() + { + return target; + } + + /** + * Retrieves the number of ticks the flag is to be applied for + * + * @return the number of ticks + */ + public double getAmount() + { + return amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } + + /** + * Checks whether or not the event is cancelled + * + * @return true if cancelled, false otherwise + */ + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/PlayerUpAttributeEvent.java b/src/main/java/com/sucy/skill/api/event/PlayerUpAttributeEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/PlayerUpAttributeEvent.java rename to src/main/java/com/sucy/skill/api/event/PlayerUpAttributeEvent.java diff --git a/src/main/java/com/sucy/skill/api/event/SkillBuffEvent.java b/src/main/java/com/sucy/skill/api/event/SkillBuffEvent.java new file mode 100644 index 00000000..58fc48a4 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/event/SkillBuffEvent.java @@ -0,0 +1,154 @@ +/** + * SkillAPI + * com.sucy.skill.api.event + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.sucy.skill.api.util.BuffType; + +/** + * Event called when a flag is applied to an entity + */ +public class SkillBuffEvent extends Event implements Cancellable +{ + private static final HandlerList handlers = new HandlerList(); + private LivingEntity caster; + private LivingEntity target; + private boolean cancelled; + private int ticks; + private BuffType type; + private double amount; + private boolean isMultiplier; + + /** + * Constructor + * + * @param entity the entity the flag was on + * @param flag the flag that is to be applied + */ + public SkillBuffEvent(LivingEntity caster, LivingEntity target, double amount, int ticks, BuffType type, boolean isMultiplier) + { + this.caster = caster; + this.target = target; + this.amount = amount; + this.ticks = ticks; + this.type = type; + this.isMultiplier = isMultiplier; + this.cancelled = false; + } + + public LivingEntity getCaster() { + return caster; + } + + public void setCaster(LivingEntity caster) { + this.caster = caster; + } + + public LivingEntity getTarget() { + return caster; + } + + public void setTarget(LivingEntity target) { + this.target = target; + } + + public int getTicks() { + return ticks; + } + + public void setTicks(int ticks) { + this.ticks = ticks; + } + + public BuffType getType() { + return type; + } + + public void setType(BuffType type) { + this.type = type; + } + + public boolean isMultiplier() { + return isMultiplier; + } + + public void setMultiplier(boolean isMultiplier) { + this.isMultiplier = isMultiplier; + } + + public double getAmount() { + return this.amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } + + /** + * Checks whether or not the event is cancelled + * + * @return true if cancelled, false otherwise + */ + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Sets whether or not the event is cancelled + * + * @param cancelled true if cancelled, false otherwise + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + /** + * @return gets the handlers for the event + */ + @Override + public HandlerList getHandlers() + { + return handlers; + } + + /** + * @return gets the handlers for the event + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/SkillDamageEvent.java b/src/main/java/com/sucy/skill/api/event/SkillDamageEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/SkillDamageEvent.java rename to src/main/java/com/sucy/skill/api/event/SkillDamageEvent.java diff --git a/src/com/sucy/skill/api/event/SkillHealEvent.java b/src/main/java/com/sucy/skill/api/event/SkillHealEvent.java similarity index 81% rename from src/com/sucy/skill/api/event/SkillHealEvent.java rename to src/main/java/com/sucy/skill/api/event/SkillHealEvent.java index a4a02d97..a37c2573 100644 --- a/src/com/sucy/skill/api/event/SkillHealEvent.java +++ b/src/main/java/com/sucy/skill/api/event/SkillHealEvent.java @@ -1,144 +1,158 @@ -/** - * SkillAPI - * com.sucy.skill.api.event.SkillHealEvent - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.api.event; - -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * An event for when an entity is healed by - * another entity with the use of a skill. - */ -public class SkillHealEvent extends Event implements Cancellable -{ - private static final HandlerList handlers = new HandlerList(); - - private LivingEntity healer; - private LivingEntity target; - private double damage; - private boolean cancelled; - - /** - * Initializes a new event - * - * @param healer entity dealing the damage - * @param target entity receiving the damage - * @param damage the amount of damage dealt - */ - public SkillHealEvent(LivingEntity healer, LivingEntity target, double damage) - { - this.healer = healer; - this.target = target; - this.damage = damage; - this.cancelled = false; - } - - /** - * Retrieves the entity that dealt the damage - * - * @return entity that dealt the damage - */ - public LivingEntity getHealer() - { - return healer; - } - - /** - * Retrieves the entity that received the damage - * - * @return entity that received the damage - */ - public LivingEntity getTarget() - { - return target; - } - - /** - * Retrieves the amount of damage dealt - * - * @return amount of damage dealt - */ - public double getAmount() - { - return damage; - } - - /** - * Sets the amount of damage dealt - * - * @param amount amount of damage dealt - */ - public void setAmount(double amount) - { - damage = amount; - } - - /** - * Checks whether or not the event is cancelled - * - * @return true if cancelled, false otherwise - */ - @Override - public boolean isCancelled() - { - return cancelled; - } - - /** - * Sets the cancelled state of the event - * - * @param cancelled the cancelled state of the event - */ - @Override - public void setCancelled(boolean cancelled) - { - this.cancelled = cancelled; - } - - /** - * Retrieves the handlers for the event - * - * @return list of event handlers - */ - @Override - public HandlerList getHandlers() - { - return handlers; - } - - /** - * Retrieves the handlers for the event - * - * @return list of event handlers - */ - public static HandlerList getHandlerList() - { - return handlers; - } -} +/** + * SkillAPI + * com.sucy.skill.api.event.SkillHealEvent + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.event; + +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * An event for when an entity is healed by + * another entity with the use of a skill. + */ +public class SkillHealEvent extends Event implements Cancellable +{ + private static final HandlerList handlers = new HandlerList(); + + private LivingEntity healer; + private LivingEntity target; + private double amount; + private boolean cancelled; + private boolean ignoreCurse; + + /** + * Initializes a new event + * + * @param healer entity dealing the damage + * @param target entity receiving the damage + * @param damage the amount of damage dealt + */ + public SkillHealEvent(LivingEntity healer, LivingEntity target, double amount, boolean ignoreCurse) + { + this.healer = healer; + this.target = target; + this.amount = amount; + this.cancelled = false; + this.ignoreCurse = ignoreCurse; + } + + /** + * Retrieves the entity that dealt the damage + * + * @return entity that dealt the damage + */ + public LivingEntity getHealer() + { + return healer; + } + + public double getEffectiveHeal() { + double current = this.target.getHealth(); + double max = this.target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(); + double result = current + this.amount > max ? max : current + this.amount; + return result - current > 0 ? result - current : 0; + } + + /** + * Retrieves the entity that received the damage + * + * @return entity that received the damage + */ + public LivingEntity getTarget() + { + return target; + } + + /** + * Retrieves the amount of damage dealt + * + * @return amount of damage dealt + */ + public double getAmount() + { + return amount; + } + + /** + * Sets the amount of damage dealt + * + * @param amount amount of damage dealt + */ + public void setAmount(double amount) + { + this.amount = amount; + } + + public boolean ignoresCurse() { + return ignoreCurse; + } + + /** + * Checks whether or not the event is cancelled + * + * @return true if cancelled, false otherwise + */ + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Sets the cancelled state of the event + * + * @param cancelled the cancelled state of the event + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + /** + * Retrieves the handlers for the event + * + * @return list of event handlers + */ + @Override + public HandlerList getHandlers() + { + return handlers; + } + + /** + * Retrieves the handlers for the event + * + * @return list of event handlers + */ + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/com/sucy/skill/api/event/TrueDamageEvent.java b/src/main/java/com/sucy/skill/api/event/TrueDamageEvent.java similarity index 100% rename from src/com/sucy/skill/api/event/TrueDamageEvent.java rename to src/main/java/com/sucy/skill/api/event/TrueDamageEvent.java diff --git a/src/com/sucy/skill/api/exception/SkillTreeException.java b/src/main/java/com/sucy/skill/api/exception/SkillTreeException.java similarity index 100% rename from src/com/sucy/skill/api/exception/SkillTreeException.java rename to src/main/java/com/sucy/skill/api/exception/SkillTreeException.java diff --git a/src/com/sucy/skill/api/particle/EffectData.java b/src/main/java/com/sucy/skill/api/particle/EffectData.java similarity index 100% rename from src/com/sucy/skill/api/particle/EffectData.java rename to src/main/java/com/sucy/skill/api/particle/EffectData.java diff --git a/src/com/sucy/skill/api/particle/EffectInstance.java b/src/main/java/com/sucy/skill/api/particle/EffectInstance.java similarity index 100% rename from src/com/sucy/skill/api/particle/EffectInstance.java rename to src/main/java/com/sucy/skill/api/particle/EffectInstance.java diff --git a/src/com/sucy/skill/api/particle/EffectManager.java b/src/main/java/com/sucy/skill/api/particle/EffectManager.java similarity index 99% rename from src/com/sucy/skill/api/particle/EffectManager.java rename to src/main/java/com/sucy/skill/api/particle/EffectManager.java index 626f7582..390b62b0 100644 --- a/src/com/sucy/skill/api/particle/EffectManager.java +++ b/src/main/java/com/sucy/skill/api/particle/EffectManager.java @@ -61,7 +61,6 @@ public static void init() { if (key.equals("one-circle")) { formulas.get(key).getPoints(XZHandler.instance); } } - MainThread.register(new EffectTask()); } public static void cleanUp() { diff --git a/src/com/sucy/skill/api/particle/EffectPlayer.java b/src/main/java/com/sucy/skill/api/particle/EffectPlayer.java similarity index 100% rename from src/com/sucy/skill/api/particle/EffectPlayer.java rename to src/main/java/com/sucy/skill/api/particle/EffectPlayer.java diff --git a/src/com/sucy/skill/api/particle/Particle.java b/src/main/java/com/sucy/skill/api/particle/Particle.java similarity index 64% rename from src/com/sucy/skill/api/particle/Particle.java rename to src/main/java/com/sucy/skill/api/particle/Particle.java index 21a1241a..042b1032 100644 --- a/src/com/sucy/skill/api/particle/Particle.java +++ b/src/main/java/com/sucy/skill/api/particle/Particle.java @@ -1,28 +1,28 @@ -/** - * SkillAPI - * com.sucy.skill.api.particle.Particle - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. +/* + SkillAPI + com.sucy.skill.api.particle.Particle + + The MIT License (MIT) + + Copyright (c) 2016 Steven Sucy + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ package com.sucy.skill.api.particle; @@ -33,6 +33,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.util.logging.Level; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -52,7 +53,7 @@ public class Particle { private static Field connection; - private static HashMap particleTypes = new HashMap<>(); + private static final HashMap particleTypes = new HashMap<>(); /** * Initializes the SkillAPI particle utility @@ -60,70 +61,37 @@ public class Particle { public static void init() { try { String version = Bukkit.getServer().getClass().getPackage().getName().substring(23); - String nms = "net.minecraft.server." + version + '.'; String craft = "org.bukkit.craftbukkit." + version + '.'; getHandle = Class.forName(craft + "entity.CraftPlayer").getMethod("getHandle"); - connection = Class.forName(nms + "EntityPlayer").getDeclaredField("playerConnection"); - sendPacket = Class.forName(nms + "PlayerConnection") - .getDeclaredMethod("sendPacket", Class.forName(nms + "Packet")); + connection = Class.forName("net.minecraft.server.level.EntityPlayer").getDeclaredField("b"); + sendPacket = Class.forName("net.minecraft.server.network.PlayerConnection") + .getDeclaredMethod("sendPacket", Class.forName("net.minecraft.network.protocol.Packet")); Class packetClass; // 1.13+ Servers Class particleEnum; - if (VersionManager.isVersionAtLeast(11300)) { + + // 1.15 servers + if (VersionManager.isVersionAtLeast(11500)) { Class craftParticle = Class.forName(craft + "CraftParticle"); toNms = craftParticle.getDeclaredMethod("toNMS", org.bukkit.Particle.class, Object.class); - particleEnum = Class.forName(nms + "ParticleParam"); - packetClass = Class.forName(nms + "PacketPlayOutWorldParticles"); + particleEnum = Class.forName("net.minecraft.core.particles.ParticleParam"); + packetClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutWorldParticles"); packet = packetClass.getConstructor( particleEnum, boolean.class, - float.class, - float.class, - float.class, + double.class, + double.class, + double.class, float.class, float.class, float.class, float.class, int.class); } - - // 1.8+ servers - else if (VersionManager.isVersionAtLeast(VersionManager.V1_8_0)) { - particleEnum = Class.forName(nms + "EnumParticle"); - for (Object value : particleEnum.getEnumConstants()) { particleTypes.put(value.toString(), value); } - packetClass = Class.forName(nms + "PacketPlayOutWorldParticles"); - packet = packetClass.getConstructor( - particleEnum, - Boolean.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Integer.TYPE, - int[].class); - } - - // 1.7.x servers - else { - packetClass = Class.forName(nms + "PacketPlayOutWorldParticles"); - packet = packetClass.getConstructor( - String.class, - Boolean.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Float.TYPE, - Integer.TYPE); - } } catch (Exception ex) { - System.out.println("Failed to set up particles, are you using Cauldron?"); + Bukkit.getLogger().log(Level.WARNING, + "Failed to set up particles, are you using Cauldron?"); } } @@ -132,13 +100,14 @@ else if (VersionManager.isVersionAtLeast(VersionManager.V1_8_0)) { * * @param player player to send to * @param packets packets to send - * * @throws Exception */ public static void send(Player player, List packets) throws Exception { Object network = connection.get(getHandle.invoke(player)); - for (Object packet : packets) { sendPacket.invoke(network, packet); } + for (Object packet : packets) { + sendPacket.invoke(network, packet); + } } /** @@ -146,13 +115,14 @@ public static void send(Player player, List packets) * * @param player player to send to * @param packets packets to send - * * @throws Exception when reflection fails */ public static void send(Player player, Object[] packets) throws Exception { Object network = connection.get(getHandle.invoke(player)); - for (Object packet : packets) { sendPacket.invoke(network, packet); } + for (Object packet : packets) { + sendPacket.invoke(network, packet); + } } /** @@ -166,7 +136,9 @@ public static void send(Location loc, List packets, double range) throws Exception { range *= range; for (Player player : loc.getWorld().getPlayers()) { - if (player.getLocation().distanceSquared(loc) < range) { send(player, packets); } + if (player.getLocation().distanceSquared(loc) < range) { + send(player, packets); + } } } @@ -181,7 +153,9 @@ public static void send(Location loc, Object[] packets, double range) throws Exception { range *= range; for (Player player : loc.getWorld().getPlayers()) { - if (player.getLocation().distanceSquared(loc) < range) { send(player, packets); } + if (player.getLocation().distanceSquared(loc) < range) { + send(player, packets); + } } } @@ -190,9 +164,7 @@ public static void send(Location loc, Object[] packets, double range) * * @param settings particle details * @param loc location to play at - * * @return particle object or null if invalid - * * @throws Exception */ public static Object make(ParticleSettings settings, Location loc) @@ -207,14 +179,14 @@ public static Object make(ParticleSettings settings, Location loc) * @param x X coordinate * @param y Y coordinate * @param z Z coordinate - * * @return particle object or null if invalid - * * @throws Exception */ public static Object make(ParticleSettings settings, double x, double y, double z) throws Exception { // Invalid particle settings - if (settings == null || settings.type == null) { return null; } + if (settings == null || settings.type == null) { + return null; + } return make( settings.type.name(), @@ -243,8 +215,36 @@ public static Object make( Material material, int data) throws Exception { + + // 1.15+ servers + if (VersionManager.isVersionAtLeast(11500)) { + Object obj = data; + final org.bukkit.Particle bukkit = org.bukkit.Particle.valueOf(name); + switch (bukkit) { + case REDSTONE: + final Color color = Color.fromRGB((int) (255 * (dx + 1)), (int) (255 * dy), (int) (255 * dz)); + dx = 0; + dy = 0; + dz = 0; + obj = new org.bukkit.Particle.DustOptions(color, amount); + break; + case ITEM_CRACK: + obj = new ItemStack(material, 1, (short) 0, (byte) data); + break; + case BLOCK_CRACK: + case BLOCK_DUST: + case FALLING_DUST: + obj = material.createBlockData(); + default: + } + if (toNms == null) + init(); + final Object particle = new Particle(); + return packet.newInstance(particle, true, x, y, z, dx, dy, dz, speed, amount); + } + // 1.13+ servers - if (VersionManager.isVersionAtLeast(11300)) { + else if (VersionManager.isVersionAtLeast(11300)) { Object obj = data; final org.bukkit.Particle bukkit = org.bukkit.Particle.valueOf(name); switch (bukkit) { @@ -263,6 +263,8 @@ public static Object make( case FALLING_DUST: obj = material.createBlockData(); } + if (toNms == null) + init(); final Object particle = toNms.invoke(null, bukkit, obj); return packet.newInstance(particle, true, (float) x, (float) y, (float) z, dx, dy, dz, speed, amount); } @@ -281,7 +283,7 @@ else if (VersionManager.isVersionAtLeast(VersionManager.V1_8_0)) { dz, speed, amount, - material == null ? new int[0] : new int[] { material.ordinal(), data }); + material == null ? new int[0] : new int[]{material.ordinal(), data}); } // 1.7.x servers just use a string for the type, diff --git a/src/com/sucy/skill/api/particle/ParticleEffect.java b/src/main/java/com/sucy/skill/api/particle/ParticleEffect.java similarity index 100% rename from src/com/sucy/skill/api/particle/ParticleEffect.java rename to src/main/java/com/sucy/skill/api/particle/ParticleEffect.java diff --git a/src/com/sucy/skill/api/particle/ParticleLookup.java b/src/main/java/com/sucy/skill/api/particle/ParticleLookup.java similarity index 100% rename from src/com/sucy/skill/api/particle/ParticleLookup.java rename to src/main/java/com/sucy/skill/api/particle/ParticleLookup.java diff --git a/src/com/sucy/skill/api/particle/ParticleSettings.java b/src/main/java/com/sucy/skill/api/particle/ParticleSettings.java similarity index 99% rename from src/com/sucy/skill/api/particle/ParticleSettings.java rename to src/main/java/com/sucy/skill/api/particle/ParticleSettings.java index 8519c724..3e6e80cc 100644 --- a/src/com/sucy/skill/api/particle/ParticleSettings.java +++ b/src/main/java/com/sucy/skill/api/particle/ParticleSettings.java @@ -158,7 +158,7 @@ public ParticleSettings(DataSection config) { * * @return packet instance * - * @throws Exception + * @throws Exception thrown */ public Object instance(double x, double y, double z) throws Exception { diff --git a/src/com/sucy/skill/api/particle/ParticleType.java b/src/main/java/com/sucy/skill/api/particle/ParticleType.java similarity index 100% rename from src/com/sucy/skill/api/particle/ParticleType.java rename to src/main/java/com/sucy/skill/api/particle/ParticleType.java diff --git a/src/com/sucy/skill/api/particle/PolarSettings.java b/src/main/java/com/sucy/skill/api/particle/PolarSettings.java similarity index 100% rename from src/com/sucy/skill/api/particle/PolarSettings.java rename to src/main/java/com/sucy/skill/api/particle/PolarSettings.java diff --git a/src/main/java/com/sucy/skill/api/particle/SpigotParticles.java b/src/main/java/com/sucy/skill/api/particle/SpigotParticles.java new file mode 100644 index 00000000..d172a68e --- /dev/null +++ b/src/main/java/com/sucy/skill/api/particle/SpigotParticles.java @@ -0,0 +1,38 @@ +package com.sucy.skill.api.particle; + +/** + * SkillAPI © 2018 + * com.sucy.skill.api.particle.SpigotParticles + */ +public class SpigotParticles { + private static boolean error = true; + +// public static void play(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance) { +// play(loc, particle, dx, dy, dz, count, speed, distance, null); +// } +// +// public static void playItem(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { +// play(loc, particle, dx, dy, dz, count, speed, distance, material); +// } +// +// public static void playBlock(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { +// play(loc, particle, dx, dy, dz, count, speed, distance, material); +// } + +// private static void play(final Location loc, final String particle, final float dx, final float dy, final float dz, final int count, final float speed, final double distance, final Material material) { +// final Particle effect = Particle.valueOf(particle.toUpperCase().replace(' ', '_')); +// if (effect == null) return; +// +// try { +// final Object packet = com.sucy.skill.api.particle.Particle.make( +// effect.name(), loc.getX(), loc.getY(), loc.getZ(), dx, dy, dz, speed, count, material, 0); +// com.sucy.skill.api.particle.Particle.send(loc, ImmutableList.of(packet), distance); +// } catch (final Exception ex) { +// if (error) { +// ex.printStackTrace(); +// error = false; +// } +// } +// } + +} diff --git a/src/com/sucy/skill/api/particle/direction/DirectionHandler.java b/src/main/java/com/sucy/skill/api/particle/direction/DirectionHandler.java similarity index 100% rename from src/com/sucy/skill/api/particle/direction/DirectionHandler.java rename to src/main/java/com/sucy/skill/api/particle/direction/DirectionHandler.java diff --git a/src/com/sucy/skill/api/particle/direction/Directions.java b/src/main/java/com/sucy/skill/api/particle/direction/Directions.java similarity index 100% rename from src/com/sucy/skill/api/particle/direction/Directions.java rename to src/main/java/com/sucy/skill/api/particle/direction/Directions.java diff --git a/src/com/sucy/skill/api/particle/direction/XYHandler.java b/src/main/java/com/sucy/skill/api/particle/direction/XYHandler.java similarity index 100% rename from src/com/sucy/skill/api/particle/direction/XYHandler.java rename to src/main/java/com/sucy/skill/api/particle/direction/XYHandler.java diff --git a/src/com/sucy/skill/api/particle/direction/XZHandler.java b/src/main/java/com/sucy/skill/api/particle/direction/XZHandler.java similarity index 100% rename from src/com/sucy/skill/api/particle/direction/XZHandler.java rename to src/main/java/com/sucy/skill/api/particle/direction/XZHandler.java diff --git a/src/com/sucy/skill/api/particle/direction/YZHandler.java b/src/main/java/com/sucy/skill/api/particle/direction/YZHandler.java similarity index 100% rename from src/com/sucy/skill/api/particle/direction/YZHandler.java rename to src/main/java/com/sucy/skill/api/particle/direction/YZHandler.java diff --git a/src/com/sucy/skill/api/particle/target/EffectTarget.java b/src/main/java/com/sucy/skill/api/particle/target/EffectTarget.java similarity index 100% rename from src/com/sucy/skill/api/particle/target/EffectTarget.java rename to src/main/java/com/sucy/skill/api/particle/target/EffectTarget.java diff --git a/src/com/sucy/skill/api/particle/target/EntityTarget.java b/src/main/java/com/sucy/skill/api/particle/target/EntityTarget.java similarity index 100% rename from src/com/sucy/skill/api/particle/target/EntityTarget.java rename to src/main/java/com/sucy/skill/api/particle/target/EntityTarget.java diff --git a/src/com/sucy/skill/api/particle/target/FixedTarget.java b/src/main/java/com/sucy/skill/api/particle/target/FixedTarget.java similarity index 100% rename from src/com/sucy/skill/api/particle/target/FixedTarget.java rename to src/main/java/com/sucy/skill/api/particle/target/FixedTarget.java diff --git a/src/com/sucy/skill/api/particle/target/FollowTarget.java b/src/main/java/com/sucy/skill/api/particle/target/FollowTarget.java similarity index 100% rename from src/com/sucy/skill/api/particle/target/FollowTarget.java rename to src/main/java/com/sucy/skill/api/particle/target/FollowTarget.java diff --git a/src/com/sucy/skill/api/particle/target/Followable.java b/src/main/java/com/sucy/skill/api/particle/target/Followable.java similarity index 100% rename from src/com/sucy/skill/api/particle/target/Followable.java rename to src/main/java/com/sucy/skill/api/particle/target/Followable.java diff --git a/src/com/sucy/skill/api/player/PlayerAccounts.java b/src/main/java/com/sucy/skill/api/player/PlayerAccounts.java similarity index 95% rename from src/com/sucy/skill/api/player/PlayerAccounts.java rename to src/main/java/com/sucy/skill/api/player/PlayerAccounts.java index 720d99c6..e7d9e20f 100644 --- a/src/com/sucy/skill/api/player/PlayerAccounts.java +++ b/src/main/java/com/sucy/skill/api/player/PlayerAccounts.java @@ -29,6 +29,7 @@ import com.rit.sucy.version.VersionPlayer; import com.sucy.skill.SkillAPI; import com.sucy.skill.api.event.PlayerAccountChangeEvent; +import com.sucy.skill.api.event.PlayerAttributeLoadEvent; import com.sucy.skill.listener.AttributeListener; import com.sucy.skill.manager.ClassBoardManager; import org.bukkit.Bukkit; @@ -89,7 +90,11 @@ public PlayerData getActiveData() { * @return Bukkit player object or null if offline/dead */ public Player getPlayer() { - return player.getPlayer(); + return player.getPlayer(); + } + + public void setPlayer(OfflinePlayer p) { + this.player = p; } /** @@ -208,7 +213,7 @@ public void setAccount(int id, boolean apply) { } if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { - ClassBoardManager.clear(new VersionPlayer(player)); + // ClassBoardManager.clear(new VersionPlayer(player)); getActiveData().stopPassives(player); AttributeListener.clearBonuses(player); getActiveData().clearBonuses(); @@ -222,6 +227,7 @@ public void setAccount(int id, boolean apply) { getActiveData().getSkillBar().setup(player); } getActiveData().getEquips().update(player); + Bukkit.getPluginManager().callEvent(new PlayerAttributeLoadEvent(player)); } else { active = event.getNewID(); } diff --git a/src/com/sucy/skill/api/player/PlayerClass.java b/src/main/java/com/sucy/skill/api/player/PlayerClass.java similarity index 94% rename from src/com/sucy/skill/api/player/PlayerClass.java rename to src/main/java/com/sucy/skill/api/player/PlayerClass.java index 31849ee7..dd5d8112 100644 --- a/src/com/sucy/skill/api/player/PlayerClass.java +++ b/src/main/java/com/sucy/skill/api/player/PlayerClass.java @@ -1,510 +1,526 @@ -/** - * SkillAPI - * com.sucy.skill.api.player.PlayerClass - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.api.player; - -import com.rit.sucy.config.Filter; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.enums.ExpSource; -import com.sucy.skill.api.enums.PointSource; -import com.sucy.skill.api.event.PlayerExperienceGainEvent; -import com.sucy.skill.api.event.PlayerExperienceLostEvent; -import com.sucy.skill.api.event.PlayerGainSkillPointsEvent; -import com.sucy.skill.api.event.PlayerLevelUpEvent; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.data.TitleType; -import com.sucy.skill.dynamic.DynamicSkill; -import com.sucy.skill.language.NotificationNodes; -import com.sucy.skill.language.RPGFilter; -import com.sucy.skill.manager.TitleManager; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -/** - *

Represents a player's class progress.

- *

- *

This class if for handling individual players.

- *

- *

This does not include information about the class specifically, - * rather what the player has within the class. For more general information - * about the class, you should use the RPGClass class.

- */ -public class PlayerClass -{ - private PlayerData player; - private RPGClass classData; - private int level; - private int points; - private double exp; - - /////////////////////////////////////////////////////// - // // - // Constructors // - // // - /////////////////////////////////////////////////////// - - /** - * Initializes a new PlayerClass. This should not be used - * by other plugins as the API provides the data. Get - * instances from the PlayerData object. - * - * @param player owning player data - * @param classData class template - */ - public PlayerClass(PlayerData player, RPGClass classData) - { - this.player = player; - this.classData = classData; - this.level = 1; - this.points = SkillAPI.getSettings().getGroupSettings(classData.getGroup()).getStartingPoints(); - this.exp = 0; - - for (Skill skill : classData.getSkills()) - { - player.giveSkill(skill, this); - } - } - - /////////////////////////////////////////////////////// - // // - // Accessor Methods // - // // - /////////////////////////////////////////////////////// - - /** - *

Retrieves the data of the player owning this class.

- * - * @return data of owning player - */ - public PlayerData getPlayerData() - { - return player; - } - - /** - *

Retrieves the generic data for the class.

- * - * @return generic data for the class - */ - public RPGClass getData() - { - return classData; - } - - /** - *

Retrieves the experience of the class towards the next level.

- *

This should not ever be higher than the required experience.

- * - * @return the current experience of the class towards the next level - */ - public double getExp() - { - return exp; - } - - /** - *

Retrieves the required experience to level up to the next level.

- * - * @return the current required experience - */ - public int getRequiredExp() - { - return classData.getRequiredExp(level); - } - - /** - *

Retrieves the total amount of experience the player has accumulated - * for this class since professing as it.

- * - * @return total accumulated experience for the class - */ - public double getTotalExp() - { - double exp = this.exp; - for (int i = 1; i < level; i++) - exp += classData.getRequiredExp(i); - return exp; - } - - /** - *

Retrieves the current level of the class.

- *

This should never be less than 1 or greater than the maximum level.

- * - * @return current level of the class - */ - public int getLevel() - { - return level; - } - - /** - *

Retrieves the number of skill points the class has currently available.

- *

This should never be a negative number.

- * - * @return number of available skill points - */ - public int getPoints() - { - return points; - } - - /** - *

Checks whether or not the class has reached the max level.

- * - * @return true if max level, false otherwise - */ - public boolean isLevelMaxed() - { - return level == classData.getMaxLevel(); - } - - /** - * Retrieves the amount of health this class provides the player - * - * @return health provided for the player by this class - */ - public double getHealth() - { - return classData.getHealth(level); - } - - /** - * Retrieves the amount of mana this class provides the player - * - * @return mana provided for the player by this class - */ - public double getMana() - { - return classData.getMana(level); - } - - /////////////////////////////////////////////////////// - // // - // Functional Methods // - // // - /////////////////////////////////////////////////////// - - /** - *

Gives skill points to be used for the class.

- *

The number of points cannot be negative.

- *

This calls an event that can be cancelled or have the number - * of points modified.

- *

This treats the points as coming from the source "SPECIAL".

- * - * @param amount amount of points to give - * - * @throws java.lang.IllegalArgumentException if the points are less than 1 - */ - public void givePoints(int amount) - { - givePoints(amount, PointSource.SPECIAL); - } - - /** - *

Gives skill points to be used for the class.

- *

The number of points cannot be negative.

- *

This calls an event that can be cancelled or have the number - * of points modified.

- * - * @param amount amount of points to give - * @param source source of the points - * - * @throws java.lang.IllegalArgumentException if the points are less than 1 - */ - public void givePoints(int amount, PointSource source) - { - // Cannot give a non-positive amount of points - if (amount < 1) - { - throw new IllegalArgumentException("Invalid point amount - cannot be less than 1"); - } - - // Call the event - PlayerGainSkillPointsEvent event = new PlayerGainSkillPointsEvent(this, amount, source); - Bukkit.getPluginManager().callEvent(event); - - // Add the points if not cancelled - if (!event.isCancelled()) - { - points += event.getAmount(); - } - } - - /** - * Uses points from the player for skill upgrades. - * - * @param amount amount of points to use - */ - public void usePoints(int amount) - { - // Cannot use too few points - if (amount < 0) - { - throw new IllegalArgumentException("Invalid points amount - cannot be less than 1"); - } - - // Cannot use more points than obtained - if (amount > points) - { - throw new IllegalArgumentException("Invalid points amount - more than current total"); - } - - // Use the points - points -= amount; - } - - /** - *

Sets the amount of points the player's class has without - * launching an event.

- *

This cannot be less than 0.

- *

This is used primarily for initialization. You should generally - * use givePoints(int, PointSource) instead.

- * - * @param amount number of points to set it to - */ - public void setPoints(int amount) - { - // Cannot have a negative amount of points - if (amount < 0) - { - throw new IllegalArgumentException("Invalid point amount - cannot be less than 1"); - } - - // Set the points - points = amount; - } - - /** - *

Gives experience to the class under the context of the experience source.

- *

This will also check for leveling up after the experience is added.

- *

If the class does not normally receive experience from the source, - * it will still launch an experience event, just it will start off as - * cancelled in case it should still be given in select circumstances.

- * - * @param amount amount of experience to give - * @param source type of the source of the experience - */ - public void giveExp(double amount, ExpSource source) { - giveExp(amount, source, true); - } - - /** - *

Gives experience to the class under the context of the experience source.

- *

This will also check for leveling up after the experience is added.

- *

If the class does not normally receive experience from the source, - * it will still launch an experience event, just it will start off as - * cancelled in case it should still be given in select circumstances.

- * - * @param amount amount of experience to give - * @param source type of the source of the experience - * @param showMessage whether or not to show the configured message if enabled - */ - public void giveExp(double amount, ExpSource source, boolean showMessage) - { - // Cannot give a non-positive amount of exp - if (amount <= 0 || level >= classData.getMaxLevel()) - { - return; - } - - // Call an event for the experience gained - PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, amount, source); - event.setCancelled(!classData.receivesExp(source)); - Bukkit.getPluginManager().callEvent(event); - - int rounded = (int)Math.ceil(event.getExp()); - - // Add experience if not cancelled - if (!event.isCancelled() && rounded > 0) - { - if (showMessage && SkillAPI.getSettings().isShowExpMessages() && player.getPlayer() != null) - { - TitleManager.show( - player.getPlayer(), - TitleType.EXP_GAINED, - NotificationNodes.EXP, - RPGFilter.EXP.setReplacement(rounded + ""), - RPGFilter.CLASS.setReplacement(classData.getName()), - Filter.AMOUNT.setReplacement(rounded + "") - ); - } - - exp += rounded; - checkLevelUp(); - } - } - - /** - * Causes the player to lose experience as a penalty (generally for dying). - * This does not lower experience below 0 and will launch an event before - * taking the experience. - * - * @param percent percent of experience to lose - */ - public void loseExp(double percent) - { - double amount = percent * getRequiredExp(); - - // Launch the event - PlayerExperienceLostEvent event = new PlayerExperienceLostEvent(this, amount); - Bukkit.getPluginManager().callEvent(event); - - // Subtract the experience - if (!event.isCancelled()) - { - amount = Math.min(event.getExp(), exp); - exp = exp - amount; - - // Exp loss message - if (SkillAPI.getSettings().isShowLossMessages() && (int) amount > 0) - { - TitleManager.show( - player.getPlayer(), - TitleType.EXP_LOST, - NotificationNodes.LOSE, - RPGFilter.EXP.setReplacement((int) amount + ""), - RPGFilter.CLASS.setReplacement(classData.getName()), - Filter.AMOUNT.setReplacement((int) amount + "") - ); - } - } - } - - /** - *

Checks whether or not the player has leveled up based on - * their current experience.

- */ - private void checkLevelUp() - { - // Count the number of levels gained, if any - int levels = 0; - int required; - while (exp >= (required = classData.getRequiredExp(level + levels)) && level + levels < classData.getMaxLevel()) - { - exp -= required; - levels++; - } - - // Give the levels if applicable - if (levels > 0) - { - giveLevels(levels); - - // Level up message - if (SkillAPI.getSettings().isShowLevelMessages()) - { - TitleManager.show( - player.getPlayer(), - TitleType.LEVEL_UP, - NotificationNodes.LVL, - RPGFilter.LEVEL.setReplacement(level + ""), - RPGFilter.CLASS.setReplacement(classData.getName()), - RPGFilter.POINTS.setReplacement(points + ""), - Filter.AMOUNT.setReplacement(levels + "") - ); - } - } - } - - /** - *

Gives levels to the player's class, leveling it up.

- *

The amount of levels must be a positive number.

- *

This will launch a level event for the gained levels.

- * - * @param amount amount of levels to give - * - * @throws java.lang.IllegalArgumentException when the level amount is less than 1 - */ - public void giveLevels(int amount) - { - // Cannot give non-positive amount of levels - if (amount < 1) - { - throw new IllegalArgumentException("Invalid level amount - cannot be less than 1"); - } - - // Level up - amount = Math.min(amount, classData.getMaxLevel() - level); - if (amount <= 0) return; - level += amount; - points += classData.getGroupSettings().getPointsForLevels(level, level - amount); - getPlayerData().giveAttribPoints(classData.getGroupSettings().getAttribsForLevels(level, level - amount)); - - // Update health/mana - final Player player = getPlayerData().getPlayer(); - if (player != null) { - getPlayerData().updateHealthAndMana(getPlayerData().getPlayer()); - getPlayerData().getEquips().update(getPlayerData().getPlayer()); - } - getPlayerData().autoLevel(); - - // Call the event - PlayerLevelUpEvent event = new PlayerLevelUpEvent(this, amount); - Bukkit.getPluginManager().callEvent(event); - - // Apply the effect - if (SkillAPI.getSettings().hasLevelUpEffect()) - { - DynamicSkill skill = SkillAPI.getSettings().getLevelUpSkill(); - skill.cast(player, level); - } - } - - /** - * Sets the level for the class - * - * @param level level to set to - */ - public void setLevel(int level) - { - if (level < 1) - throw new IllegalArgumentException("Cannot be a level less than 0"); - - this.level = level; - } - - /** - * Sets the current experience for the player - * - * @param exp experience to set to - */ - public void setExp(double exp) - { - this.exp = Math.max(Math.min(exp, getRequiredExp() - 1), 0); - } - - /** - * Sets the class data this player class is based off of, optionally - * resetting the class progress. - * - * @param classData class data to switch to - */ - public void setClassData(RPGClass classData) - { - this.classData = classData; - } -} +/** + * SkillAPI + * com.sucy.skill.api.player.PlayerClass + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.player; + +import com.rit.sucy.config.Filter; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.classes.RPGClass; +import com.sucy.skill.api.enums.ExpSource; +import com.sucy.skill.api.enums.PointSource; +import com.sucy.skill.api.event.PlayerExperienceGainEvent; +import com.sucy.skill.api.event.PlayerExperienceLostEvent; +import com.sucy.skill.api.event.PlayerGainSkillPointsEvent; +import com.sucy.skill.api.event.PlayerLevelUpEvent; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.data.TitleType; +import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.language.NotificationNodes; +import com.sucy.skill.language.RPGFilter; +import com.sucy.skill.log.LogType; +import com.sucy.skill.log.Logger; +import com.sucy.skill.manager.TitleManager; + +import java.util.logging.Level; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + *

Represents a player's class progress.

+ *

+ *

This class if for handling individual players.

+ *

+ *

This does not include information about the class specifically, + * rather what the player has within the class. For more general information + * about the class, you should use the RPGClass class.

+ */ +public class PlayerClass +{ + private PlayerData player; + private RPGClass classData; + private int level; + private int points; + private double exp; + + /////////////////////////////////////////////////////// + // // + // Constructors // + // // + /////////////////////////////////////////////////////// + + /** + * Initializes a new PlayerClass. This should not be used + * by other plugins as the API provides the data. Get + * instances from the PlayerData object. + * + * @param player owning player data + * @param classData class template + */ + public PlayerClass(PlayerData player, RPGClass classData) + { + this.player = player; + this.classData = classData; + this.level = 1; + this.points = SkillAPI.getSettings().getGroupSettings(classData.getGroup()).getStartingPoints(); + this.exp = 0; + + for (Skill skill : classData.getSkills()) + { + player.giveSkill(skill, this); + } + + // Load global skills + for (String skillKey : SkillAPI.getSettings().getGlobalSkills()) { + try { + player.giveSkill(SkillAPI.getSkill(skillKey), this); + } + catch (Exception e){ + Bukkit.getLogger().log(Level.WARNING, "Could not load skill: " + skillKey + " for player " + player.getPlayer().getName()); + e.printStackTrace(); + } + } + } + + /////////////////////////////////////////////////////// + // // + // Accessor Methods // + // // + /////////////////////////////////////////////////////// + + /** + *

Retrieves the data of the player owning this class.

+ * + * @return data of owning player + */ + public PlayerData getPlayerData() + { + return player; + } + + /** + *

Retrieves the generic data for the class.

+ * + * @return generic data for the class + */ + public RPGClass getData() + { + return classData; + } + + /** + *

Retrieves the experience of the class towards the next level.

+ *

This should not ever be higher than the required experience.

+ * + * @return the current experience of the class towards the next level + */ + public double getExp() + { + return exp; + } + + /** + *

Retrieves the required experience to level up to the next level.

+ * + * @return the current required experience + */ + public int getRequiredExp() + { + return classData.getRequiredExp(level); + } + + /** + *

Retrieves the total amount of experience the player has accumulated + * for this class since professing as it.

+ * + * @return total accumulated experience for the class + */ + public double getTotalExp() + { + double exp = this.exp; + for (int i = 1; i < level; i++) + exp += classData.getRequiredExp(i); + return exp; + } + + /** + *

Retrieves the current level of the class.

+ *

This should never be less than 1 or greater than the maximum level.

+ * + * @return current level of the class + */ + public int getLevel() + { + return level; + } + + /** + *

Retrieves the number of skill points the class has currently available.

+ *

This should never be a negative number.

+ * + * @return number of available skill points + */ + public int getPoints() + { + return points; + } + + /** + *

Checks whether or not the class has reached the max level.

+ * + * @return true if max level, false otherwise + */ + public boolean isLevelMaxed() + { + return level == classData.getMaxLevel(); + } + + /** + * Retrieves the amount of health this class provides the player + * + * @return health provided for the player by this class + */ + public double getHealth() + { + return classData.getHealth(level); + } + + /** + * Retrieves the amount of mana this class provides the player + * + * @return mana provided for the player by this class + */ + public double getMana() + { + return classData.getMana(level); + } + + /////////////////////////////////////////////////////// + // // + // Functional Methods // + // // + /////////////////////////////////////////////////////// + + /** + *

Gives skill points to be used for the class.

+ *

The number of points cannot be negative.

+ *

This calls an event that can be cancelled or have the number + * of points modified.

+ *

This treats the points as coming from the source "SPECIAL".

+ * + * @param amount amount of points to give + * + * @throws java.lang.IllegalArgumentException if the points are less than 1 + */ + public void givePoints(int amount) + { + givePoints(amount, PointSource.SPECIAL); + } + + /** + *

Gives skill points to be used for the class.

+ *

The number of points cannot be negative.

+ *

This calls an event that can be cancelled or have the number + * of points modified.

+ * + * @param amount amount of points to give + * @param source source of the points + * + * @throws java.lang.IllegalArgumentException if the points are less than 1 + */ + public void givePoints(int amount, PointSource source) + { + // Cannot give a non-positive amount of points + if (amount < 1) + { + throw new IllegalArgumentException("Invalid point amount - cannot be less than 1"); + } + + // Call the event + PlayerGainSkillPointsEvent event = new PlayerGainSkillPointsEvent(this, amount, source); + Bukkit.getPluginManager().callEvent(event); + + // Add the points if not cancelled + if (!event.isCancelled()) + { + points += event.getAmount(); + } + } + + /** + * Uses points from the player for skill upgrades. + * + * @param amount amount of points to use + */ + public void usePoints(int amount) + { + // Cannot use too few points + if (amount < 0) + { + throw new IllegalArgumentException("Invalid points amount - cannot be less than 1"); + } + + // Cannot use more points than obtained + if (amount > points) + { + throw new IllegalArgumentException("Invalid points amount - more than current total"); + } + + // Use the points + points -= amount; + } + + /** + *

Sets the amount of points the player's class has without + * launching an event.

+ *

This cannot be less than 0.

+ *

This is used primarily for initialization. You should generally + * use givePoints(int, PointSource) instead.

+ * + * @param amount number of points to set it to + */ + public void setPoints(int amount) + { + // Cannot have a negative amount of points + if (amount < 0) + { + throw new IllegalArgumentException("Invalid point amount - cannot be less than 1"); + } + + // Set the points + points = amount; + } + + /** + *

Gives experience to the class under the context of the experience source.

+ *

This will also check for leveling up after the experience is added.

+ *

If the class does not normally receive experience from the source, + * it will still launch an experience event, just it will start off as + * cancelled in case it should still be given in select circumstances.

+ * + * @param amount amount of experience to give + * @param source type of the source of the experience + */ + public void giveExp(double amount, ExpSource source) { + giveExp(amount, source, true); + } + + /** + *

Gives experience to the class under the context of the experience source.

+ *

This will also check for leveling up after the experience is added.

+ *

If the class does not normally receive experience from the source, + * it will still launch an experience event, just it will start off as + * cancelled in case it should still be given in select circumstances.

+ * + * @param amount amount of experience to give + * @param source type of the source of the experience + * @param showMessage whether or not to show the configured message if enabled + */ + public void giveExp(double amount, ExpSource source, boolean showMessage) + { + // Cannot give a non-positive amount of exp + if (amount <= 0 || level >= classData.getMaxLevel()) + { + return; + } + + // Call an event for the experience gained + PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, amount, source); + event.setCancelled(!classData.receivesExp(source)); + Bukkit.getPluginManager().callEvent(event); + + int rounded = (int)Math.ceil(event.getExp()); + + // Add experience if not cancelled + if (!event.isCancelled() && rounded > 0) + { + if (showMessage && SkillAPI.getSettings().isShowExpMessages() && player.getPlayer() != null) + { + TitleManager.show( + player.getPlayer(), + TitleType.EXP_GAINED, + NotificationNodes.EXP, + RPGFilter.EXP.setReplacement(rounded + ""), + RPGFilter.CLASS.setReplacement(classData.getName()), + Filter.AMOUNT.setReplacement(rounded + "") + ); + } + + exp += rounded; + checkLevelUp(); + } + } + + /** + * Causes the player to lose experience as a penalty (generally for dying). + * This does not lower experience below 0 and will launch an event before + * taking the experience. + * + * @param percent percent of experience to lose + */ + public void loseExp(double percent) + { + double amount = percent * getRequiredExp(); + + // Launch the event + PlayerExperienceLostEvent event = new PlayerExperienceLostEvent(this, amount); + Bukkit.getPluginManager().callEvent(event); + + // Subtract the experience + if (!event.isCancelled()) + { + amount = Math.min(event.getExp(), exp); + exp = exp - amount; + + // Exp loss message + if (SkillAPI.getSettings().isShowLossMessages() && (int) amount > 0) + { + TitleManager.show( + player.getPlayer(), + TitleType.EXP_LOST, + NotificationNodes.LOSE, + RPGFilter.EXP.setReplacement((int) amount + ""), + RPGFilter.CLASS.setReplacement(classData.getName()), + Filter.AMOUNT.setReplacement((int) amount + "") + ); + } + } + } + + /** + *

Checks whether or not the player has leveled up based on + * their current experience.

+ */ + private void checkLevelUp() + { + // Count the number of levels gained, if any + int levels = 0; + int required; + while (exp >= (required = classData.getRequiredExp(level + levels)) && level + levels < classData.getMaxLevel()) + { + exp -= required; + levels++; + } + + // Give the levels if applicable + if (levels > 0) + { + giveLevels(levels); + + // Level up message + if (SkillAPI.getSettings().isShowLevelMessages()) + { + TitleManager.show( + player.getPlayer(), + TitleType.LEVEL_UP, + NotificationNodes.LVL, + RPGFilter.LEVEL.setReplacement(level + ""), + RPGFilter.CLASS.setReplacement(classData.getName()), + RPGFilter.POINTS.setReplacement(points + ""), + Filter.AMOUNT.setReplacement(levels + "") + ); + } + } + } + + /** + *

Gives levels to the player's class, leveling it up.

+ *

The amount of levels must be a positive number.

+ *

This will launch a level event for the gained levels.

+ * + * @param amount amount of levels to give + * + * @throws java.lang.IllegalArgumentException when the level amount is less than 1 + */ + public void giveLevels(int amount) + { + // Cannot give non-positive amount of levels + if (amount < 1) + { + throw new IllegalArgumentException("Invalid level amount - cannot be less than 1"); + } + + // Level up + amount = Math.min(amount, classData.getMaxLevel() - level); + if (amount <= 0) return; + level += amount; + points += classData.getGroupSettings().getPointsForLevels(level, level - amount); + getPlayerData().giveAttribPoints(classData.getGroupSettings().getAttribsForLevels(level, level - amount)); + + // Update health/mana + final Player player = getPlayerData().getPlayer(); + if (player != null) { + getPlayerData().updateHealthAndMana(getPlayerData().getPlayer()); + getPlayerData().getEquips().update(getPlayerData().getPlayer()); + } + getPlayerData().autoLevel(); + + // Call the event + PlayerLevelUpEvent event = new PlayerLevelUpEvent(this, amount); + Bukkit.getPluginManager().callEvent(event); + + // Apply the effect + if (SkillAPI.getSettings().hasLevelUpEffect()) + { + DynamicSkill skill = SkillAPI.getSettings().getLevelUpSkill(); + skill.cast(player, level); + } + } + + /** + * Sets the level for the class + * + * @param level level to set to + */ + public void setLevel(int level) + { + if (level < 1) + throw new IllegalArgumentException("Cannot be a level less than 0"); + + this.level = level; + } + + /** + * Sets the current experience for the player + * + * @param exp experience to set to + */ + public void setExp(double exp) + { + this.exp = Math.max(Math.min(exp, getRequiredExp() - 1), 0); + } + + /** + * Sets the class data this player class is based off of, optionally + * resetting the class progress. + * + * @param classData class data to switch to + */ + public void setClassData(RPGClass classData) + { + this.classData = classData; + } +} diff --git a/src/com/sucy/skill/api/player/PlayerCombos.java b/src/main/java/com/sucy/skill/api/player/PlayerCombos.java similarity index 100% rename from src/com/sucy/skill/api/player/PlayerCombos.java rename to src/main/java/com/sucy/skill/api/player/PlayerCombos.java diff --git a/src/main/java/com/sucy/skill/api/player/PlayerData.java b/src/main/java/com/sucy/skill/api/player/PlayerData.java new file mode 100644 index 00000000..fb8bf82c --- /dev/null +++ b/src/main/java/com/sucy/skill/api/player/PlayerData.java @@ -0,0 +1,2040 @@ +/** + * SkillAPI + * com.sucy.skill.api.player.PlayerData + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.player; + +import com.rit.sucy.config.Filter; +import com.rit.sucy.config.FilterType; +import com.rit.sucy.config.parse.DataSection; +import com.rit.sucy.player.TargetHelper; +import com.rit.sucy.version.VersionManager; +import com.rit.sucy.version.VersionPlayer; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.classes.RPGClass; +import com.sucy.skill.api.enums.*; +import com.sucy.skill.api.event.*; +import com.sucy.skill.api.skills.PassiveSkill; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.api.skills.SkillShot; +import com.sucy.skill.api.skills.TargetSkill; +import com.sucy.skill.cast.PlayerCastBars; +import com.sucy.skill.data.GroupSettings; +import com.sucy.skill.data.PlayerEquips; +import com.sucy.skill.dynamic.EffectComponent; +import com.sucy.skill.gui.handlers.AttributeHandler; +import com.sucy.skill.gui.handlers.DetailsHandler; +import com.sucy.skill.gui.handlers.ProfessHandler; +import com.sucy.skill.gui.handlers.SkillHandler; +import com.sucy.skill.gui.tool.GUITool; +import com.sucy.skill.language.ErrorNodes; +import com.sucy.skill.language.GUINodes; +import com.sucy.skill.language.RPGFilter; +import com.sucy.skill.listener.AttributeListener; +import com.sucy.skill.log.LogType; +import com.sucy.skill.log.Logger; +import com.sucy.skill.manager.AttributeManager; +import com.sucy.skill.task.ScoreboardTask; + +import net.md_5.bungee.api.ChatColor; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import java.util.*; + +import static com.sucy.skill.api.event.PlayerSkillCastFailedEvent.Cause.*; + +/** + * Represents one account for a player which can contain one class from each + * group and the skills in each of those classes. You should not instantiate + * this class yourself and instead get it from the SkillAPI static methods. + * + * In order to get a player's data, use "SkillAPI.getPlayerData(...)". Do NOT + * try to instantaite your own PlayerData object. + */ +public class PlayerData { + private final HashMap classes = new HashMap<>(); + private final HashMap skills = new HashMap<>(); + private final HashMap binds = new HashMap<>(); + private final HashMap attributes = new HashMap<>(); + private final HashMap bonusAttrib = new HashMap<>(); + + private DataSection extraData = new DataSection(); + private OfflinePlayer player; + private PlayerSkillBar skillBar; + private PlayerCastBars castBars; + private PlayerCombos combos; + private PlayerEquips equips; + private String scheme; + private String menuClass; + private double mana; + private double maxMana; + private double bonusHealth; + private double bonusMana; + private double lastHealth; + private double hunger; + private boolean init; + private boolean passive; + private int attribPoints; + private long skillTimer; + + /** + * Initializes a new account data representation for a player. + * + * @param player player to store the data for + */ + PlayerData(OfflinePlayer player, boolean init) { + this.player = player; + this.skillBar = new PlayerSkillBar(this); + this.castBars = new PlayerCastBars(this); + this.combos = new PlayerCombos(this); + this.equips = new PlayerEquips(this); + this.init = SkillAPI.isLoaded() && init; + this.scheme = "default"; + this.hunger = 1; + for (String group : SkillAPI.getGroups()) { + GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); + RPGClass rpgClass = settings.getDefault(); + + if (rpgClass != null && settings.getPermission() == null) { + setClass(rpgClass); + } + } + } + + /** + * Retrieves the Bukkit player object of the owner + * + * @return Bukkit player object of the owner or null if offline + */ + public Player getPlayer() { + return player.getPlayer(); + } + + public void setPlayer(OfflinePlayer p) { + this.player = p; + } + + /** + * Retrieves the name of the owner + * + * @return name of the owner + */ + public String getPlayerName() { + return player.getName(); + } + + public UUID getUUID() { + return player.getUniqueId(); + } + + /** + * Retrieves the skill bar data for the owner + * + * @return skill bar data of the owner + */ + public PlayerSkillBar getSkillBar() { + return skillBar; + } + + /** + * @return cast bars data for the player + */ + public PlayerCastBars getCastBars() { + return castBars; + } + + /** + * Returns the data for the player's combos + * + * @return combo data for the player + */ + public PlayerCombos getComboData() { + return combos; + } + + /** + * @return extra data attached to the player's account + */ + public DataSection getExtraData() { + return extraData; + } + + /** + * @return equipped item data + */ + public PlayerEquips getEquips() { + return equips; + } + + /** + * @return health during last logout + */ + public double getLastHealth() { + return lastHealth; + } + + /** + * Used by the API for restoring health - do not use this. + * + * @param health health logged off with + */ + public void setLastHealth(double health) { + lastHealth = health; + } + + /** + * The hunger value here is not representative of the player's total hunger, + * rather the amount left of the next hunger point. This is manipulated by + * attributes were if an attribute says a player has twice as much "hunger" as + * normal, this will go down by decimals to slow the decay of hunger. + * + * @return amount of the next hunger point the player has + */ + public double getHungerValue() { + return hunger; + } + + /** + * @param hungerValue new hunger value + * @see PlayerData#getHungerValue + */ + public void setHungerValue(final double hungerValue) { + this.hunger = hungerValue; + } + + public int subtractHungerValue(final double amount) { + final double scaled = amount / scaleStat(AttributeManager.HUNGER, amount); + final int lost = scaled >= hunger ? (int) (scaled - hunger) + 1 : 0; + this.hunger += lost - amount; + return lost; + } + + /** + * Ends the initialization flag for the data. Used by the API to avoid async + * issues. Do not use this in other plugins. + */ + public void endInit() { + init = false; + } + + /** + * Retrieves the name of the active map menu scheme for the player + * + * @return map menu scheme name + */ + public String getScheme() { + return scheme; + } + + /** + * Sets the active scheme name for the player + * + * @param name name of the scheme + */ + public void setScheme(String name) { + scheme = name; + } + + /////////////////////////////////////////////////////// + // // + // Attributes // + // // + /////////////////////////////////////////////////////// + + /** + * Retrieves a map of all player attribute totals. Modifying the map will not + * change actual player attributes. + * + * @return attribute totals + */ + public HashMap getAttributes() { + HashMap map = new HashMap<>(); + for (String key : SkillAPI.getAttributeManager().getKeys()) { + map.put(key, getAttribute(key)); + } + return map; + } + + /** + * Retrieves a map of all attributes the player invested. This doesn't count + * base attributes from classes or bonus attributes from effects. Modifying the + * map will not change actual player attributes. + * + * @return attribute totals + */ + public HashMap getInvestedAttributes() { + return new HashMap<>(attributes); + } + + /** + * Gets the number of attribute points the player has between invested and bonus + * sources. + * + * @param key attribute key + * + * @return number of total points + */ + public int getAttribute(String key) { + key = key.toLowerCase(); + int total = 0; + if (attributes.containsKey(key)) { + total += attributes.get(key); + } + if (bonusAttrib.containsKey(key)) { + total += bonusAttrib.get(key); + } + for (PlayerClass playerClass : classes.values()) { + total += playerClass.getData().getAttribute(key, playerClass.getLevel()); + } + return Math.max(0, total); + } + + /** + * Gets the number of attribute points invested in the given attribute + * + * @param key attribute key + * + * @return number of invested points + */ + public int getInvestedAttribute(String key) { + return attributes.getOrDefault(key.toLowerCase(), 0); + } + + /** + * Checks whether or not the player has any points invested in a given attribute + * + * @param key attribute key + * + * @return true if any points are invested, false otherwise + */ + public boolean hasAttribute(String key) { + return getAttribute(key) > 0; + } + + /** + * Invests a point in the attribute if the player has any remaining attribute + * points. If the player has no remaining points, this will do nothing. + * + * @param key attribute key + * + * @return whether or not it was successfully upgraded + */ + public boolean upAttribute(String key) { + key = key.toLowerCase(); + int current = getInvestedAttribute(key); + int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); + if (attribPoints > 0 && current < max) { + attributes.put(key, current + 1); + attribPoints--; + + PlayerUpAttributeEvent event = new PlayerUpAttributeEvent(this, key); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + attributes.put(key, current); + attribPoints++; + } + else { + return true; + } + } + return false; + } + + /** + * Gives the player attribute points without costing attribute points. + * + * @param key attribute to give points for + * @param amount amount to give + */ + public void giveAttribute(String key, int amount) { + key = key.toLowerCase(); + int current = getInvestedAttribute(key); + int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); + amount = Math.min(amount + current, max); + if (amount > current) { + attributes.put(key, amount); + AttributeListener.updatePlayer(this); + } + } + + /** + * Adds bonus attributes to the player. These do not count towards the max + * invest amount and cannot be refunded. + * + * @param key attribute key + * @param amount amount to add + */ + public void addBonusAttributes(String key, int amount) { + key = SkillAPI.getAttributeManager().normalize(key); + amount += bonusAttrib.getOrDefault(key, 0); + bonusAttrib.put(key, amount); + AttributeListener.updatePlayer(this); + } + + /** + * Refunds an attribute point from the given attribute if there are any points + * invested in it. If there are none, this will do nothing. + * + * @param key attribute key + */ + public boolean refundAttribute(String key) { + key = key.toLowerCase(); + int current = getInvestedAttribute(key); + if (current > 0) { + PlayerRefundAttributeEvent event = new PlayerRefundAttributeEvent(this, key); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + + attribPoints += 1; + attributes.put(key, current - 1); + if (current - 1 <= 0) { + attributes.remove(key); + } + AttributeListener.updatePlayer(this); + + return true; + } + return false; + } + + /** + * Refunds all spent attribute points for a specific attribute + */ + public void refundAttributes(String key) { + key = key.toLowerCase(); + attribPoints += getInvestedAttribute(key); + attributes.remove(key); + AttributeListener.updatePlayer(this); + } + + /** + * Refunds all spent attribute points + */ + public void refundAttributes() { + ArrayList keys = new ArrayList<>(attributes.keySet()); + for (String key : keys) { + refundAttributes(key); + } + } + + /** + * Retrieves the current number of attribute points the player has + * + * @return attribute point total + */ + public int getAttributePoints() { + return attribPoints; + } + + /** + * Gives the player attribute points + * + * @param amount amount of attribute points + */ + public void giveAttribPoints(int amount) { + attribPoints += amount; + } + + /** + * Sets the current amount of attribute points + * + * @param amount amount of points to have + */ + public void setAttribPoints(int amount) { + attribPoints = amount; + } + + /** + * Scales a stat value using the player's attributes + * + * @param stat stat key + * @param value base value + * + * @return modified value + */ + public double scaleStat(final String stat, final double value) { + final AttributeManager manager = SkillAPI.getAttributeManager(); + if (manager == null) { + return value; + } + + final List matches = manager.forStat(stat); + if (matches == null) { + return value; + } + + double modified = value; + for (final AttributeManager.Attribute attribute : matches) { + int amount = getAttribute(attribute.getKey()); + if (amount > 0) { + modified = attribute.modifyStat(stat, modified, amount); + } + } + return modified; + } + + /** + * Scales a dynamic skill's value using global modifiers + * + * @param component component holding the value + * @param key key of the value + * @param value unmodified value + * + * @return the modified value + */ + public double scaleDynamic(EffectComponent component, String key, double base) { + final AttributeManager manager = SkillAPI.getAttributeManager(); + if (manager == null) { + return 0; + } + + final List matches = manager.forComponent(component, key); + if (matches == null) { + return 0; + } + + double value = 0; + for (final AttributeManager.Attribute attribute : matches) { + int amount = getAttribute(attribute.getKey()); + if (amount > 0) { + value += attribute.modify(component, key, base, amount); + } + } + return value; + } + + public double getCritBonus(EffectComponent component, double base, double chance) { + final AttributeManager manager = SkillAPI.getAttributeManager(); + if (manager == null) { + return 0; + } + + // Max dex on any skill with crit chance gives (dexcrit)x max str/int + double modifier = SkillAPI.getSettings().getDexCrit() / (chance * 100); + AttributeManager.Attribute attr = manager.getAttribute("dexterity"); + int amount = getAttribute(attr.getKey()); + return base * (modifier * amount); + } + + /** + * Opens the attribute menu for the player + * + * @return true if successfully opened, false if conditions weren't met + */ + public boolean openAttributeMenu() { + Player player = getPlayer(); + if (SkillAPI.getSettings().isAttributesEnabled() && player != null) { + GUITool.getAttributesMenu().show(new AttributeHandler(), this, + SkillAPI.getLanguage() + .getMessage(GUINodes.ATTRIB_TITLE, true, FilterType.COLOR, + RPGFilter.POINTS.setReplacement(attribPoints + ""), + Filter.PLAYER.setReplacement(player.getName())) + .get(0), + SkillAPI.getAttributeManager().getAttributes()); + return true; + } + return false; + } + + /** + * Retrieves the player's attribute data. Modifying this will modify the + * player's actual data. + * + * @return the player's attribute data + */ + public HashMap getAttributeData() { + return attributes; + } + + /////////////////////////////////////////////////////// + // // + // Skills // + // // + /////////////////////////////////////////////////////// + + /** + * Checks if the owner has a skill by name. This is not case-sensitive and does + * not check to see if the skill is unlocked. It only checks if the skill is + * available to upgrade/use. + * + * @param name name of the skill + * + * @return true if has the skill, false otherwise + */ + public boolean hasSkill(String name) { + return name != null && skills.containsKey(name.toLowerCase()); + } + + /** + * Retrieves a skill of the owner by name. This is not case-sensitive. + * + * @param name name of the skill + * + * @return data for the skill or null if the player doesn't have the skill + */ + public PlayerSkill getSkill(String name) { + if (name == null) { + return null; + } + name = name.replace('?', ' ').trim(); + return skills.get(name.toLowerCase()); + } + + public int getInvestedSkillPoints() { + int total = 0; + for (PlayerSkill playerSkill : skills.values()) { + total += playerSkill.getInvestedCost(); + } + return total; + } + + /** + * Retrieves all of the skill data the player has. Modifying this collection + * will not modify the player's owned skills but modifying one of the elements + * will change that element's data for the player. + * + * @return collection of skill data for the owner + */ + public Collection getSkills() { + return skills.values(); + } + + /** + * Retrieves the level of a skill for the owner. This is not case-sensitive. + * + * @param name name of the skill + * + * @return level of the skill or 0 if not found + */ + public int getSkillLevel(String name) { + PlayerSkill skill = getSkill(name); + return skill == null ? 0 : skill.getLevel(); + } + + /** + * Gives the player a skill outside of the normal class skills. This skill will + * not show up in a skill tree. + * + * @param skill skill to give the player + */ + public void giveSkill(Skill skill) { + giveSkill(skill, null); + } + + /** + * Gives the player a skill using the class data as a parent. This skill will + * not show up in a skill tree. + * + * @param skill skill to give the player + * @param parent parent class data + */ + public void giveSkill(Skill skill, PlayerClass parent) { + String key = skill.getKey(); + if (!skills.containsKey(key)) { + PlayerSkill data = new PlayerSkill(this, skill, parent); + combos.addSkill(skill); + skills.put(key, data); + autoLevel(skill); + } + } + + /** + * Attempts to auto-level any skills that are able to do so + */ + public void autoLevel() { + if (init) { + return; + } + + final Player player = getPlayer(); + if (player == null) { + return; + } + + for (PlayerSkill skill : skills.values()) { + if (skill.getData().isAllowed(player)) { + autoLevel(skill.getData()); + } + } + } + + private void autoLevel(Skill skill) { + PlayerSkill data = skills.get(skill.getKey()); + if (data == null || getPlayer() == null || !skill.isAllowed(getPlayer())) { + return; + } + + int lastLevel = data.getLevel(); + while (data.getData().canAutoLevel(lastLevel) && !data.isMaxed() + && data.getLevelReq() <= data.getPlayerClass().getLevel()) { + upgradeSkill(skill, false); + if (lastLevel == data.getLevel()) { + break; + } + lastLevel++; + } + } + + /** + * Upgrades a skill owned by the player. The player must own the skill, have + * enough skill points, meet the level and skill requirements, and not have + * maxed out the skill already in order to upgrade the skill. This will consume + * the skill point cost while upgrading the skill. + * + * @param skill skill to upgrade + * + * @return true if successfully was upgraded, false otherwise + */ + public boolean upgradeSkill(Skill skill, boolean runEvent) { + // Cannot be null + if (skill == null) { + return false; + } + + // Must be a valid available skill + PlayerSkill data = skills.get(skill.getName().toLowerCase()); + if (data == null) { + return false; + } + + // Must meet any skill requirements + if (!skill.isCompatible(this) || !skill.hasInvestedEnough(this) || !skill.hasDependency(this)) { + return false; + } + + int level = data.getPlayerClass().getLevel(); + int points = data.getPlayerClass().getPoints(); + int cost = data.getCost(); + if (!data.isMaxed() && level >= data.getLevelReq() && points >= cost) { + // Upgrade event + PlayerSkillUpgradeEvent event = new PlayerSkillUpgradeEvent(this, data, cost); + if (runEvent) { + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + } + + // Apply upgrade + data.getPlayerClass().usePoints(cost); + forceUpSkill(data); + + return true; + } + else { + return false; + } + } + + /** + * Forcefully upgrades a skill, not letting other plugins cancel it and ignoring + * any requirements to do so + * + * @param skill skill to forcefully upgrade + */ + public void forceUpSkill(PlayerSkill skill) { + skill.addLevels(1); + + // Passive calls + if (passive) { + Player player = getPlayer(); + if (player != null && skill.getData() instanceof PassiveSkill) { + if (skill.getLevel() == 1) { + ((PassiveSkill) skill.getData()).initialize(player, skill.getLevel()); + } + else { + ((PassiveSkill) skill.getData()).update(player, skill.getLevel() - 1, skill.getLevel()); + } + } + + // Unlock event + if (skill.getLevel() == 1) { + Bukkit.getPluginManager().callEvent(new PlayerSkillUnlockEvent(this, skill)); + this.autoLevel(); + } + } + } + + /** + * Downgrades a skill owned by the player. The player must own the skill and it + * must not currently be level 0 for the player to downgrade the skill. This + * will refund the skill point cost when downgrading the skill. + * + * @param skill skill to downgrade + * + * @return true if successfully downgraded, false otherwise + */ + public boolean downgradeSkill(Skill skill) { + // Cannot be null + if (skill == null) { + return false; + } + + // Must be a valid available skill + PlayerSkill data = skills.get(skill.getName().toLowerCase()); + if (data == null) { + return false; + } + + // Must not be a free skill + if (data.getCost() == 0) { + return false; + } + + // Must not be required by another skill + for (PlayerSkill s : skills.values()) { + if (s.getData().getSkillReq() != null && s.getData().getSkillReq().equalsIgnoreCase(skill.getName()) + && data.getLevel() <= s.getData().getSkillReqLevel() && s.getLevel() > 0) { + return false; + } + } + + int cost = skill.getCost(data.getLevel() - 1); + if (cost <= 0) { + return false; + } + + if (data.getLevel() > 0) { + // Upgrade event + PlayerSkillDowngradeEvent event = new PlayerSkillDowngradeEvent(this, data, cost); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + + // Apply upgrade + data.getPlayerClass().givePoints(cost, PointSource.REFUND); + forceDownSkill(data); + + return true; + } + else { + return false; + } + } + + /** + * Forcefully downgrades a skill, not letting other plugins stop it and ignoring + * any skill requirements to do so. + * + * @param skill skill to forcefully downgrade + */ + public void forceDownSkill(PlayerSkill skill) { + skill.addLevels(-1); + + // Passive calls + Player player = getPlayer(); + if (player != null && skill.getData() instanceof PassiveSkill) { + if (skill.getLevel() == 0) { + ((PassiveSkill) skill.getData()).stopEffects(player, 1); + } + else { + ((PassiveSkill) skill.getData()).update(player, skill.getLevel() + 1, skill.getLevel()); + } + } + + // Clear bindings + if (skill.getLevel() == 0) { + clearBinds(skill.getData()); + } + } + + /** + * Refunds a skill for the player, resetting it down to level 0 and giving back + * any invested skill points. + * + * @param skill skill to refund + */ + public void refundSkill(PlayerSkill skill) { + Player player = getPlayer(); + + if (skill.getCost() == 0 || skill.getLevel() == 0) { + return; + } + + skill.getPlayerClass().givePoints(skill.getInvestedCost(), PointSource.REFUND); + skill.setLevel(0); + + if (player != null && (skill.getData() instanceof PassiveSkill)) { + ((PassiveSkill) skill.getData()).stopEffects(player, 1); + } + } + + /** + * Refunds all skills for the player + */ + public void refundSkills() { + for (PlayerSkill skill : skills.values()) { + refundSkill(skill); + } + + clearAllBinds(); + } + + /** + * Shows the skill tree for the player. If the player has multiple trees, this + * will show the list of skill trees they can view. + */ + public void showSkills() { + showSkills(getPlayer()); + } + + /** + * Shows the class details for the player + * + * @param player player to show to + * + * @return true if shown, false if nothing to show + */ + public boolean showDetails(Player player) { + if (classes.size() > 0 && player != null) { + HashMap iconMap = new HashMap<>(); + for (Map.Entry entry : classes.entrySet()) { + iconMap.put(entry.getKey().toLowerCase(), entry.getValue().getData()); + } + + GUITool.getDetailsMenu().show(new DetailsHandler(), this, + SkillAPI.getLanguage().getMessage(GUINodes.CLASS_LIST, true, FilterType.COLOR, + Filter.PLAYER.setReplacement(player.getName())).get(0), + iconMap); + return true; + } + else { + return false; + } + } + + /** + * Shows profession options of the first class group available + * + * @param player player to show profession options for + * + * @return true if shown profession options, false if none available + */ + public boolean showProfession(Player player) { + for (String group : SkillAPI.getGroups()) { + PlayerClass c = getClass(group); + if (c == null || (c.getLevel() == c.getData().getMaxLevel() && c.getData().getOptions().size() > 0)) { + GUITool.getProfessMenu(c == null ? null : c.getData()).show(new ProfessHandler(), this, + SkillAPI.getLanguage().getMessage(GUINodes.PROFESS_TITLE, true, FilterType.COLOR, + Filter.PLAYER.setReplacement(player.getName()), RPGFilter.GROUP.setReplacement(group)) + .get(0), + SkillAPI.getClasses()); + return true; + } + } + return false; + } + + /** + * Shows the skill tree for the player. If the player has multiple trees, this + * will show the list of skill trees they can view. + * + * @param player player to show the skill tree for + * + * @return true if able to show the player, false otherwise + */ + public boolean showSkills(Player player) { + // Cannot show an invalid player, and cannot show no skills + if (player == null || classes.size() == 0 || skills.size() == 0) { + return false; + } + + // Show list of classes that have skill trees + if (classes.size() > 1) { + return showDetails(player); + } + + // Show only class's skill tree otherwise + else { + return showSkills(player, classes.values().iterator().next()); + } + } + + /** + * Shows the skill tree to the player for the given class + * + * @param player player to show + * @param playerClass class to look for + * + * @return true if succeeded, false otherwise + */ + public boolean showSkills(Player player, PlayerClass playerClass) { + // Cannot show an invalid player, and cannot show no skills + if (player == null || playerClass.getData().getSkills().size() == 0) { + return false; + } + + // Show skill tree of the class + this.menuClass = playerClass.getData().getName(); + GUITool.getSkillTree(playerClass.getData()).show(new SkillHandler(), this, + SkillAPI.getLanguage() + .getMessage(GUINodes.SKILL_TREE, true, FilterType.COLOR, + RPGFilter.POINTS.setReplacement(playerClass.getPoints() + ""), + RPGFilter.LEVEL.setReplacement(playerClass.getLevel() + ""), + RPGFilter.CLASS.setReplacement(playerClass.getData().getName()), + Filter.PLAYER.setReplacement(getPlayerName())) + .get(0), + playerClass.getData().getSkillMap()); + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] /skills 5"); + } + return true; + } + + /** + * Retrieves the name of the class shown in the skill tree + * + * @return class name + */ + public String getShownClassName() { + return menuClass; + } + + /////////////////////////////////////////////////////// + // // + // Classes // + // // + /////////////////////////////////////////////////////// + + /** + * Checks whether or not the player has as least one class they have professed + * as. + * + * @return true if professed, false otherwise + */ + public boolean hasClass() { + return classes.size() > 0; + } + + /** + * Checks whether or not a player has a class within the given group + * + * @param group class group to check + * + * @return true if has a class in the group, false otherwise + */ + public boolean hasClass(String group) { + return classes.containsKey(group); + } + + /** + * Retrieves the collection of the data for classes the player has professed as. + * + * @return collection of the data for professed classes + */ + public Collection getClasses() { + return classes.values(); + } + + /** + * Retrieves the data of a class the player professed as by group. This is + * case-sensitive. + * + * @param group group to get the profession for + * + * @return professed class data or null if not professed for the group + */ + public PlayerClass getClass(String group) { + return classes.get(group); + } + + /** + * Retrieves the data of the professed class under the main class group. The + * "main" group is determined by the setting in the config. + * + * @return main professed class data or null if not professed for the main group + */ + public PlayerClass getMainClass() { + String main = SkillAPI.getSettings().getMainGroup(); + if (classes.containsKey(main)) { + return classes.get(main); + } + else if (classes.size() > 0) { + return classes.values().toArray(new PlayerClass[classes.size()])[0]; + } + else { + return null; + } + } + + /** + * Sets the professed class for the player for the corresponding group. This + * will not save any skills, experience, or levels of the previous class if + * there was any. The new class will start at level 1 with 0 experience. + * + * @param rpgClass class to assign to the player + * + * @return the player-specific data for the new class + */ + public PlayerClass setClass(RPGClass rpgClass) { + PlayerClass c = classes.remove(rpgClass.getGroup()); + if (c != null) { + for (Skill skill : c.getData().getSkills()) { + skills.remove(skill.getName().toLowerCase()); + combos.removeSkill(skill); + } + } + else { + attribPoints += rpgClass.getGroupSettings().getStartingAttribs(); + } + + PlayerClass classData = new PlayerClass(this, rpgClass); + classes.put(rpgClass.getGroup(), classData); + + // Add in missing skills + for (Skill skill : rpgClass.getSkills()) { + giveSkill(skill, classData); + } + + // Load global skills + for (String skillKey : SkillAPI.getSettings().getGlobalSkills()) { + giveSkill(SkillAPI.getSkill(skillKey), classData); + } + + updateHealthAndMana(getPlayer()); + updateScoreboard(); + return classes.get(rpgClass.getGroup()); + } + + /** + * Checks whether or not the player is professed as the class without checking + * child classes. + * + * @param rpgClass class to check + * + * @return true if professed as the specific class, false otherwise + */ + public boolean isExactClass(RPGClass rpgClass) { + if (rpgClass == null) { + return false; + } + PlayerClass c = classes.get(rpgClass.getGroup()); + return (c != null) && (c.getData() == rpgClass); + } + + /** + * Checks whether or not the player is professed as the class or any of its + * children. + * + * @param rpgClass class to check + * + * @return true if professed as the class or one of its children, false + * otherwise + */ + public boolean isClass(RPGClass rpgClass) { + if (rpgClass == null) { + return false; + } + + PlayerClass pc = classes.get(rpgClass.getGroup()); + if (pc == null) { + return false; + } + + RPGClass temp = pc.getData(); + while (temp != null) { + if (temp == rpgClass) { + return true; + } + temp = temp.getParent(); + } + + return false; + } + + /** + * Checks whether or not the player can profess into the given class. This + * checks to make sure the player is currently professed as the parent of the + * given class and is high enough of a level to do so. + * + * @param rpgClass class to check + * + * @return true if can profess, false otherwise + */ + public boolean canProfess(RPGClass rpgClass) { + Player p = getPlayer(); + if (p == null || !rpgClass.isAllowed(p)) { + return false; + } + + if (classes.containsKey(rpgClass.getGroup())) { + PlayerClass current = classes.get(rpgClass.getGroup()); + return rpgClass.getParent() == current.getData() && current.getData().getMaxLevel() <= current.getLevel(); + } + else { + return !rpgClass.hasParent(); + } + } + + /** + * Resets the class data for the owner under the given group. This will remove + * the profession entirely, leaving no remaining data until the player professes + * again to a starting class. + * + * @param group group to reset + */ + public void reset(String group) { + GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); + if (!settings.canReset()) { + return; + } + + PlayerClass playerClass = classes.remove(group); + if (playerClass != null) { + // Remove skills + RPGClass data = playerClass.getData(); + for (Skill skill : data.getSkills()) { + PlayerSkill ps = skills.remove(skill.getName().toLowerCase()); + if (ps != null && ps.isUnlocked() && ps.getData() instanceof PassiveSkill) { + ((PassiveSkill) ps.getData()).stopEffects(getPlayer(), ps.getLevel()); + } + combos.removeSkill(skill); + } + + // Update GUI features + updateScoreboard(); + + // Call the event + Bukkit.getPluginManager().callEvent(new PlayerClassChangeEvent(playerClass, data, null)); + } + + // Restore default class if applicable + RPGClass rpgClass = settings.getDefault(); + if (rpgClass != null && settings.getPermission() == null) { + setClass(rpgClass); + } + binds.clear(); + resetAttribs(); + } + + /** + * Resets all profession data for the player. This clears all professions the + * player has, leaving no remaining data until the player professes again to a + * starting class. + */ + public void resetAll() { + ArrayList keys = new ArrayList<>(classes.keySet()); + for (String key : keys) { + reset(key); + } + } + + /** + * Resets attributes for the player + */ + public void resetAttribs() { + attributes.clear(); + attribPoints = 0; + for (PlayerClass c : classes.values()) { + GroupSettings s = c.getData().getGroupSettings(); + attribPoints += s.getStartingAttribs() + s.getAttribsForLevels(c.getLevel(), 1); + } + AttributeListener.updatePlayer(this); + updateHealthAndMana(getPlayer()); + } + + /** + * Professes the player into the class if they are able to. This will reset the + * class data if the group options are set to reset upon profession. Otherwise, + * all skills, experience, and levels of the current class under the group will + * be retained and carried over into the new profession. + * + * @param rpgClass class to profess into + * + * @return true if successfully professed, false otherwise + */ + public boolean profess(RPGClass rpgClass) { + if (rpgClass != null && canProfess(rpgClass)) { + final PlayerClass previousData = classes.get(rpgClass.getGroup()); + final RPGClass previous = previousData == null ? null : previousData.getData(); + + // Pre-class change event in case someone wants to stop it + final PlayerPreClassChangeEvent event = new PlayerPreClassChangeEvent(this, previousData, previous, + rpgClass); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + + // Reset data if applicable + final boolean isResetting = SkillAPI.getSettings().getGroupSettings(rpgClass.getGroup()).isProfessReset(); + if (isResetting) { + reset(rpgClass.getGroup()); + } + + // Inherit previous class data if any + final PlayerClass current; + if (previousData == null || isResetting) { + current = new PlayerClass(this, rpgClass); + classes.put(rpgClass.getGroup(), current); + attribPoints += rpgClass.getGroupSettings().getStartingAttribs(); + } + else { + current = previousData; + previousData.setClassData(rpgClass); + } + + // Add skills + for (Skill skill : rpgClass.getSkills()) { + if (!skills.containsKey(skill.getKey())) { + skills.put(skill.getKey(), new PlayerSkill(this, skill, current)); + combos.addSkill(skill); + } + } + + Bukkit.getPluginManager().callEvent(new PlayerClassChangeEvent(current, previous, current.getData())); + AttributeListener.updatePlayer(this); + resetAttribs(); + updateScoreboard(); + return true; + } + else { + return false; + } + } + + /** + * Gives experience to the player from the given source + * + * @param amount amount of experience to give + * @param source source of the experience + */ + public void giveExp(double amount, ExpSource source) { + giveExp(amount, source, true); + } + + /** + * Gives experience to the player from the given source + * + * @param amount amount of experience to give + * @param source source of the experience + * @param message whether or not to show the configured message if enabled + */ + public void giveExp(double amount, ExpSource source, boolean message) { + for (PlayerClass playerClass : classes.values()) { + playerClass.giveExp(amount, source, message); + } + } + + /** + * Causes the player to lose experience as a penalty (generally for dying) + */ + public void loseExp() { + for (PlayerClass playerClass : classes.values()) { + double penalty = playerClass.getData().getGroupSettings().getDeathPenalty(); + if (penalty > 0) { + playerClass.loseExp(penalty); + } + } + } + + /** + * Gives levels to the player for all classes matching the experience source + * + * @param amount amount of levels to give + * @param source source of the levels + */ + public boolean giveLevels(int amount, ExpSource source) { + boolean success = false; + for (PlayerClass playerClass : classes.values()) { + RPGClass data = playerClass.getData(); + if (data.receivesExp(source)) { + success = true; + playerClass.giveLevels(amount); + } + } + updateHealthAndMana(getPlayer()); + return success; + } + + /** + * Gives skill points to the player for all classes matching the experience + * source + * + * @param amount amount of levels to give + * @param source source of the levels + */ + public void givePoints(int amount, ExpSource source) { + for (PlayerClass playerClass : classes.values()) { + if (playerClass.getData().receivesExp(source)) { + playerClass.givePoints(amount); + } + } + } + + /////////////////////////////////////////////////////// + // // + // Health and Mana // + // // + /////////////////////////////////////////////////////// + + /** + * Updates the player's max health and mana using class data. + * + * @param player player to update the health and mana for + */ + public void updateHealthAndMana(Player player) { + if (player == null || !SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { + return; + } + + // Update maxes + double health = bonusHealth; + maxMana = bonusMana; + for (PlayerClass c : classes.values()) { + health += c.getHealth(); + maxMana += c.getMana(); + } + if (health == bonusHealth) { + health += SkillAPI.getSettings().getDefaultHealth(); + } + if (health <= 0) { + health = SkillAPI.getSettings().getDefaultHealth(); + } + if (SkillAPI.getSettings().isModifyHealth()) { + player.setMaxHealth(health); + } + mana = Math.min(mana, maxMana); + + // Health scaling is available starting with 1.6.2 + if (SkillAPI.getSettings().isOldHealth()) { + player.setHealthScaled(true); + player.setHealthScale(20); + } + else { + player.setHealthScaled(false); + } + } + + /** + * Gives max health to the player. This does not carry over to other accounts + * and will reset when SkillAPI is disabled. This does however carry over + * through death and professions. This will accept negative values. + * + * @param amount amount of bonus health to give + */ + public void addMaxHealth(double amount) { + bonusHealth += amount; + bonusHealth = bonusHealth >= 0 ? bonusHealth : 0; + final Player player = getPlayer(); + if (player != null) { + if (VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { + final AttributeInstance attribute = player.getAttribute(Attribute.GENERIC_MAX_HEALTH); + attribute.setBaseValue(attribute.getBaseValue() + amount); + } + else { + final double newHealth = player.getMaxHealth() + amount; + player.setMaxHealth(newHealth); + if (player.getMaxHealth() > newHealth) { + player.setMaxHealth(newHealth * 2 - player.getMaxHealth()); + } + } + } + } + + /** + * Gives max mana to the player. This does not carry over to other accounts and + * will reset when SkillAPI is disabled. This does however carry over through + * death and professions. This will accept negative values. + * + * @param amount amount of bonus mana to give + */ + public void addMaxMana(double amount) { + bonusMana += amount; + maxMana += amount; + mana += amount; + } + + /** + * Retrieves the amount of mana the player currently has. + * + * @return current player mana + */ + public double getMana() { + return mana; + } + + /** + * Checks whether or not the player has at least the specified amount of mana + * + * @param amount required mana amount + * + * @return true if has the amount of mana, false otherwise + */ + public boolean hasMana(double amount) { + return mana >= amount; + } + + /** + * Retrieves the max amount of mana the player can have including bonus mana + * + * @return max amount of mana the player can have + */ + public double getMaxMana() { + return maxMana; + } + + /** + * Regenerates mana for the player based on the regen amounts of professed + * classes + */ + public void regenMana() { + double amount = 0; + for (PlayerClass c : classes.values()) { + if (c.getData().hasManaRegen()) { + amount += c.getData().getManaRegen(); + } + } + if (amount > 0) { + giveMana(amount, ManaSource.REGEN); + } + } + + // Only bring Player as param because playerdata only has offlineplayer + public void regenHealth(Player p) { + if (!p.isDead() && p.getHealth() != p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()) { + double regen = Math.max(0, (SkillAPI.getPlayerData(p).scaleStat(AttributeManager.HEALTH_REGEN, 0))); + + if (regen > 0) { + PlayerRegenEvent event = new PlayerRegenEvent(p, regen); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + regen = event.getAmount(); + double health = p.getHealth(); + p.setHealth(Math.min(p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(), health + regen)); + } + } + } + } + + /** + * Sets the player's amount of mana without launching events + * + * @param amount current mana + */ + public void setMana(double amount) { + this.mana = amount; + } + + /** + * Gives mana to the player from an unknown source. This will not cause the + * player's mana to go above their max amount. + * + * @param amount amount of mana to give + */ + public void giveMana(double amount) { + giveMana(amount, ManaSource.SPECIAL); + } + + /** + * Gives mana to the player from the given mana source. This will not cause the + * player's mana to go above the max amount. + * + * @param amount amount of mana to give + * @param source source of the mana + */ + public void giveMana(double amount, ManaSource source) { + if (mana == maxMana) { + return; + } + PlayerManaGainEvent event = new PlayerManaGainEvent(this, amount, source); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + Logger.log(LogType.MANA, 2, + getPlayerName() + " gained " + event.getAmount() + " mana due to " + event.getSource().name()); + + mana += event.getAmount(); + if (mana > maxMana) { + mana = maxMana; + } + if (mana < 0) { + mana = 0; + } + } + else { + Logger.log(LogType.MANA, 2, getPlayerName() + " had their mana gain cancelled"); + } + } + + /** + * Takes mana away from the player for an unknown reason. This will not cause + * the player to fall below 0 mana. + * + * @param amount amount of mana to take away + */ + public void useMana(double amount) { + useMana(amount, ManaCost.SPECIAL); + } + + /** + * Takes mana away from the player for the specified reason. This will not cause + * the player to fall below 0 mana. + * + * @param amount amount of mana to take away + * @param cost source of the mana cost + */ + public void useMana(double amount, ManaCost cost) { + PlayerManaLossEvent event = new PlayerManaLossEvent(this, amount, cost); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + Logger.log(LogType.MANA, 2, + getPlayerName() + " used " + event.getAmount() + " mana due to " + event.getSource().name()); + + mana -= event.getAmount(); + if (mana < 0) { + mana = 0; + } + } + } + + /** + * Clears bonus health/mana + */ + public void clearBonuses() { + Player p = Bukkit.getPlayer(player.getName()); + Bukkit.getPluginManager().callEvent(new PlayerAttributeUnloadEvent(p)); + bonusMana = 0; + bonusHealth = 0; + bonusAttrib.clear(); + equips = new PlayerEquips(this); + } + + /////////////////////////////////////////////////////// + // // + // Skill Binding // + // // + /////////////////////////////////////////////////////// + + /** + * Retrieves a skill the player has bound by material + * + * @param mat material to get the bind for + * + * @return skill bound to the material or null if none are bound + */ + public PlayerSkill getBoundSkill(Material mat) { + return binds.get(mat); + } + + /** + * Retrieves the bound data for the player. Modifying this map will modify the + * bindings the player has. + * + * @return the skill binds data for the player + */ + public HashMap getBinds() { + return binds; + } + + /** + * Checks whether or not the material has a skill bound to it + * + * @param mat material to check + * + * @return true if a skill is bound to it, false otherwise + */ + public boolean isBound(Material mat) { + return binds.containsKey(mat); + } + + /** + * Binds a skill to a material for the player. The bind will not work if the + * skill was already bound to the material. + * + * @param mat material to bind the skill to + * @param skill skill to bind to the material + * + * @return true if was able to bind the skill, false otherwise + */ + public boolean bind(Material mat, PlayerSkill skill) { + // Special cases + if (mat == null || (skill != null && skill.getPlayerData() != this)) { + return false; + } + + PlayerSkill bound = getBoundSkill(mat); + if (bound != skill) { + // Apply the binding + if (skill == null) { + binds.remove(mat); + } + else { + binds.put(mat, skill); + } + + // Update the old skill's bind + if (bound != null) { + bound.setBind(null); + } + + // Update the new skill's bind + if (skill != null) { + skill.setBind(mat); + } + + return true; + } + + // The skill was already bound + else { + return false; + } + } + + /** + * Clears a skill binding on the material. If there is no binding on the + * material, this will do nothing. + * + * @param mat material to clear bindings from + * + * @return true if a binding was cleared, false otherwise + */ + public boolean clearBind(Material mat) { + return binds.remove(mat) != null; + } + + /** + * Clears the skill binding for the given skill. This will remove the bindings + * on all materials involving the skill. + * + * @param skill skill to unbind + */ + public void clearBinds(Skill skill) { + ArrayList keys = new ArrayList<>(binds.keySet()); + for (Material key : keys) { + PlayerSkill bound = binds.get(key); + if (bound.getData() == skill) { + binds.remove(key); + } + } + } + + /** + * Clears all binds the player currently has + */ + public void clearAllBinds() { + binds.clear(); + } + + /////////////////////////////////////////////////////// + // // + // Functions // + // // + /////////////////////////////////////////////////////// + + /** + * Records any data to save with class data + * + * @param player player to record for + */ + public void record(Player player) { + this.lastHealth = player.getHealth(); + } + + /** + * Updates the scoreboard with the player's current class. This is already done + * by the API and doesn't need to be done by other plugins. + */ + public void updateScoreboard() { + if (SkillAPI.getSettings().isShowScoreboard()) { + SkillAPI.schedule(new ScoreboardTask(this), 2); + } + } + + /** + * Starts passive abilities for the player if they are online. This is already + * called by the API and shouldn't be called by other plugins. + * + * @param player player to set the passive skills up for + */ + public void startPassives(Player player) { + if (player == null) { + return; + } + passive = true; + for (PlayerSkill skill : skills.values()) { + if (skill.isUnlocked() && (skill.getData() instanceof PassiveSkill)) { + ((PassiveSkill) skill.getData()).initialize(player, skill.getLevel()); + } + } + } + + /** + * Stops passive abilities for the player if they are online. This is already + * called by the API and shouldn't be called by other plugins. + * + * @param player player to stop the passive skills for + */ + public void stopPassives(Player player) { + if (player == null) { + return; + } + passive = false; + for (PlayerSkill skill : skills.values()) { + if (skill.isUnlocked() && (skill.getData() instanceof PassiveSkill)) { + try { + ((PassiveSkill) skill.getData()).stopEffects(player, skill.getLevel()); + } catch (Exception ex) { + Logger.bug("Failed to stop passive skill " + skill.getData().getName()); + ex.printStackTrace(); + } + } + } + } + + /** + * Casts a skill by name for the player. In order to cast the skill, the player + * must be online, have the skill unlocked, have enough mana, have the skill off + * cooldown, and have a proper target if applicable. + * + * @param skillName name of the skill ot cast + * + * @return true if successfully cast the skill, false otherwise + */ + public boolean cast(String skillName) { + return cast(skills.get(skillName.toLowerCase())); + } + + /** + * Casts a skill for the player. In order to cast the skill, the player must be + * online, have the skill unlocked, have enough mana, have the skill off + * cooldown, and have a proper target if applicable. + * + * @param skill skill to cast + * + * @return true if successfully cast the skill, false otherwise + */ + public boolean cast(PlayerSkill skill) { + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 1"); + } + // Invalid skill + if (skill == null) { + throw new IllegalArgumentException("Skill cannot be null"); + } + + int level = skill.getLevel(); + + // Not unlocked or on cooldown + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 2"); + } + if (!check(skill, true, true)) { + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill check failed " + skill.getData().getName()); + } + return false; + } + + // Dead players can't cast skills + Player p = getPlayer(); + if (p.isDead()) { + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " failed, player is dead"); + } + return PlayerSkillCastFailedEvent.invoke(skill, CASTER_DEAD); + } + + // Disable casting in spectator mode + if (p.getGameMode() == GameMode.SPECTATOR) { + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " failed, player is spectator"); + } + return PlayerSkillCastFailedEvent.invoke(skill, SPECTATOR); + } + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 3"); + } + + // Skill Shots + if (skill.getData() instanceof SkillShot) { + PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); + Bukkit.getPluginManager().callEvent(event); + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " (skillshot) 4"); + } + + // Make sure it isn't cancelled + if (!event.isCancelled()) { + try { + if (((SkillShot) skill.getData()).cast(p, level)) { + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " (skillshot) 5"); + } + PlayerSkillCastSuccessEvent success = new PlayerSkillCastSuccessEvent(this, skill, p); + Bukkit.getPluginManager().callEvent(success); + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " (skillshot) 6"); + } + return applyUse(p, skill, event.getManaCost()); + } else { + return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); + } + } catch (Exception ex) { + Logger.bug("Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); + ex.printStackTrace(); + return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); + } + } else { return PlayerSkillCastFailedEvent.invoke(skill, CANCELED); } + } + + // Target Skills + else if (skill.getData() instanceof TargetSkill) { + LivingEntity target = TargetHelper.getLivingTarget(p, skill.getData().getRange(level)); + + // Must have a target + if (target == null) { + return PlayerSkillCastFailedEvent.invoke(skill, NO_TARGET); + } + + PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); + Bukkit.getPluginManager().callEvent(event); + + // Make sure it isn't cancelled + if (!event.isCancelled()) { + try { + final boolean canAttack = !SkillAPI.getSettings().canAttack(p, target); + if (((TargetSkill) skill.getData()).cast(p, target, level, canAttack)) { + PlayerSkillCastSuccessEvent success = new PlayerSkillCastSuccessEvent(this, skill, p); + Bukkit.getPluginManager().callEvent(success); + return applyUse(p, skill, event.getManaCost()); + } + else { + return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); + } + } catch (Exception ex) { + Logger.bug("Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); + ex.printStackTrace(); + return PlayerSkillCastFailedEvent.invoke(skill, EFFECT_FAILED); + } + } + else { + PlayerSkillCastFailedEvent.invoke(skill, CANCELED); + } + } + + return false; + } + + private boolean applyUse(final Player player, final PlayerSkill skill, final double manaCost) { + skill.startCooldown(); + if (SkillAPI.getSettings().isShowSkillMessages()) { + skill.getData().sendMessage(player, SkillAPI.getSettings().getMessageRadius()); + } + if (SkillAPI.getSettings().isManaEnabled()) { + useMana(manaCost, ManaCost.SKILL_CAST); + } + skillTimer = System.currentTimeMillis() + SkillAPI.getSettings().getCastCooldown(); + return true; + } + + /** + * Checks the cooldown and mana requirements for a skill + * + * @param skill skill to check for + * @param cooldown whether or not to check cooldowns + * @param mana whether or not to check mana requirements + * + * @return true if can use + */ + public boolean check(PlayerSkill skill, boolean cooldown, boolean mana) { + if (SkillAPI.debug)Bukkit.getLogger().info("[SkillAPI Debug] Check skill 0 " + skill.getData().getName()); + if (skill == null || System.currentTimeMillis() < skillTimer) { + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 2 1"); + return false; + } + + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Check skill 1 " + skill.getData().getName()); + SkillStatus status = skill.getStatus(); + int level = skill.getLevel(); + double cost = skill.getData().getManaCost(level); + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Check skill 2 " + skill.getData().getName()); + + // Not unlocked + if (level <= 0) { + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 2 2"); + return PlayerSkillCastFailedEvent.invoke(skill, NOT_UNLOCKED); + } + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Check skill 3 " + skill.getData().getName()); + + // On Cooldown + if (status == SkillStatus.ON_COOLDOWN && cooldown) { + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 2 3"); + SkillAPI.getLanguage().sendMessage(ErrorNodes.COOLDOWN, getPlayer(), FilterType.COLOR, + RPGFilter.COOLDOWN.setReplacement(skill.getCooldown() + ""), + RPGFilter.SKILL.setReplacement(skill.getData().getName())); + return PlayerSkillCastFailedEvent.invoke(skill, ON_COOLDOWN); + } + + // Not enough mana + else if (status == SkillStatus.MISSING_MANA && mana) { + SkillAPI.getLanguage().sendMessage(ErrorNodes.MANA, getPlayer(), FilterType.COLOR, + RPGFilter.SKILL.setReplacement(skill.getData().getName()), + RPGFilter.MANA.setReplacement(getMana() + ""), + RPGFilter.COST.setReplacement((int) Math.ceil(cost) + ""), + RPGFilter.MISSING.setReplacement((int) Math.ceil(cost - getMana()) + ""), + RPGFilter.MANANAME.setReplacement(ChatColor.stripColor(this.getClass("class").getData().getManaName()))); + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Cast skill " + skill.getData().getName() + " 2 4"); + return PlayerSkillCastFailedEvent.invoke(skill, NO_MANA); + } + else { + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Check skill success " + skill.getData().getName()); + return true; + } + } + + /** + * Initializes the application of the data for the player + * + * @param player player to set up for + */ + public void init(Player player) { + if (!SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { + return; + } + + AttributeListener.updatePlayer(this); + getEquips().update(player); + this.updateHealthAndMana(player); + this.startPassives(player); + this.updateScoreboard(); + if (this.getLastHealth() > 0 && !player.isDead()) { + player.setHealth(Math.min(this.getLastHealth(), player.getMaxHealth())); + } + } +} diff --git a/src/com/sucy/skill/api/player/PlayerSkill.java b/src/main/java/com/sucy/skill/api/player/PlayerSkill.java similarity index 100% rename from src/com/sucy/skill/api/player/PlayerSkill.java rename to src/main/java/com/sucy/skill/api/player/PlayerSkill.java diff --git a/src/com/sucy/skill/api/player/PlayerSkillBar.java b/src/main/java/com/sucy/skill/api/player/PlayerSkillBar.java similarity index 98% rename from src/com/sucy/skill/api/player/PlayerSkillBar.java rename to src/main/java/com/sucy/skill/api/player/PlayerSkillBar.java index 06dd3399..6a1a5607 100644 --- a/src/com/sucy/skill/api/player/PlayerSkillBar.java +++ b/src/main/java/com/sucy/skill/api/player/PlayerSkillBar.java @@ -159,9 +159,10 @@ public int countOpenSlots() return -1; ItemStack[] items = p.getInventory().getContents(); - for (int i = 0; i < items.length; i++) - if ((items[i] == null || items[i].getType() == Material.AIR) && !slots.containsKey(i + 1) && !reserved.contains(i)) + for (int i = 0; i < 36; i++) + if ((items[i] == null || items[i].getType() == Material.AIR) && !slots.containsKey(i + 1) && !reserved.contains(i)) { count++; + } return count; } @@ -182,6 +183,10 @@ public void toggleEnabled() setup(player.getPlayer()); } } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } /** * Toggles a slot between weapon and skill diff --git a/src/com/sucy/skill/api/player/PlayerSkillSlot.java b/src/main/java/com/sucy/skill/api/player/PlayerSkillSlot.java similarity index 100% rename from src/com/sucy/skill/api/player/PlayerSkillSlot.java rename to src/main/java/com/sucy/skill/api/player/PlayerSkillSlot.java diff --git a/src/com/sucy/skill/api/projectile/CustomProjectile.java b/src/main/java/com/sucy/skill/api/projectile/CustomProjectile.java similarity index 90% rename from src/com/sucy/skill/api/projectile/CustomProjectile.java rename to src/main/java/com/sucy/skill/api/projectile/CustomProjectile.java index 27faca45..ecf77a42 100644 --- a/src/com/sucy/skill/api/projectile/CustomProjectile.java +++ b/src/main/java/com/sucy/skill/api/projectile/CustomProjectile.java @@ -74,16 +74,21 @@ private static boolean isLivingEntity(Object thing) { static { try { - Class aabbClass = Reflection.getNMSClass("AxisAlignedBB"); - Class entityClass = Reflection.getNMSClass("Entity"); + Class aabbClass = Reflection.getClass("net.minecraft.world.phys.AxisAlignedBB"); + Class entityClass = Reflection.getClass("net.minecraft.world.entity.Entity"); aabbConstructor = aabbClass.getConstructor(double.class, double.class, double.class, double.class, double.class, double.class); getBukkitEntity = entityClass.getDeclaredMethod("getBukkitEntity"); getHandle = Reflection.getCraftClass("CraftWorld").getDeclaredMethod("getHandle"); - Class worldClass = Reflection.getNMSClass("World"); + Class worldClass = Reflection.getClass("net.minecraft.world.level.World"); try { getEntities = worldClass.getDeclaredMethod("getEntities", entityClass, aabbClass, Predicate.class); } catch (Exception e) { - getEntitiesGuava = worldClass.getDeclaredMethod("getEntities", entityClass, aabbClass, com.google.common.base.Predicate.class); + try { + getEntitiesGuava = worldClass.getDeclaredMethod("getEntities", entityClass, aabbClass, com.google.common.base.Predicate.class); + } + catch (Exception exc) { + + } } } catch (Exception ex) { Logger.log("Unable to use reflection for accurate collision - will resort to simple radius check"); @@ -213,25 +218,26 @@ protected void checkCollision(final boolean pierce) { private List getColliding() { // Reflection for nms collision List result = new ArrayList(1); - try { - Object nmsWorld = getHandle.invoke(getLocation().getWorld()); - Object predicate = getEntities == null ? GUAVA_PREDICATE : JAVA_PREDICATE; - Object list = (getEntities == null ? getEntitiesGuava : getEntities) - .invoke(nmsWorld, null, getBoundingBox(), predicate); - for (Object item : (List) list) { - result.add((LivingEntity) getBukkitEntity.invoke(item)); - } - } + //try { + // Object nmsWorld = getHandle.invoke(getLocation().getWorld()); + // Object predicate = getEntities == null ? GUAVA_PREDICATE : JAVA_PREDICATE; + // Object list = (getEntities == null ? getEntitiesGuava : getEntities) + // .invoke(nmsWorld, null, getBoundingBox(), predicate); + // for (Object item : (List) list) { + // result.add((LivingEntity) getBukkitEntity.invoke(item)); + // } + //} + // Fallback when reflection fails + //catch (Exception ex) { // Fallback when reflection fails - catch (Exception ex) { - double radiusSq = getCollisionRadius(); - radiusSq *= radiusSq; - for (LivingEntity entity : getNearbyEntities()) { - if (entity == thrower) - continue; - - if (getLocation().distanceSquared(entity.getLocation()) < radiusSq) - result.add(entity); + double radiusSq = getCollisionRadius(); + radiusSq *= radiusSq; + for (LivingEntity entity : getNearbyEntities()) { + if (entity == thrower) { + continue; + } + if (getLocation().distanceSquared(entity.getLocation()) < radiusSq) { + result.add(entity); } } return result; @@ -261,10 +267,12 @@ private List getNearbyEntities() { int minZ = (int) (loc.getZ() - radius) >> 4; int maxZ = (int) (loc.getZ() + radius) >> 4; for (int i = minX; i <= maxX; i++) - for (int j = minZ; j < maxZ; j++) - for (Entity entity : loc.getWorld().getChunkAt(i, j).getEntities()) + for (int j = minZ; j <= maxZ; j++) { + for (Entity entity : loc.getWorld().getChunkAt(i, j).getEntities()) { if (entity instanceof LivingEntity) list.add((LivingEntity) entity); + } + } return list; } diff --git a/src/com/sucy/skill/api/projectile/HomingProjectile.java b/src/main/java/com/sucy/skill/api/projectile/HomingProjectile.java similarity index 100% rename from src/com/sucy/skill/api/projectile/HomingProjectile.java rename to src/main/java/com/sucy/skill/api/projectile/HomingProjectile.java diff --git a/src/com/sucy/skill/api/projectile/ItemProjectile.java b/src/main/java/com/sucy/skill/api/projectile/ItemProjectile.java similarity index 99% rename from src/com/sucy/skill/api/projectile/ItemProjectile.java rename to src/main/java/com/sucy/skill/api/projectile/ItemProjectile.java index 372d6716..4efd0c23 100644 --- a/src/com/sucy/skill/api/projectile/ItemProjectile.java +++ b/src/main/java/com/sucy/skill/api/projectile/ItemProjectile.java @@ -134,7 +134,7 @@ protected boolean landed() @Override protected double getCollisionRadius() { - return item.getVelocity().length() / 2; + return item.getVelocity().length(); } @Override diff --git a/src/com/sucy/skill/api/projectile/ParticleProjectile.java b/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java similarity index 97% rename from src/com/sucy/skill/api/projectile/ParticleProjectile.java rename to src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java index d1e6eeef..aeff053f 100644 --- a/src/com/sucy/skill/api/projectile/ParticleProjectile.java +++ b/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java @@ -214,7 +214,7 @@ public void run() if (count >= freq) { count = 0; - ParticleHelper.play(loc, settings); + ParticleHelper.play(getShooter(), loc, settings); } // Lifespan @@ -243,7 +243,7 @@ public void run() public static ArrayList spread(LivingEntity shooter, int level, Vector center, Location loc, Settings settings, double angle, int amount, ProjectileCallback callback) { ArrayList dirs = calcSpread(center, angle, amount); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); for (Vector dir : dirs) { Location l = loc.clone(); @@ -273,7 +273,7 @@ public static ArrayList rain(LivingEntity shooter, int level { Vector vel = new Vector(0, 1, 0); ArrayList locs = calcRain(center, radius, height, amount); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); for (Location l : locs) { l.setDirection(vel); diff --git a/src/com/sucy/skill/api/projectile/ProjectileCallback.java b/src/main/java/com/sucy/skill/api/projectile/ProjectileCallback.java similarity index 100% rename from src/com/sucy/skill/api/projectile/ProjectileCallback.java rename to src/main/java/com/sucy/skill/api/projectile/ProjectileCallback.java diff --git a/src/com/sucy/skill/api/skills/PassiveSkill.java b/src/main/java/com/sucy/skill/api/skills/PassiveSkill.java similarity index 100% rename from src/com/sucy/skill/api/skills/PassiveSkill.java rename to src/main/java/com/sucy/skill/api/skills/PassiveSkill.java diff --git a/src/com/sucy/skill/api/skills/Skill.java b/src/main/java/com/sucy/skill/api/skills/Skill.java similarity index 99% rename from src/com/sucy/skill/api/skills/Skill.java rename to src/main/java/com/sucy/skill/api/skills/Skill.java index 7a93e82b..8fe5d20a 100644 --- a/src/com/sucy/skill/api/skills/Skill.java +++ b/src/main/java/com/sucy/skill/api/skills/Skill.java @@ -86,6 +86,7 @@ public abstract class Skill implements IconHolder private int skillReqLevel; private boolean needsPermission; private int combo; + private double critchance; /** * The settings for the skill which include configurable stats @@ -180,6 +181,7 @@ public Skill(String name, String type, ItemStack indicator, int maxLevel, String this.skillReq = skillReq; this.skillReqLevel = skillReqLevel; this.needsPermission = false; + this.critchance = 0; this.message = SkillAPI.getLanguage().getMessage(NotificationNodes.CAST, true, FilterType.COLOR).get(0); this.iconLore = SkillAPI.getLanguage().getMessage(SkillNodes.LAYOUT, true, FilterType.COLOR); @@ -628,6 +630,7 @@ public ItemStack getIndicator(PlayerSkill skillData, boolean brief) catch (Exception ex) { Logger.invalid("Skill icon filter for the skill \"" + name + "\" is invalid (Line = \"" + line + "\") - " + ex.getMessage()); + ex.printStackTrace(); } } @@ -761,7 +764,7 @@ public void damage(LivingEntity target, double damage, LivingEntity source, Stri if (PluginChecker.isNoCheatActive()) NoCheatHook.exempt(player); skillDamage = true; target.setNoDamageTicks(0); - target.damage(event.getDamage(), source); + target.damage(event.getDamage(), target == source ? null : source); skillDamage = false; if (PluginChecker.isNoCheatActive()) NoCheatHook.unexempt(player); } @@ -837,6 +840,7 @@ public static boolean isSkillDamage() private static final String DESC = "desc"; private static final String ATTR = "attributes"; private static final String COMBO = "combo"; + private static final String CRIT = "crit-chance"; /** * Saves the skill data to the configuration, overwriting all previous data @@ -895,6 +899,7 @@ public void load(DataSection config) message = TextFormatter.colorString(config.getString(MSG, message)); needsPermission = config.getString(PERM, needsPermission + "").equalsIgnoreCase("true"); combo = SkillAPI.getComboManager().parseCombo(config.getString(COMBO)); + critchance = config.getDouble(CRIT, 0); if (config.isList(DESC)) { diff --git a/src/com/sucy/skill/api/skills/SkillAttribute.java b/src/main/java/com/sucy/skill/api/skills/SkillAttribute.java similarity index 97% rename from src/com/sucy/skill/api/skills/SkillAttribute.java rename to src/main/java/com/sucy/skill/api/skills/SkillAttribute.java index f6faade5..b29f052a 100644 --- a/src/com/sucy/skill/api/skills/SkillAttribute.java +++ b/src/main/java/com/sucy/skill/api/skills/SkillAttribute.java @@ -61,4 +61,6 @@ public final class SkillAttribute public static final String INCOMPATIBLE = "incompatible"; public static final String POINTS_SPENT_REQ = "points-spent-req"; + + public static final String CRIT_CHANCE = "crit-chance"; } diff --git a/src/com/sucy/skill/api/skills/SkillShot.java b/src/main/java/com/sucy/skill/api/skills/SkillShot.java similarity index 100% rename from src/com/sucy/skill/api/skills/SkillShot.java rename to src/main/java/com/sucy/skill/api/skills/SkillShot.java diff --git a/src/com/sucy/skill/api/skills/TargetSkill.java b/src/main/java/com/sucy/skill/api/skills/TargetSkill.java similarity index 100% rename from src/com/sucy/skill/api/skills/TargetSkill.java rename to src/main/java/com/sucy/skill/api/skills/TargetSkill.java diff --git a/src/com/sucy/skill/api/util/ActionBar.java b/src/main/java/com/sucy/skill/api/util/ActionBar.java similarity index 100% rename from src/com/sucy/skill/api/util/ActionBar.java rename to src/main/java/com/sucy/skill/api/util/ActionBar.java diff --git a/src/com/sucy/skill/api/util/Buff.java b/src/main/java/com/sucy/skill/api/util/Buff.java similarity index 100% rename from src/com/sucy/skill/api/util/Buff.java rename to src/main/java/com/sucy/skill/api/util/Buff.java diff --git a/src/com/sucy/skill/api/util/BuffData.java b/src/main/java/com/sucy/skill/api/util/BuffData.java similarity index 76% rename from src/com/sucy/skill/api/util/BuffData.java rename to src/main/java/com/sucy/skill/api/util/BuffData.java index 560747e0..691069c5 100644 --- a/src/com/sucy/skill/api/util/BuffData.java +++ b/src/main/java/com/sucy/skill/api/util/BuffData.java @@ -27,8 +27,11 @@ package com.sucy.skill.api.util; import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.event.PlayerCalculateDamageEvent; import com.sucy.skill.log.LogType; import com.sucy.skill.log.Logger; + +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.scheduler.BukkitRunnable; @@ -95,11 +98,13 @@ public void addBuff(final BuffType type, final String category, final Buff buff, private void doAddBuff(final String type, final Buff buff, final int ticks) { final Map typeBuffs = buffs.computeIfAbsent(type, t -> new HashMap<>()); final Buff conflict = typeBuffs.remove(buff.getKey()); - if (conflict != null) + if (conflict != null && conflict.task != null) conflict.task.cancel(); typeBuffs.put(buff.getKey(), buff); - buff.task = SkillAPI.schedule(new BuffTask(type, buff.getKey()), ticks); + if (ticks >= 0) { + buff.task = SkillAPI.schedule(new BuffTask(type, buff.getKey()), ticks); + } } /** @deprecated use {@link BuffData#addBuff(BuffType, Buff, int)} instead */ @@ -133,8 +138,8 @@ public void addSkillDefenseBuff(Buff buff, int ticks) { * @param value value to modify * @return value after all buff applications */ - public double apply(final BuffType type, final double value) { - return doApply(value, type.name()); + public double apply(final LivingEntity entity, final LivingEntity target, final BuffType type, final double value) { + return doApply(entity, target, value, type.name()); } /** @@ -145,18 +150,20 @@ public double apply(final BuffType type, final double value) { * @param value value to modify * @return value after all buff applications */ - public double apply(final BuffType type, final String category, final double value) { + public double apply(final LivingEntity entity, final LivingEntity target, final BuffType type, final String category, final double value) { return category == null || category.length() == 0 - ? doApply(value, type.name()) - : doApply(value, type.name(), type.name() + category); + ? doApply(entity, target, value, type.name()) + : doApply(entity, target, value, type.name(), type.name() + category); } - private double doApply(final double value, final String... types) { + private double doApply(final LivingEntity caster, final LivingEntity target, double value, final String... types) { // Ignore zeroed out values that shouldn't get buffs if (value <= 0) return value; - - double multiplier = 1; + + // Skip buff calculation on entities without buffs + double posMult = 1; + double negMult = 1; double bonus = 0; Logger.log(LogType.BUFF, 1, "Buffs:"); for (final String type : types) { @@ -168,19 +175,33 @@ private double doApply(final double value, final String... types) { for (final Buff buff : typeBuffs.values()) { if (buff.isPercent()) { Logger.log(LogType.BUFF, 1, " - x" + buff.getValue()); - multiplier *= buff.getValue(); + double bVal = buff.getValue(); + if (bVal >= 1) { + posMult += bVal - 1; + } + else { + negMult *= bVal; + } } else { Logger.log(LogType.BUFF, 1, " - +" + buff.getValue()); bonus += buff.getValue(); } } } - Logger.log(LogType.BUFF, 1, "Result: x" + multiplier + ", +" + bonus + ", " + value + " -> " + Math.max(0, value * multiplier + bonus)); + PlayerCalculateDamageEvent e = new PlayerCalculateDamageEvent(entity, target, value, posMult, negMult, bonus, types); + Bukkit.getPluginManager().callEvent(e); + posMult = e.getPosmult(); + negMult = e.getNegmult(); + bonus = e.getFlat(); + value = e.getDamage(); + + Logger.log(LogType.BUFF, 1, "Result: x" + posMult + "*" + negMult + ", +" + bonus + ", " + value + " = " + Math.max(0, value * (posMult * negMult) + bonus)); // Negatives aren't well received by bukkit, so return 0 instead - if (multiplier <= 0) return 0; + if (negMult <= 0) return 0; + if (value <= 0) return 0; - return Math.max(0, value * multiplier + bonus); + return Math.max(1, value * (posMult * negMult) + bonus); } private double getFlatBonus(final String... types) { @@ -211,30 +232,30 @@ private double getMultiplier(final String... types) { /** @deprecated use {@link BuffData#apply(BuffType, double)} instead */ @Deprecated - public double modifyDealtDamage(double damage) + public double modifyDealtDamage(LivingEntity entity, LivingEntity target, double damage) { - return apply(BuffType.DAMAGE, damage); + return apply(entity, target, BuffType.DAMAGE, damage); } /** @deprecated use {@link BuffData#apply(BuffType, double)} instead */ @Deprecated - public double modifyTakenDamage(double damage) + public double modifyTakenDamage(LivingEntity entity, LivingEntity target, double damage) { - return apply(BuffType.DEFENSE, damage); + return apply(entity, target, BuffType.DEFENSE, damage); } /** @deprecated use {@link BuffData#apply(BuffType, double)} instead */ @Deprecated - public double modifySkillDealtDamage(double damage) + public double modifySkillDealtDamage(LivingEntity entity, LivingEntity target, double damage) { - return apply(BuffType.SKILL_DAMAGE, damage); + return apply(entity, target, BuffType.SKILL_DAMAGE, damage); } /** @deprecated use {@link BuffData#apply(BuffType, double)} instead */ @Deprecated - public double modifySkillTakenDamage(double damage) + public double modifySkillTakenDamage(LivingEntity entity, LivingEntity target, double damage) { - return apply(BuffType.SKILL_DEFENSE, damage); + return apply(entity, target, BuffType.SKILL_DEFENSE, damage); } /** @@ -243,7 +264,9 @@ public double modifySkillTakenDamage(double damage) public void clear() { for (final Map typeBuffs : buffs.values()) { for (final Buff buff : typeBuffs.values()) { - buff.task.cancel(); + if (buff.task != null) { + buff.task.cancel(); + } } } buffs.clear(); diff --git a/src/com/sucy/skill/api/util/BuffManager.java b/src/main/java/com/sucy/skill/api/util/BuffManager.java similarity index 86% rename from src/com/sucy/skill/api/util/BuffManager.java rename to src/main/java/com/sucy/skill/api/util/BuffManager.java index 09fab902..09e18380 100644 --- a/src/com/sucy/skill/api/util/BuffManager.java +++ b/src/main/java/com/sucy/skill/api/util/BuffManager.java @@ -27,6 +27,7 @@ package com.sucy.skill.api.util; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import java.util.HashMap; import java.util.UUID; @@ -144,10 +145,10 @@ public static void addSkillDefenseBuff(final LivingEntity entity, final Buff buf * * @return modified number */ - public static double apply(final LivingEntity entity, final BuffType type, final double amount) + public static double apply(final LivingEntity entity, final LivingEntity target, final BuffType type, final double amount) { - final BuffData data = getBuffData(entity, false); - return data == null ? amount : data.apply(type, amount); + final BuffData data = getBuffData(entity, entity instanceof Player); + return data == null ? amount : data.apply(entity, target, type, amount); } /** @@ -161,33 +162,33 @@ public static double apply(final LivingEntity entity, final BuffType type, final * * @return modified number */ - public static double apply(final LivingEntity entity, final BuffType type, final String category, final double amount) + public static double apply(final LivingEntity entity, final LivingEntity target, final BuffType type, final String category, final double amount) { - final BuffData data = getBuffData(entity, false); - return data == null ? amount : data.apply(type, category, amount); + final BuffData data = getBuffData(entity, entity instanceof Player); + return data == null ? amount : data.apply(entity, target, type, category, amount); } /** @deprecated use {@link BuffManager#apply(LivingEntity, BuffType, double)} instead */ @Deprecated - public static double modifyDealtDamage(final LivingEntity entity, final double damage) { - return apply(entity, BuffType.DAMAGE, damage); + public static double modifyDealtDamage(final LivingEntity entity, final LivingEntity target, final double damage) { + return apply(entity, target, BuffType.DAMAGE, damage); } /** @deprecated use {@link BuffManager#apply(LivingEntity, BuffType, double)} instead */ @Deprecated - public static double modifyTakenDefense(final LivingEntity entity, final double damage) { - return apply(entity, BuffType.DEFENSE, damage); + public static double modifyTakenDefense(final LivingEntity entity, final LivingEntity target, final double damage) { + return apply(entity, target, BuffType.DEFENSE, damage); } /** @deprecated use {@link BuffManager#apply(LivingEntity, BuffType, double)} instead */ @Deprecated - public static double modifySkillDealtDamage(LivingEntity entity, double damage) { - return apply(entity, BuffType.SKILL_DAMAGE, damage); + public static double modifySkillDealtDamage(LivingEntity entity, final LivingEntity target, double damage) { + return apply(entity, target, BuffType.SKILL_DAMAGE, damage); } /** @deprecated use {@link BuffManager#apply(LivingEntity, BuffType, double)} instead */ @Deprecated - public static double modifySkillTakenDefense(LivingEntity entity, double damage) { - return apply(entity, BuffType.SKILL_DEFENSE, damage); + public static double modifySkillTakenDefense(LivingEntity entity, final LivingEntity target, double damage) { + return apply(entity, target, BuffType.SKILL_DEFENSE, damage); } } diff --git a/src/com/sucy/skill/api/util/BuffType.java b/src/main/java/com/sucy/skill/api/util/BuffType.java similarity index 100% rename from src/com/sucy/skill/api/util/BuffType.java rename to src/main/java/com/sucy/skill/api/util/BuffType.java diff --git a/src/com/sucy/skill/api/util/Combat.java b/src/main/java/com/sucy/skill/api/util/Combat.java similarity index 100% rename from src/com/sucy/skill/api/util/Combat.java rename to src/main/java/com/sucy/skill/api/util/Combat.java diff --git a/src/com/sucy/skill/api/util/DamageLoreRemover.java b/src/main/java/com/sucy/skill/api/util/DamageLoreRemover.java similarity index 92% rename from src/com/sucy/skill/api/util/DamageLoreRemover.java rename to src/main/java/com/sucy/skill/api/util/DamageLoreRemover.java index d58c8696..028d1c8e 100644 --- a/src/com/sucy/skill/api/util/DamageLoreRemover.java +++ b/src/main/java/com/sucy/skill/api/util/DamageLoreRemover.java @@ -61,10 +61,10 @@ private static void setup() try { - NBT_BASE = Reflection.getNMSClass("NBTBase"); - NBT_COMPOUND = Reflection.getNMSClass("NBTTagCompound"); - NBT_LIST = Reflection.getNMSClass("NBTTagList"); - NMS_ITEM = Reflection.getNMSClass("ItemStack"); + NBT_BASE = Reflection.getClass("net.minecraft.nbt.NBTBase"); + NBT_COMPOUND = Reflection.getClass("net.minecraft.nbt.NBTTagCompound"); + NBT_LIST = Reflection.getClass("net.minecraft.nbt.NBTTagList"); + NMS_ITEM = Reflection.getClass("net.minecraft.world.item.ItemStack"); CRAFT_ITEM = Reflection.getCraftClass("inventory.CraftItemStack"); AS_NMS = CRAFT_ITEM.getMethod("asNMSCopy", ItemStack.class); diff --git a/src/com/sucy/skill/api/util/Data.java b/src/main/java/com/sucy/skill/api/util/Data.java similarity index 92% rename from src/com/sucy/skill/api/util/Data.java rename to src/main/java/com/sucy/skill/api/util/Data.java index 5c93c2aa..afe27cf4 100644 --- a/src/com/sucy/skill/api/util/Data.java +++ b/src/main/java/com/sucy/skill/api/util/Data.java @@ -45,8 +45,9 @@ public class Data { private static final String DATA = "icon-data"; private static final String DURABILITY = "icon-durability"; private static final String LORE = "icon-lore"; + private static final String MODEL = "icon-model"; - private static ItemStack parse(final String mat, final short dur, final byte data, final List lore) { + private static ItemStack parse(final String mat, final short dur, final byte data, final List lore, final int model) { try { Material material = Material.matchMaterial(mat); if (material == null) { @@ -62,6 +63,7 @@ private static ItemStack parse(final String mat, final short dur, final byte dat final ItemMeta meta = item.getItemMeta(); meta.setDisplayName(colored.remove(0)); meta.setLore(colored); + meta.setCustomModelData(model); item.setItemMeta(meta); } return DamageLoreRemover.removeAttackDmg(item); @@ -87,6 +89,7 @@ public static void serializeIcon(ItemStack item, DataSection config) { lore.add(0, item.getItemMeta().getDisplayName()); int count = lore.size(); for (int i = 0; i < count; i++) { lore.add(lore.remove(0).replace(ChatColor.COLOR_CHAR, '&')); } + config.set(MODEL, item.getItemMeta().getCustomModelData()); config.set(LORE, lore); } } @@ -104,10 +107,11 @@ public static ItemStack parseIcon(DataSection config) { } final int data = config.getInt(DATA, 0); + final int model = config.getInt(MODEL, 0); return parse( config.getString(MAT, "JACK_O_LANTERN"), (short) config.getInt(DURABILITY, data), (byte) data, - config.getList(LORE, null)); + config.getList(LORE, null), model); } } diff --git a/src/com/sucy/skill/api/util/FlagData.java b/src/main/java/com/sucy/skill/api/util/FlagData.java similarity index 96% rename from src/com/sucy/skill/api/util/FlagData.java rename to src/main/java/com/sucy/skill/api/util/FlagData.java index 12d2c7d8..4c9c8429 100644 --- a/src/com/sucy/skill/api/util/FlagData.java +++ b/src/main/java/com/sucy/skill/api/util/FlagData.java @@ -28,6 +28,8 @@ import com.sucy.skill.api.event.FlagApplyEvent; import com.sucy.skill.api.event.FlagExpireEvent; +import com.sucy.skill.api.player.PlayerData; + import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.plugin.Plugin; @@ -64,10 +66,12 @@ public FlagData(LivingEntity entity) * @param flag flag to set * @param ticks number of ticks to set the flag for */ - public void addFlag(String flag, int ticks) + public void addFlag(LivingEntity caster, String flag, int ticks) { - FlagApplyEvent event = new FlagApplyEvent(entity, flag, ticks); + FlagApplyEvent event = new FlagApplyEvent(caster, entity, flag, ticks); Bukkit.getPluginManager().callEvent(event); + ticks = event.getTicks(); + if (event.isCancelled()) return; // Permanent flag diff --git a/src/com/sucy/skill/api/util/FlagManager.java b/src/main/java/com/sucy/skill/api/util/FlagManager.java similarity index 95% rename from src/com/sucy/skill/api/util/FlagManager.java rename to src/main/java/com/sucy/skill/api/util/FlagManager.java index 469607a2..6249f08b 100644 --- a/src/com/sucy/skill/api/util/FlagManager.java +++ b/src/main/java/com/sucy/skill/api/util/FlagManager.java @@ -28,6 +28,8 @@ import org.bukkit.entity.LivingEntity; +import com.sucy.skill.api.player.PlayerData; + import java.util.HashMap; /** @@ -80,12 +82,12 @@ public static FlagData getFlagData(LivingEntity entity, boolean create) * @param flag the flag to add * @param ticks the duration to add the flag for */ - public static void addFlag(LivingEntity entity, String flag, int ticks) + public static void addFlag(LivingEntity caster, LivingEntity entity, String flag, int ticks) { FlagData data = getFlagData(entity, true); if (data != null) { - data.addFlag(flag, ticks); + data.addFlag(caster, flag, ticks); } } diff --git a/src/com/sucy/skill/api/util/ItemSerializer.java b/src/main/java/com/sucy/skill/api/util/ItemSerializer.java similarity index 98% rename from src/com/sucy/skill/api/util/ItemSerializer.java rename to src/main/java/com/sucy/skill/api/util/ItemSerializer.java index db6cb2f1..2a4183f1 100644 --- a/src/com/sucy/skill/api/util/ItemSerializer.java +++ b/src/main/java/com/sucy/skill/api/util/ItemSerializer.java @@ -29,6 +29,8 @@ import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; import com.rit.sucy.reflect.Reflection; + +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; @@ -42,6 +44,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.logging.Level; // Based on the thread https://bukkit.org/threads/help-with-serialized-nbttagcompounds.116335/ public class ItemSerializer { @@ -104,7 +107,8 @@ private static void initialize() { nbtCompressedStreamTools_read = nbtCompressedStreamTools.getDeclaredMethod("a", DataInputStream.class); } catch (Exception ex) { - System.out.println("Server doesn't support NBT serialization - resorting to a less complete implementation"); + Bukkit.getLogger().log(Level.WARNING, + "Server doesn't support NBT serialization - resorting to a less complete implementation"); } } diff --git a/src/com/sucy/skill/api/util/Nearby.java b/src/main/java/com/sucy/skill/api/util/Nearby.java similarity index 98% rename from src/com/sucy/skill/api/util/Nearby.java rename to src/main/java/com/sucy/skill/api/util/Nearby.java index 4f8a2661..893df723 100644 --- a/src/com/sucy/skill/api/util/Nearby.java +++ b/src/main/java/com/sucy/skill/api/util/Nearby.java @@ -92,8 +92,7 @@ private static List getLivingNearby(Entity source, Location loc, d for (int i = minX; i <= maxX; i++) for (int j = minZ; j <= maxZ; j++) for (Entity entity : loc.getWorld().getChunkAt(i, j).getEntities()) - if (entity != source - && entity instanceof LivingEntity + if (entity != source && entity instanceof LivingEntity && entity.getWorld() == loc.getWorld() && entity.getLocation().distanceSquared(loc) < radius) result.add((LivingEntity) entity); diff --git a/src/main/java/com/sucy/skill/api/util/ParticleHelper.java b/src/main/java/com/sucy/skill/api/util/ParticleHelper.java new file mode 100644 index 00000000..b4af2974 --- /dev/null +++ b/src/main/java/com/sucy/skill/api/util/ParticleHelper.java @@ -0,0 +1,357 @@ +/* + * SkillAPI + * com.sucy.skill.api.util.ParticleHelper + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.api.util; + +import com.destroystokyo.paper.ParticleBuilder; +import com.sucy.skill.api.ParticleSettings; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.enums.Direction; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; + +import java.util.Random; + +/** + * Helper class for playing particles via config strings in various ways. + */ +public class ParticleHelper { + + /** + * Settings key for the arrangement type of particles + */ + public static final String ARRANGEMENT_KEY = "arrangement"; + + /** + * Number of particles + */ + public static final String PARTICLES_KEY = "particles"; + + /** + * The level to use for scaling values + */ + public static final String LEVEL = "level"; + + /** + * Settings key for the type of particle + */ + public static final String PARTICLE_KEY = "particle"; + + /** + * Settings key for the material used by the particle (for block crack, icon crack, and block dust) + */ + public static final String MATERIAL_KEY = "material"; + + /** + * Settings key for the material data used by the particle (for block crack, icon crack, and block dust) + */ + public static final String TYPE_KEY = "type"; + + /** + * Settings key for the radius of the particle arrangement + */ + public static final String RADIUS_KEY = "radius"; + + /** + * Settings key for the amount of particles to play + */ + public static final String AMOUNT_KEY = "amount"; + + /** + * Settings key for the particle arrangement direction (circles only) + */ + public static final String DIRECTION_KEY = "direction"; + + /** + * Settings key for the Bukkit effects' data (default 0) + */ + public static final String DATA_KEY = "data"; + + /** + * Settings key for the reflection particles' visible radius (default 25) + */ + public static final String VISIBLE_RADIUS_KEY = "visible-radius"; + + /** + * Settings key for the reflection particles' X-offset (default 0) + */ + public static final String DX_KEY = "dx"; + + /** + * Settings key for the reflection particles' Y-offset (default 0) + */ + public static final String DY_KEY = "dy"; + + /** + * Settings key for the reflection particles' Z-offset (default 0) + */ + public static final String DZ_KEY = "dz"; + + /** + * Settings key for the colored particles' red color (default 0) + */ + public static final String RGB_KEY = "rgb"; + + /** + * Settings key for the reflection particles' "speed" value (default 1) + */ + public static final String SPEED_KEY = "speed"; + + private static final Random random = new Random(); + + public static void play(ParticleSettings particleSettings, Location loc) { + + Settings settings = particleSettings.getOriginalSettings(); + + if (settings.has(ARRANGEMENT_KEY)) { + int level = settings.getInt(LEVEL, 1); + double radius = settings.getAttr(RADIUS_KEY, level, 3.0); + int amount = (int) settings.getAttr(PARTICLES_KEY, level, 10); + + String arrangement = settings.getString(ARRANGEMENT_KEY).toLowerCase(); + switch (arrangement) { + case "circle": + Direction dir = null; + if (settings.has(DIRECTION_KEY)) { + try { + dir = Direction.valueOf(settings.getString(DIRECTION_KEY)); + } catch (Exception ex) { /* Use default value */ } + } + if (dir == null) { + dir = Direction.XZ; + } + + fillCircle(particleSettings, loc, radius, amount, dir); + break; + case "sphere": + fillSphere(particleSettings, loc, radius, amount); + break; + case "hemisphere": + fillHemisphere(particleSettings, loc, radius, amount); + break; + } + } else { + particleSettings.spawn(loc); +// play(caster, loc, particle, settings); + } + } + + /** + * Plays particles about the given location using the given settings + * + * @param loc location to center the effect around + * @param settings data to play the particles with + */ + public static void play(LivingEntity caster, Location loc, Settings settings) { +// String particle = settings.getString(PARTICLE_KEY, "invalid"); + + ParticleSettings particleSettings = new ParticleSettings(caster, settings); + play(particleSettings, loc); + +// if (settings.has(ARRANGEMENT_KEY)) { +// int level = settings.getInt(LEVEL, 1); +// double radius = settings.getAttr(RADIUS_KEY, level, 3.0); +// int amount = (int) settings.getAttr(PARTICLES_KEY, level, 10); +// +// String arrangement = settings.getString(ARRANGEMENT_KEY).toLowerCase(); +// switch (arrangement) { +// case "circle": +// Direction dir = null; +// if (settings.has(DIRECTION_KEY)) { +// try { +// dir = Direction.valueOf(settings.getString(DIRECTION_KEY)); +// } catch (Exception ex) { /* Use default value */ } +// } +// if (dir == null) { +// dir = Direction.XZ; +// } +// +// fillCircle(particleSettings, loc, radius, amount, dir); +// break; +// case "sphere": +// fillSphere(particleSettings, loc, radius, amount); +// break; +// case "hemisphere": +// fillHemisphere(particleSettings, loc, radius, amount); +// break; +// } +// } else { +// particleSettings.spawn(loc); +//// play(caster, loc, particle, settings); +// } + } + + /** + * Plays a particle at the given location based on the string + * + * @param loc location to play the effect + * @param caster particle to play + * @param particleSettings data to play the particle with + */ + private static void play(LivingEntity caster, Location loc, ParticleBuilder particleSettings) { +// , final String particle, Settings settings) { +// int rad = settings.getInt(VISIBLE_RADIUS_KEY, 25); +// +// final boolean onlyCaster = settings.getBool("onlycaster", true); +// +// final float dx = (float) settings.getDouble(DX_KEY, 0.0); +// final float dy = (float) settings.getDouble(DY_KEY, 0.0); +// final float dz = (float) settings.getDouble(DZ_KEY, 0.0); +// +// +// final int amount = settings.getInt(AMOUNT_KEY, 1); +// final float speed = (float) settings.getDouble(SPEED_KEY, 1.0); +// final Material mat = Material.valueOf(settings.getString(MATERIAL_KEY, "DIRT").toUpperCase().replace(" ", "_")); + +// try { +// // Normal bukkit effects +// if (BUKKIT_EFFECTS.containsKey(particle)) { +// loc.getWorld().playEffect(loc, BUKKIT_EFFECTS.get(particle), settings.getInt(DATA_KEY, 0)); +// } +// +// // Entity effects +// else if (ENTITY_EFFECTS.contains(particle)) { +// play(loc, EntityEffect.valueOf(particle.toUpperCase().replace(' ', '_'))); +// } +// +// // v1.13 particles +// else if (VersionManager.isVersionAtLeast(11300)) { +// +// particleSettings.location(loc).spawn(); +// } +// } catch (Exception ex) { +// settings.dumpToConsole(); +// } + } + + /** + * Plays several of a particle type randomly within a circle + * + * @param center center location of the circle + * @param particleSettings data to play the particle with + * @param radius radius of the circle + * @param amount amount of particles to play + * @param direction direction of the particle + */ + public static void fillCircle(ParticleSettings particleSettings, Location center, double radius, int amount, Direction direction) { + Location temp = center.clone(); + double rSquared = radius * radius; + double twoRadius = radius * 2; + int index = 0; + + // Play the particles + while (index < amount) { + if (direction == Direction.XY || direction == Direction.XZ) { + temp.setX(center.getX() + random.nextDouble() * twoRadius - radius); + } + if (direction == Direction.XY || direction == Direction.YZ) { + temp.setY(center.getY() + random.nextDouble() * twoRadius - radius); + } + if (direction == Direction.XZ || direction == Direction.YZ) { + temp.setZ(center.getZ() + random.nextDouble() * twoRadius - radius); + } + + if (temp.distanceSquared(center) > rSquared) { + continue; + } + + particleSettings.spawn(temp); +// play(caster, temp, particle, settings); + index++; + } + } + + /** + * Randomly plays particle effects within the sphere + * + * @param particleSettings data to play the particle with + * @param center location to center the effect around + * @param radius radius of the sphere + * @param amount amount of particles to use + */ + public static void fillSphere(ParticleSettings particleSettings, Location center, double radius, int amount) { + Location temp = center.clone(); + double rSquared = radius * radius; + double twoRadius = radius * 2; + int index = 0; + + // Play the particles + while (index < amount) { + temp.setX(center.getX() + random.nextDouble() * twoRadius - radius); + temp.setY(center.getY() + random.nextDouble() * twoRadius - radius); + temp.setZ(center.getZ() + random.nextDouble() * twoRadius - radius); + + if (temp.distanceSquared(center) > rSquared) { + continue; + } + + particleSettings.spawn(temp); +// play(caster, temp, particle, settings); + index++; + } + } + + /** + * Randomly plays particle effects within the hemisphere + * + * @param loc location to center the effect around + * @param particleSettings data to play the particle with + * @param radius radius of the sphere + * @param amount amount of particles to use + */ + public static void fillHemisphere(ParticleSettings particleSettings, Location loc, double radius, int amount) { + Location temp = loc.clone(); + double rSquared = radius * radius; + double twoRadius = radius * 2; + int index = 0; + + // Play the particles + while (index < amount) { + temp.setX(loc.getX() + random.nextDouble() * twoRadius - radius); + temp.setY(loc.getY() + random.nextDouble() * radius); + temp.setZ(loc.getZ() + random.nextDouble() * twoRadius - radius); + + if (temp.distanceSquared(loc) > rSquared) { + continue; + } + + particleSettings.spawn(temp); +// play(caster, temp, particle, settings); + index++; + } + } + +// private static final HashMap BUKKIT_EFFECTS = new HashMap() {{ +// put("smoke", Effect.SMOKE); +// put("ender signal", Effect.ENDER_SIGNAL); +// put("mobspawner flames", Effect.MOBSPAWNER_FLAMES); +// put("potion break", Effect.POTION_BREAK); +// }}; +// +// private static final Set ENTITY_EFFECTS = ImmutableSet.of( +// "death", "hurt", "sheep eat", "wolf hearts", "wolf shake", "wolf smoke"); + +} diff --git a/src/com/sucy/skill/api/util/StatusFlag.java b/src/main/java/com/sucy/skill/api/util/StatusFlag.java similarity index 89% rename from src/com/sucy/skill/api/util/StatusFlag.java rename to src/main/java/com/sucy/skill/api/util/StatusFlag.java index adfd31f5..3d984c0d 100644 --- a/src/com/sucy/skill/api/util/StatusFlag.java +++ b/src/main/java/com/sucy/skill/api/util/StatusFlag.java @@ -32,6 +32,8 @@ public class StatusFlag { public static final String STUN = "stun"; + public static final String CHARM = "charm"; + public static final String CURSE = "curse"; public static final String ROOT = "root"; public static final String INVINCIBLE = "invincible"; public static final String ABSORB = "absorb"; @@ -41,11 +43,11 @@ public class StatusFlag public static final String CHANNEL = "channel"; public static final String[] ALL = new String[] { - STUN, ROOT, INVINCIBLE, ABSORB, DISARM, SILENCE, CHANNELING + STUN, ROOT, CHARM, CURSE, INVINCIBLE, ABSORB, DISARM, SILENCE, CHANNELING }; public static final String[] NEGATIVE = new String[] { - STUN, ROOT, DISARM, SILENCE + STUN, ROOT, DISARM, SILENCE, CHARM, CURSE }; public static final String[] POSITIVE = new String[] { diff --git a/src/com/sucy/skill/api/util/Title.java b/src/main/java/com/sucy/skill/api/util/Title.java similarity index 100% rename from src/com/sucy/skill/api/util/Title.java rename to src/main/java/com/sucy/skill/api/util/Title.java diff --git a/src/com/sucy/skill/cast/CircleIndicator.java b/src/main/java/com/sucy/skill/cast/CircleIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/CircleIndicator.java rename to src/main/java/com/sucy/skill/cast/CircleIndicator.java diff --git a/src/com/sucy/skill/cast/ConeIndicator.java b/src/main/java/com/sucy/skill/cast/ConeIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/ConeIndicator.java rename to src/main/java/com/sucy/skill/cast/ConeIndicator.java diff --git a/src/com/sucy/skill/cast/CylinderIndicator.java b/src/main/java/com/sucy/skill/cast/CylinderIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/CylinderIndicator.java rename to src/main/java/com/sucy/skill/cast/CylinderIndicator.java diff --git a/src/com/sucy/skill/cast/IIndicator.java b/src/main/java/com/sucy/skill/cast/IIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/IIndicator.java rename to src/main/java/com/sucy/skill/cast/IIndicator.java diff --git a/src/com/sucy/skill/cast/IndicatorSettings.java b/src/main/java/com/sucy/skill/cast/IndicatorSettings.java similarity index 100% rename from src/com/sucy/skill/cast/IndicatorSettings.java rename to src/main/java/com/sucy/skill/cast/IndicatorSettings.java diff --git a/src/com/sucy/skill/cast/IndicatorType.java b/src/main/java/com/sucy/skill/cast/IndicatorType.java similarity index 100% rename from src/com/sucy/skill/cast/IndicatorType.java rename to src/main/java/com/sucy/skill/cast/IndicatorType.java diff --git a/src/com/sucy/skill/cast/PlayerCastBars.java b/src/main/java/com/sucy/skill/cast/PlayerCastBars.java similarity index 100% rename from src/com/sucy/skill/cast/PlayerCastBars.java rename to src/main/java/com/sucy/skill/cast/PlayerCastBars.java diff --git a/src/com/sucy/skill/cast/PlayerView.java b/src/main/java/com/sucy/skill/cast/PlayerView.java similarity index 100% rename from src/com/sucy/skill/cast/PlayerView.java rename to src/main/java/com/sucy/skill/cast/PlayerView.java diff --git a/src/com/sucy/skill/cast/ProjectileIndicator.java b/src/main/java/com/sucy/skill/cast/ProjectileIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/ProjectileIndicator.java rename to src/main/java/com/sucy/skill/cast/ProjectileIndicator.java diff --git a/src/com/sucy/skill/cast/SphereIndicator.java b/src/main/java/com/sucy/skill/cast/SphereIndicator.java similarity index 100% rename from src/com/sucy/skill/cast/SphereIndicator.java rename to src/main/java/com/sucy/skill/cast/SphereIndicator.java diff --git a/src/com/sucy/skill/cmd/CmdAP.java b/src/main/java/com/sucy/skill/cmd/CmdAP.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdAP.java rename to src/main/java/com/sucy/skill/cmd/CmdAP.java index 471e5bee..0672e6f5 100644 --- a/src/com/sucy/skill/cmd/CmdAP.java +++ b/src/main/java/com/sucy/skill/cmd/CmdAP.java @@ -34,6 +34,8 @@ import com.sucy.skill.SkillAPI; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.language.RPGFilter; + +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -73,7 +75,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender else if (args.length >= 1 && (args.length >= 2 || sender instanceof Player)) { // Get the player data - OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdAccount.java b/src/main/java/com/sucy/skill/cmd/CmdAccount.java similarity index 94% rename from src/com/sucy/skill/cmd/CmdAccount.java rename to src/main/java/com/sucy/skill/cmd/CmdAccount.java index 56e06bcd..3d9f6523 100644 --- a/src/com/sucy/skill/cmd/CmdAccount.java +++ b/src/main/java/com/sucy/skill/cmd/CmdAccount.java @@ -85,6 +85,10 @@ else if (args.length == 0) if (player.getAccountLimit() >= id && id > 0) { + if (player.getActiveId() == id) { + sender.sendMessage("§cYou're already on this account!"); + return; + } player.setAccount(id); command.sendMessage(sender, CHANGED, ChatColor.DARK_GREEN + "Your account has been changed"); return; @@ -92,7 +96,7 @@ else if (args.length == 0) } catch (Exception ex) { - // Invalid ID + ex.printStackTrace(); } command.sendMessage(sender, NOT_ACCOUNT, ChatColor.RED + "That is not a valid account ID"); diff --git a/src/com/sucy/skill/cmd/CmdAttribute.java b/src/main/java/com/sucy/skill/cmd/CmdAttribute.java similarity index 91% rename from src/com/sucy/skill/cmd/CmdAttribute.java rename to src/main/java/com/sucy/skill/cmd/CmdAttribute.java index e4b06429..20b3f848 100644 --- a/src/com/sucy/skill/cmd/CmdAttribute.java +++ b/src/main/java/com/sucy/skill/cmd/CmdAttribute.java @@ -63,9 +63,14 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender // Only plays have skills to view else if (sender instanceof Player) { - Player p = (Player) sender; - PlayerData data = SkillAPI.getPlayerData(p); - data.openAttributeMenu(); + try { + Player p = (Player) sender; + PlayerData data = SkillAPI.getPlayerData(p); + data.openAttributeMenu(); + } + catch (Exception e) { + e.printStackTrace(); + } } // Console doesn't have profession options diff --git a/src/com/sucy/skill/cmd/CmdBackup.java b/src/main/java/com/sucy/skill/cmd/CmdBackup.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdBackup.java rename to src/main/java/com/sucy/skill/cmd/CmdBackup.java index 9ddf985c..9b4770bd 100644 --- a/src/com/sucy/skill/cmd/CmdBackup.java +++ b/src/main/java/com/sucy/skill/cmd/CmdBackup.java @@ -35,7 +35,6 @@ import com.sucy.skill.SkillAPI; import com.sucy.skill.data.Settings; import com.sucy.skill.data.io.SQLIO; -import com.sun.xml.internal.fastinfoset.Encoder; import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; @@ -112,11 +111,11 @@ public void run() while (query.next()) { String sqlYaml = query.getString(SQLIO.DATA); - String yaml = YAMLParser.parseText(sqlYaml, SQLIO.STRING).toString(); + String yaml = YAMLParser.parseText(sqlYaml, SQLIO.QUOTE).toString(); String name = query.getString("Name"); FileOutputStream out = new FileOutputStream(new File(file, name + ".yml")); - BufferedWriter write = new BufferedWriter(new OutputStreamWriter(out, Encoder.UTF_8)); + BufferedWriter write = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); write.write(yaml); diff --git a/src/com/sucy/skill/cmd/CmdBar.java b/src/main/java/com/sucy/skill/cmd/CmdBar.java similarity index 96% rename from src/com/sucy/skill/cmd/CmdBar.java rename to src/main/java/com/sucy/skill/cmd/CmdBar.java index 11c6d61d..9f66fc94 100644 --- a/src/com/sucy/skill/cmd/CmdBar.java +++ b/src/main/java/com/sucy/skill/cmd/CmdBar.java @@ -60,6 +60,12 @@ public class CmdBar implements IFunction @Override public void execute(ConfigurableCommand command, Plugin plugin, CommandSender sender, String[] args) { + + // If the skill bar is disabled then we return and un + SkillAPI api = (SkillAPI) plugin; + if(!api.isSkillBarsEnabled()) + return; + if (!(sender instanceof Player)) { command.sendMessage(sender, NOT_PLAYER, "&4Only players can use this command"); diff --git a/src/com/sucy/skill/cmd/CmdBind.java b/src/main/java/com/sucy/skill/cmd/CmdBind.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdBind.java rename to src/main/java/com/sucy/skill/cmd/CmdBind.java diff --git a/src/com/sucy/skill/cmd/CmdCast.java b/src/main/java/com/sucy/skill/cmd/CmdCast.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdCast.java rename to src/main/java/com/sucy/skill/cmd/CmdCast.java diff --git a/src/com/sucy/skill/cmd/CmdChangeClass.java b/src/main/java/com/sucy/skill/cmd/CmdChangeClass.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdChangeClass.java rename to src/main/java/com/sucy/skill/cmd/CmdChangeClass.java index f44b1886..4c311451 100644 --- a/src/com/sucy/skill/cmd/CmdChangeClass.java +++ b/src/main/java/com/sucy/skill/cmd/CmdChangeClass.java @@ -1,6 +1,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; import com.rit.sucy.version.VersionManager; @@ -40,7 +41,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender String className = args[2]; for (int i = 3; i < args.length; i++) className += ' ' + args[i]; - final Player player = VersionManager.getPlayer(playerName); + final Player player = Bukkit.getPlayer(playerName); if (player == null) { cmd.sendMessage(sender, INVALID_PLAYER, ChatColor.DARK_RED + "{player} is not online", Filter.PLAYER.setReplacement(playerName)); diff --git a/src/com/sucy/skill/cmd/CmdClearBinds.java b/src/main/java/com/sucy/skill/cmd/CmdClearBinds.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdClearBinds.java rename to src/main/java/com/sucy/skill/cmd/CmdClearBinds.java diff --git a/src/com/sucy/skill/cmd/CmdCombo.java b/src/main/java/com/sucy/skill/cmd/CmdCombo.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdCombo.java rename to src/main/java/com/sucy/skill/cmd/CmdCombo.java diff --git a/src/com/sucy/skill/cmd/CmdCustomize.java b/src/main/java/com/sucy/skill/cmd/CmdCustomize.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdCustomize.java rename to src/main/java/com/sucy/skill/cmd/CmdCustomize.java diff --git a/src/main/java/com/sucy/skill/cmd/CmdDebug.java b/src/main/java/com/sucy/skill/cmd/CmdDebug.java new file mode 100644 index 00000000..9b2bb3fb --- /dev/null +++ b/src/main/java/com/sucy/skill/cmd/CmdDebug.java @@ -0,0 +1,48 @@ +/** + * SkillAPI + * com.sucy.skill.cmd.CmdWorld + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.cmd; + +import com.rit.sucy.commands.ConfigurableCommand; +import com.rit.sucy.commands.IFunction; +import com.sucy.skill.SkillAPI; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class CmdDebug implements IFunction { + + @Override + public void execute(final ConfigurableCommand cmd, final Plugin plugin, final CommandSender sender, final String[] args) { + SkillAPI.debug = !SkillAPI.debug; + Bukkit.getLogger().info("[SkillAPI] Debug set to " + SkillAPI.debug); + } +} diff --git a/src/com/sucy/skill/cmd/CmdExp.java b/src/main/java/com/sucy/skill/cmd/CmdExp.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdExp.java rename to src/main/java/com/sucy/skill/cmd/CmdExp.java index 3e21e61d..6e2ccde0 100644 --- a/src/com/sucy/skill/cmd/CmdExp.java +++ b/src/main/java/com/sucy/skill/cmd/CmdExp.java @@ -1,6 +1,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -81,7 +82,7 @@ else if ((args.length >= 1 && sender instanceof Player && IS_NUMBER.matcher(args if (args.length > 1 && IS_NUMBER.matcher(args[1]).matches()) numberIndex = 1; // Get the player data - OfflinePlayer target = numberIndex == 0 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = numberIndex == 0 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdForceAccount.java b/src/main/java/com/sucy/skill/cmd/CmdForceAccount.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdForceAccount.java rename to src/main/java/com/sucy/skill/cmd/CmdForceAccount.java index dcbe7848..33ce273b 100644 --- a/src/com/sucy/skill/cmd/CmdForceAccount.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceAccount.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; import com.rit.sucy.version.VersionManager; @@ -69,7 +70,7 @@ public void execute(ConfigurableCommand command, Plugin plugin, CommandSender se // Switch accounts if valid number else { - OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); if (player == null) { diff --git a/src/com/sucy/skill/cmd/CmdForceAttr.java b/src/main/java/com/sucy/skill/cmd/CmdForceAttr.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdForceAttr.java rename to src/main/java/com/sucy/skill/cmd/CmdForceAttr.java index 7b4d9430..7032392f 100644 --- a/src/com/sucy/skill/cmd/CmdForceAttr.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceAttr.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -70,7 +71,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender } // Grab the player data - OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); if (player == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdForceCast.java b/src/main/java/com/sucy/skill/cmd/CmdForceCast.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdForceCast.java rename to src/main/java/com/sucy/skill/cmd/CmdForceCast.java index 218908b0..c809600a 100644 --- a/src/com/sucy/skill/cmd/CmdForceCast.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceCast.java @@ -37,6 +37,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.bukkit.Bukkit; import java.util.regex.Pattern; @@ -70,7 +71,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender } else { - Player player = VersionManager.getPlayer(args[0]); + Player player = Bukkit.getPlayer(args[0]); if (player == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdForceProfess.java b/src/main/java/com/sucy/skill/cmd/CmdForceProfess.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdForceProfess.java rename to src/main/java/com/sucy/skill/cmd/CmdForceProfess.java index dd16c013..0a0ca82d 100644 --- a/src/com/sucy/skill/cmd/CmdForceProfess.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceProfess.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -72,7 +73,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender } else { - OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); if (player == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdForceReset.java b/src/main/java/com/sucy/skill/cmd/CmdForceReset.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdForceReset.java rename to src/main/java/com/sucy/skill/cmd/CmdForceReset.java index 14c3e174..deabb7ff 100644 --- a/src/com/sucy/skill/cmd/CmdForceReset.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceReset.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; import com.rit.sucy.config.parse.NumberParser; @@ -69,7 +70,7 @@ public void execute(ConfigurableCommand command, Plugin plugin, CommandSender se // Switch accounts if valid number else { - OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); if (player == null) { diff --git a/src/com/sucy/skill/cmd/CmdForceSkill.java b/src/main/java/com/sucy/skill/cmd/CmdForceSkill.java similarity index 97% rename from src/com/sucy/skill/cmd/CmdForceSkill.java rename to src/main/java/com/sucy/skill/cmd/CmdForceSkill.java index 0f5e5648..3562cef7 100644 --- a/src/com/sucy/skill/cmd/CmdForceSkill.java +++ b/src/main/java/com/sucy/skill/cmd/CmdForceSkill.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.version.VersionManager; import com.sucy.skill.SkillAPI; @@ -68,7 +69,7 @@ public void execute(ConfigurableCommand command, Plugin plugin, CommandSender se // Switch accounts if valid number else { - OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); if (player == null) { diff --git a/src/com/sucy/skill/cmd/CmdInfo.java b/src/main/java/com/sucy/skill/cmd/CmdInfo.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdInfo.java rename to src/main/java/com/sucy/skill/cmd/CmdInfo.java index cd8151c6..feb67b4a 100644 --- a/src/com/sucy/skill/cmd/CmdInfo.java +++ b/src/main/java/com/sucy/skill/cmd/CmdInfo.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; import com.rit.sucy.text.TextFormatter; @@ -77,7 +78,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender // Only can show info of a player so console needs to provide a name else if (sender instanceof Player || args.length >= 1) { - OfflinePlayer target = args.length == 0 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = args.length == 0 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdLevel.java b/src/main/java/com/sucy/skill/cmd/CmdLevel.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdLevel.java rename to src/main/java/com/sucy/skill/cmd/CmdLevel.java index d595b009..ad445392 100644 --- a/src/com/sucy/skill/cmd/CmdLevel.java +++ b/src/main/java/com/sucy/skill/cmd/CmdLevel.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -86,7 +87,7 @@ else if ((args.length >= 1 && sender instanceof Player && IS_NUMBER.matcher(args if (args.length > 1 && IS_NUMBER.matcher(args[1]).matches()) numberIndex = 1; // Get the player data - OfflinePlayer target = numberIndex == 0 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = numberIndex == 0 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdList.java b/src/main/java/com/sucy/skill/cmd/CmdList.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdList.java rename to src/main/java/com/sucy/skill/cmd/CmdList.java index abea1a1e..0a670a9a 100644 --- a/src/com/sucy/skill/cmd/CmdList.java +++ b/src/main/java/com/sucy/skill/cmd/CmdList.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.ConfigurableCommand; +import org.bukkit.Bukkit; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; import com.rit.sucy.version.VersionManager; @@ -72,7 +73,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender // Only can show info of a player so console needs to provide a name else if (sender instanceof Player || args.length >= 1) { - OfflinePlayer target = args.length == 0 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = args.length == 0 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdLore.java b/src/main/java/com/sucy/skill/cmd/CmdLore.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdLore.java rename to src/main/java/com/sucy/skill/cmd/CmdLore.java diff --git a/src/com/sucy/skill/cmd/CmdMana.java b/src/main/java/com/sucy/skill/cmd/CmdMana.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdMana.java rename to src/main/java/com/sucy/skill/cmd/CmdMana.java index 9254d8e2..b0797bce 100644 --- a/src/com/sucy/skill/cmd/CmdMana.java +++ b/src/main/java/com/sucy/skill/cmd/CmdMana.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -75,7 +76,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender else if (args.length >= 1 && (args.length >= 2 || sender instanceof Player)) { // Get the player data - OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdOptions.java b/src/main/java/com/sucy/skill/cmd/CmdOptions.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdOptions.java rename to src/main/java/com/sucy/skill/cmd/CmdOptions.java diff --git a/src/com/sucy/skill/cmd/CmdPoints.java b/src/main/java/com/sucy/skill/cmd/CmdPoints.java similarity index 98% rename from src/com/sucy/skill/cmd/CmdPoints.java rename to src/main/java/com/sucy/skill/cmd/CmdPoints.java index 11248256..f5f3ce0d 100644 --- a/src/com/sucy/skill/cmd/CmdPoints.java +++ b/src/main/java/com/sucy/skill/cmd/CmdPoints.java @@ -27,6 +27,7 @@ package com.sucy.skill.cmd; import com.rit.sucy.commands.CommandManager; +import org.bukkit.Bukkit; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.IFunction; import com.rit.sucy.config.Filter; @@ -74,7 +75,7 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender else if (args.length >= 1 && (args.length >= 2 || sender instanceof Player)) { // Get the player data - OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : VersionManager.getOfflinePlayer(args[0], false); + OfflinePlayer target = args.length == 1 ? (OfflinePlayer) sender : Bukkit.getOfflinePlayer(args[0]); if (target == null) { cmd.sendMessage(sender, NOT_PLAYER, ChatColor.RED + "That is not a valid player name"); diff --git a/src/com/sucy/skill/cmd/CmdProfess.java b/src/main/java/com/sucy/skill/cmd/CmdProfess.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdProfess.java rename to src/main/java/com/sucy/skill/cmd/CmdProfess.java diff --git a/src/com/sucy/skill/cmd/CmdRefund.java b/src/main/java/com/sucy/skill/cmd/CmdRefund.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdRefund.java rename to src/main/java/com/sucy/skill/cmd/CmdRefund.java diff --git a/src/com/sucy/skill/cmd/CmdReload.java b/src/main/java/com/sucy/skill/cmd/CmdReload.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdReload.java rename to src/main/java/com/sucy/skill/cmd/CmdReload.java diff --git a/src/com/sucy/skill/cmd/CmdReset.java b/src/main/java/com/sucy/skill/cmd/CmdReset.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdReset.java rename to src/main/java/com/sucy/skill/cmd/CmdReset.java diff --git a/src/com/sucy/skill/cmd/CmdSkill.java b/src/main/java/com/sucy/skill/cmd/CmdSkill.java similarity index 85% rename from src/com/sucy/skill/cmd/CmdSkill.java rename to src/main/java/com/sucy/skill/cmd/CmdSkill.java index 88ecd50d..5d95a492 100644 --- a/src/com/sucy/skill/cmd/CmdSkill.java +++ b/src/main/java/com/sucy/skill/cmd/CmdSkill.java @@ -32,6 +32,8 @@ import com.sucy.skill.SkillAPI; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.gui.map.Menu; + +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.CommandSender; @@ -70,12 +72,20 @@ public void execute(ConfigurableCommand cmd, Plugin plugin, CommandSender sender // Only plays have skills to view else if (sender instanceof Player) { - Player p = (Player) sender; - PlayerData data = SkillAPI.getPlayerData(p); - if (!data.showSkills(p)) - { - cmd.sendMessage(sender, NO_SKILLS, ChatColor.RED + "You have no skills to view"); - } + try { + Player p = (Player) sender; + PlayerData data = SkillAPI.getPlayerData(p); + if (SkillAPI.debug) { + Bukkit.getLogger().info("[SkillAPI Debug] /skills 1"); + } + if (!data.showSkills(p)) + { + cmd.sendMessage(sender, NO_SKILLS, ChatColor.RED + "You have no skills to view"); + } + } + catch (Exception e) { + e.printStackTrace(); + } } // Console doesn't have profession options diff --git a/src/com/sucy/skill/cmd/CmdSkillMap.java b/src/main/java/com/sucy/skill/cmd/CmdSkillMap.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdSkillMap.java rename to src/main/java/com/sucy/skill/cmd/CmdSkillMap.java diff --git a/src/com/sucy/skill/cmd/CmdSwitch.java b/src/main/java/com/sucy/skill/cmd/CmdSwitch.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdSwitch.java rename to src/main/java/com/sucy/skill/cmd/CmdSwitch.java diff --git a/src/main/java/com/sucy/skill/cmd/CmdToggleBar.java b/src/main/java/com/sucy/skill/cmd/CmdToggleBar.java new file mode 100644 index 00000000..2d27db5e --- /dev/null +++ b/src/main/java/com/sucy/skill/cmd/CmdToggleBar.java @@ -0,0 +1,44 @@ +package com.sucy.skill.cmd; + +import com.rit.sucy.commands.ConfigurableCommand; +import com.rit.sucy.commands.IFunction; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.api.player.PlayerSkillBar; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class CmdToggleBar implements IFunction { + + private static final String TOGGLE_ON = "toggle-on"; + private static final String TOGGLE_OFF = "toggle-off"; + + @Override + public void execute(final ConfigurableCommand cmd, final Plugin plugin, final CommandSender sender, final String[] args) { + SkillAPI api = (SkillAPI) plugin; + boolean enabled = api.isSkillBarsEnabled(); + api.setSkillBarsEnabled(!enabled); + + String key = enabled ? TOGGLE_OFF : TOGGLE_ON; + cmd.sendMessage(sender, key, "Toggled"); + + // If true means we are disabling it, thus disabling all online players on enabled worlds + if (enabled) { + for (World world : Bukkit.getWorlds()) { + if (!SkillAPI.getSettings().isWorldEnabled(world)) + continue; + for (Player online : world.getPlayers()) { + PlayerData data = SkillAPI.getPlayerData(online); + if (!data.hasClass()) + continue; + PlayerSkillBar bar = data.getSkillBar(); + if (bar.isEnabled()) + bar.toggleEnabled(); + } + } + } + } +} \ No newline at end of file diff --git a/src/com/sucy/skill/cmd/CmdUnbind.java b/src/main/java/com/sucy/skill/cmd/CmdUnbind.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdUnbind.java rename to src/main/java/com/sucy/skill/cmd/CmdUnbind.java diff --git a/src/com/sucy/skill/cmd/CmdWorld.java b/src/main/java/com/sucy/skill/cmd/CmdWorld.java similarity index 100% rename from src/com/sucy/skill/cmd/CmdWorld.java rename to src/main/java/com/sucy/skill/cmd/CmdWorld.java diff --git a/src/com/sucy/skill/data/Click.java b/src/main/java/com/sucy/skill/data/Click.java similarity index 100% rename from src/com/sucy/skill/data/Click.java rename to src/main/java/com/sucy/skill/data/Click.java diff --git a/src/com/sucy/skill/data/ExpFormula.java b/src/main/java/com/sucy/skill/data/ExpFormula.java similarity index 100% rename from src/com/sucy/skill/data/ExpFormula.java rename to src/main/java/com/sucy/skill/data/ExpFormula.java diff --git a/src/com/sucy/skill/data/GroupSettings.java b/src/main/java/com/sucy/skill/data/GroupSettings.java similarity index 100% rename from src/com/sucy/skill/data/GroupSettings.java rename to src/main/java/com/sucy/skill/data/GroupSettings.java diff --git a/src/com/sucy/skill/data/Permissions.java b/src/main/java/com/sucy/skill/data/Permissions.java similarity index 100% rename from src/com/sucy/skill/data/Permissions.java rename to src/main/java/com/sucy/skill/data/Permissions.java diff --git a/src/com/sucy/skill/data/PlayerEquips.java b/src/main/java/com/sucy/skill/data/PlayerEquips.java similarity index 86% rename from src/com/sucy/skill/data/PlayerEquips.java rename to src/main/java/com/sucy/skill/data/PlayerEquips.java index 7114d795..5084cd97 100644 --- a/src/com/sucy/skill/data/PlayerEquips.java +++ b/src/main/java/com/sucy/skill/data/PlayerEquips.java @@ -33,11 +33,14 @@ import com.sucy.skill.api.player.PlayerClass; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.listener.MainListener; + import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import de.tr7zw.nbtapi.NBTItem; import java.util.Arrays; import java.util.HashMap; @@ -46,6 +49,9 @@ import java.util.Map; import java.util.Set; +import me.neoblade298.neocore.bukkit.NeoCore; +import me.neoblade298.neocore.bukkit.InstanceType; + import static com.sucy.skill.listener.ItemListener.ARMOR_TYPES; /** @@ -73,8 +79,9 @@ public PlayerEquips(PlayerData player) other = new EquipData[SkillAPI.getSettings().getSlots().length]; for (int i = 0; i < other.length; i++) { other[i] = empty; - if (SkillAPI.getSettings().getSlots()[i] == 40) + if (SkillAPI.getSettings().getSlots()[i] == 40) { offhand = i; + } } } @@ -100,8 +107,9 @@ public void update(Player player) { PlayerInventory inv = player.getInventory(); weapon = swap(inv, inv.getHeldItemSlot(), weapon, true); - for (int i = 0; i < other.length; i++) + for (int i = 0; i < other.length; i++) { other[i] = swap(inv, SkillAPI.getSettings().getSlots()[i], other[i], i == offhand); + } } /** @@ -116,19 +124,24 @@ public void update(Player player) private EquipData swap(PlayerInventory inv, int index, EquipData from, boolean weapon) { EquipData to = make(inv.getItem(index)); + // No change if (Objects.equal(from.item, to.item)) { return to; } + // Old item gave attributes, new one doesn't if (from.isMet() && (!weapon || !from.isArmor)) { from.revert(); } + // New item is an armor in the weapon slot if (weapon && to.isArmor) { return to; } - else if (!to.isMet()) + + // New item can't be equipped because of requirements + else if (!to.isMet() && !MainListener.loadingPlayers.contains(player.getUUID())) { if (SkillAPI.getSettings().isDropWeapon() || !weapon) { inv.setItem(index, TEMP); @@ -145,6 +158,12 @@ else if (!to.isMet()) return to; } } + + public void swapOffhand() { + EquipData temp = weapon; + weapon = other[offhand]; + other[offhand] = temp; + } private boolean isArmor(final ItemStack item) { return item != null && ARMOR_TYPES.contains(item.getType()); @@ -180,10 +199,12 @@ public void updateWeapon(PlayerInventory inv) */ private EquipData make(ItemStack item) { - if (item == null) + if (item == null) { return empty; - else + } + else { return new EquipData(item); + } } /** @@ -279,7 +300,8 @@ else if (lower.startsWith(excludeText)) { } // Attribute requirements - if (attributes && !done) + NBTItem nbti = new NBTItem(item); + if (attributes && !done && nbti.hasKey("gear")) { for (String attr : SkillAPI.getAttributeManager().getLookupKeys()) { @@ -295,14 +317,20 @@ else if (lower.startsWith(excludeText)) { } text = settings.getAttrGiveText(attr); - if (lower.startsWith(text)) + if (lower.contains(text)) { if (attribs == null) attribs = new HashMap<>(); String normalized = SkillAPI.getAttributeManager().normalize(attr); int current = attribs.containsKey(attr) ? attribs.get(attr) : 0; - int extra = NumberParser.parseInt(lower.substring(text.length()).replace("%", "")); + + int index = lower.indexOf('+'); + if (index == -1) { + index = lower.indexOf('-'); + } + lower = lower.substring(index); + int extra = Integer.parseInt(lower.replaceAll("[^0-9-]", "")); attribs.put(normalized, current + extra); break; } @@ -349,6 +377,12 @@ boolean isMet() PlayerClass main = player.getMainClass(); String className = main == null ? "null" : main.getData().getName().toLowerCase(); + + // Special to instances, all equipment is safe on id 13 (spectator account) + if (NeoCore.getInstanceType() == InstanceType.SESSIONS && + SkillAPI.getPlayerAccountData(player.getPlayer()).getActiveId() == 13) { + return true; + } if ((levelReq > 0 && (main == null || main.getLevel() < levelReq)) || (classExc != null && main != null && classExc.contains(className)) || (classReq != null && (main == null || !classReq.contains(className)))) @@ -400,5 +434,18 @@ private boolean matches(final Set names, final PlayerClass playerClass) return false; } + + @Override + public String toString() { + if (this.item == null) { + return "null"; + } + else if (this.item.hasItemMeta()) { + return this.item.getItemMeta().getDisplayName(); + } + else { + return this.item.getType().toString(); + } + } } } diff --git a/src/com/sucy/skill/data/PlayerSettings.java b/src/main/java/com/sucy/skill/data/PlayerSettings.java similarity index 100% rename from src/com/sucy/skill/data/PlayerSettings.java rename to src/main/java/com/sucy/skill/data/PlayerSettings.java diff --git a/src/com/sucy/skill/data/PlayerStats.java b/src/main/java/com/sucy/skill/data/PlayerStats.java similarity index 100% rename from src/com/sucy/skill/data/PlayerStats.java rename to src/main/java/com/sucy/skill/data/PlayerStats.java diff --git a/src/com/sucy/skill/data/Point2D.java b/src/main/java/com/sucy/skill/data/Point2D.java similarity index 100% rename from src/com/sucy/skill/data/Point2D.java rename to src/main/java/com/sucy/skill/data/Point2D.java diff --git a/src/com/sucy/skill/data/Point3D.java b/src/main/java/com/sucy/skill/data/Point3D.java similarity index 100% rename from src/com/sucy/skill/data/Point3D.java rename to src/main/java/com/sucy/skill/data/Point3D.java diff --git a/src/com/sucy/skill/data/Settings.java b/src/main/java/com/sucy/skill/data/Settings.java similarity index 95% rename from src/com/sucy/skill/data/Settings.java rename to src/main/java/com/sucy/skill/data/Settings.java index 790ca1e0..5f320dcf 100644 --- a/src/com/sucy/skill/data/Settings.java +++ b/src/main/java/com/sucy/skill/data/Settings.java @@ -1,1639 +1,1677 @@ -/** - * SkillAPI - * com.sucy.skill.data.Settings - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.data; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.rit.sucy.config.CommentedConfig; -import com.rit.sucy.config.parse.DataSection; -import com.rit.sucy.config.parse.NumberParser; -import com.rit.sucy.text.TextFormatter; -import com.rit.sucy.version.VersionManager; -import com.sucy.party.Parties; -import com.sucy.party.Party; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.CombatProtection; -import com.sucy.skill.api.DefaultCombatProtection; -import com.sucy.skill.api.player.PlayerClass; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.cast.IndicatorSettings; -import com.sucy.skill.data.formula.Formula; -import com.sucy.skill.data.formula.value.CustomValue; -import com.sucy.skill.dynamic.DynamicSkill; -import com.sucy.skill.gui.tool.GUITool; -import com.sucy.skill.log.Logger; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.Animals; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Monster; -import org.bukkit.entity.Player; -import org.bukkit.entity.Tameable; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.MaterialData; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - *

The management class for SkillAPI's config.yml settings.

- */ -public class Settings { - - private HashMap groups = new HashMap(); - - private SkillAPI plugin; - private DataSection config; - - /** - *

Initializes a new settings manager.

- *

This is already set up by SkillAPI and shouldn't be - * instantiated elsewhere. Instead, get it from SkillAPI - * using the SkillAPI.getSettings() method.

- * - * @param plugin SkillAPI plugin reference - */ - public Settings(SkillAPI plugin) { - this.plugin = plugin; - CommentedConfig file = new CommentedConfig(plugin, "config"); - file.checkDefaults(); - file.save(); - config = file.getConfig(); - reload(); - } - - /** - *

Reloads the settings from SkillAPI's config.yml file.

- *

This will fill in any missing values with default values - * and trim any values that aren't supposed to be there.

- */ - public void reload() { - loadExperienceSettings(); - loadAccountSettings(); - loadClassSettings(); - loadManaSettings(); - loadSkillSettings(); - loadItemSettings(); - loadGUISettings(); - loadCastSettings(); - loadComboSettings(); - loadExpSettings(); - loadSkillBarSettings(); - loadLoggingSettings(); - loadWorldSettings(); - loadSaveSettings(); - loadTargetingSettings(); - loadWorldGuardSettings(); - } - - /////////////////////////////////////////////////////// - // // - // Experience Settings // - // // - /////////////////////////////////////////////////////// - - private static final String DEFAULT_YIELD = "default"; - - private Map> breakYields; - private Map> placeYields; - private Map> craftYields; - - private boolean trackBreak; - private boolean yieldsEnabled; - - public void loadExperienceSettings() { - CommentedConfig file = new CommentedConfig(plugin, "exp"); - file.checkDefaults(); - file.save(); - DataSection config = file.getConfig(); - - DataSection breakData = config.getSection("break"); - yieldsEnabled = config.getBoolean("enabled", false); - trackBreak = breakData.getBoolean("allow-replace", true); - breakYields = loadYields(breakData.getSection("types")); - placeYields = loadYields(config.getSection("place")); - craftYields = loadYields(config.getSection("craft")); - } - - private Map> loadYields(DataSection config) { - Map> yields = new HashMap>(); - for (String className : config.keys()) { - HashMap map = new HashMap(); - DataSection classYields = config.getSection(className); - for (String type : classYields.keys()) { - map.put(type.toUpperCase().replace(" ", "_"), classYields.getDouble(type)); - } - yields.put(className, map); - } - return yields; - } - - public boolean trackBreaks() { - return trackBreak; - } - - public boolean yieldsEnabled() { - return yieldsEnabled; - } - - public double getBreakYield(PlayerClass playerClass, Material mat) { - return getYield(breakYields, playerClass, mat.name()); - } - - public double getPlaceYield(PlayerClass playerClass, Material mat) { - return getYield(placeYields, playerClass, mat.name()); - } - - public double getCraftYield(PlayerClass playerClass, Material mat) { - return getYield(craftYields, playerClass, mat.name()); - } - - private double getYield(Map> yields, PlayerClass playerClass, String key) { - double yield = getYield(yields.get(playerClass.getData().getName()), key); - return yield > 0 ? yield : getYield(yields.get(DEFAULT_YIELD), key); - } - - private double getYield(Map yields, String key) { - return yields == null ? 0 : (yields.containsKey(key) ? yields.get(key) : 0); - } - - /////////////////////////////////////////////////////// - // // - // Group Settings // - // // - /////////////////////////////////////////////////////// - - public void loadGroupSettings() { - CommentedConfig file = new CommentedConfig(plugin, "groups"); - DataSection config = file.getConfig(); - groups.clear(); - - for (String key : config.keys()) { - groups.put(key.toLowerCase(), new GroupSettings(config.getSection(key))); - } - for (String group : SkillAPI.getGroups()) { - if (!groups.containsKey(group.toLowerCase())) { - GroupSettings settings = new GroupSettings(); - groups.put(group.toLowerCase(), settings); - settings.save(config.createSection(group.toLowerCase())); - } - config.setComments(group.toLowerCase(), ImmutableList.of( - "", - " Settings for classes with the group " + group, - " If new classes are loaded with different groups,", - " the new groups will show up in this file after the first load.")); - } - - file.save(); - } - - /** - * Retrieves the settings for a class group - * - * @param group name of the group to retrieve the settings for - * - * @return settings for the class group - */ - public GroupSettings getGroupSettings(String group) { - if (!groups.containsKey(group.toLowerCase())) { - return new GroupSettings(); - } - return groups.get(group.toLowerCase()); - } - - /////////////////////////////////////////////////////// - // // - // Account Settings // - // // - /////////////////////////////////////////////////////// - - private static final String ACCOUNT_BASE = "Accounts."; - private static final String ACCOUNT_MAIN = ACCOUNT_BASE + "main-class-group"; - private static final String ACCOUNT_EACH = ACCOUNT_BASE + "one-per-class"; - private static final String ACCOUNT_MAX = ACCOUNT_BASE + "max-accounts"; - private static final String ACCOUNT_PERM = ACCOUNT_BASE + "perm-accounts"; - - private String mainGroup; - private boolean onePerClass; - private int maxAccounts; - - private HashMap permAccounts = new HashMap(); - - /** - * Retrieves the main class group for displaying prefixes - * or showing account information - * - * @return main class group - */ - public String getMainGroup() { - return mainGroup; - } - - /** - * Retrieves whether or not accounts should be initialized with - * one file per class. - * - * @return true if enabled, false otherwise - */ - public boolean isOnePerClass() { - return onePerClass; - } - - /** - * Retrieves the max accounts allowed for most players - * - * @return max accounts allowed for most players - */ - public int getMaxAccounts() { - return maxAccounts; - } - - /** - * Retrieves the max amount of accounts allowed for a specific player - * by checking permissions for additional accounts. - * - * @param player player to check the max allowed accounts for - * - * @return number of allowed accounts - */ - public int getMaxAccounts(Player player) { - if (player == null) { - return maxAccounts; - } - int max = maxAccounts; - for (Map.Entry entry : permAccounts.entrySet()) { - if (player.hasPermission(entry.getKey())) { - max = Math.max(max, entry.getValue()); - } - } - return max; - } - - private void loadAccountSettings() { - mainGroup = config.getString(ACCOUNT_MAIN); - onePerClass = config.getBoolean(ACCOUNT_EACH); - maxAccounts = config.getInt(ACCOUNT_MAX); - - // Permission account amounts - List list = config.getList(ACCOUNT_PERM); - for (String item : list) { - if (!item.contains(":")) { - continue; - } - - String[] pieces = item.split(":"); - if (pieces.length != 2) { - continue; - } - - try { - permAccounts.put(pieces[0], Integer.parseInt(pieces[1])); - } catch (Exception ex) { - // Invalid setting value - } - } - } - - /////////////////////////////////////////////////////// - // // - // Targeting Settings // - // // - /////////////////////////////////////////////////////// - - private static final String TARGET_BASE = "Targeting."; - private static final String TARGET_MONSTER = TARGET_BASE + "monsters-enemy"; - private static final String TARGET_PASSIVE = TARGET_BASE + "passive-ally"; - private static final String TARGET_PLAYER = TARGET_BASE + "player-ally"; - private static final String TARGET_PARTIES = TARGET_BASE + "parties-ally"; - private static final String TARGET_NPC = TARGET_BASE + "affect-npcs"; - private static final String TARGET_STANDS = TARGET_BASE + "affect-armor-stands"; - - private ArrayList monsterWorlds = new ArrayList(); - private ArrayList passiveWorlds = new ArrayList(); - private ArrayList playerWorlds = new ArrayList(); - - private boolean monsterEnemy; - private boolean passiveAlly; - private boolean playerAlly; - private boolean partiesAlly; - private boolean affectNpcs; - private boolean affectArmorStands; - - private CombatProtection combatProtection = new DefaultCombatProtection(); - - /** - * Checks whether or not something can be attacked - * - * @param attacker the attacking entity - * @param target the target entity - * - * @return true if can be attacked, false otherwise - */ - public boolean canAttack(LivingEntity attacker, LivingEntity target) { - if (attacker instanceof Player) { - final Player player = (Player) attacker; - if (target instanceof Animals && !(target instanceof Tameable)) { - if (passiveAlly || passiveWorlds.contains(attacker.getWorld().getName())) { return false; } - } else if (target instanceof Monster) { - if (monsterEnemy || monsterWorlds.contains(attacker.getWorld().getName())) { return true; } - } else if (target instanceof Player) { - if (playerAlly || playerWorlds.contains(attacker.getWorld().getName())) { return false; } - - if (partiesAlly) { - final Parties parties = Parties.getPlugin(Parties.class); - final Party p1 = parties.getJoinedParty(player); - final Party p2 = parties.getJoinedParty((Player) target); - return p1 == null || p1 != p2; - } - return combatProtection.canAttack(player, (Player) target); - } - return combatProtection.canAttack(player, target); - } else if (attacker instanceof Tameable) { - Tameable tameable = (Tameable) attacker; - if (tameable.isTamed() && (tameable.getOwner() instanceof LivingEntity)) { - return (tameable.getOwner() != target) - && canAttack((LivingEntity) tameable.getOwner(), target); - } - } else { return !(target instanceof Monster); } - - return combatProtection.canAttack(attacker, target); - } - - /** - * Checks whether or not something is an ally - * - * @param attacker the attacking entity - * @param target the target entity - * - * @return true if an ally, false otherwise - */ - public boolean isAlly(LivingEntity attacker, LivingEntity target) { - return !canAttack(attacker, target); - } - - /** - * Checks whether or not a target is a valid target. - * - * @param target target to check - * @return true if a valid target, false otherwise - */ - public boolean isValidTarget(final LivingEntity target) { - return (!target.hasMetadata("NPC") || affectNpcs) - && (!target.getType().name().equals("ARMOR_STAND") || affectArmorStands); - } - - /** - * Swaps out the default combat protection for a custom one - * - * @param combatProtection combat protection to use - */ - public void setCombatProtection(final CombatProtection combatProtection) { - this.combatProtection = combatProtection; - } - - private void loadTargetingSettings() { - if (config.isList(TARGET_MONSTER)) { - monsterWorlds.addAll(config.getList(TARGET_MONSTER)); - monsterEnemy = false; - } else { monsterEnemy = config.getBoolean(TARGET_MONSTER); } - - if (config.isList(TARGET_PASSIVE)) { - passiveWorlds.addAll(config.getList(TARGET_PASSIVE)); - passiveAlly = false; - } else { passiveAlly = config.getBoolean(TARGET_PASSIVE); } - - if (config.isList(TARGET_PLAYER)) { - playerWorlds.addAll(config.getList(TARGET_PLAYER)); - playerAlly = false; - } else { playerAlly = config.getBoolean(TARGET_PLAYER); } - - partiesAlly = config.getBoolean(TARGET_PARTIES); - affectArmorStands = config.getBoolean(TARGET_STANDS); - affectNpcs = config.getBoolean(TARGET_NPC); - } - - /////////////////////////////////////////////////////// - // // - // Saving Settings // - // // - /////////////////////////////////////////////////////// - - private static final String SAVE_BASE = "Saving."; - private static final String SAVE_AUTO = SAVE_BASE + "auto-save"; - private static final String SAVE_MINS = SAVE_BASE + "minutes"; - private static final String SAVE_SQL = SAVE_BASE + "sql-database"; - private static final String SAVE_SQLD = SAVE_BASE + "sql-details"; - - private boolean auto; - private boolean useSql; - private int minutes; - private int sqlDelay; - - private String sqlHost; - private String sqlPort; - private String sqlDatabase; - private String sqlUser; - private String sqlPass; - - /** - * Checks whether or not auto saving is enabled - * - * @return true if enabled, false otherwise - */ - public boolean isAutoSave() { - return auto; - } - - /** - * Retrieves the amount of ticks in between each auto save - * - * @return frequency of saves - */ - public int getSaveFreq() { - return minutes * 60 * 20; - } - - /** - * Checks whether or not the plugin is using SQL Database saving - * - * @return true if enabled, false otherwise - */ - public boolean isUseSql() { - return useSql; - } - - /** - * Retrieves the host IP for the database - * - * @return host IP for SQL database - */ - public String getSQLHost() { - return sqlHost; - } - - /** - * Retrieves the host port for the database - * - * @return host port for SQL database - */ - public String getSQLPort() { - return sqlPort; - } - - /** - * Retrieves the name of the SQL database - * - * @return SQL database name - */ - public String getSQLDatabase() { - return sqlDatabase; - } - - /** - * Retrieves the username for the database credentials - * - * @return SQL database username - */ - public String getSQLUser() { - return sqlUser; - } - - /** - * Retrieves the password for the database credentials - * - * @return SQL database password - */ - public String getSQLPass() { - return sqlPass; - } - - /** - * @return time in milliseconds to wait before loading SQL data - */ - public int getSqlDelay() { - return sqlDelay; - } - - private void loadSaveSettings() { - auto = config.getBoolean(SAVE_AUTO); - minutes = config.getInt(SAVE_MINS); - useSql = config.getBoolean(SAVE_SQL); - - if (useSql) { - DataSection details = config.getSection(SAVE_SQLD); - sqlHost = details.getString("host"); - sqlPort = details.getString("port"); - sqlDatabase = details.getString("database"); - sqlUser = details.getString("username"); - sqlPass = details.getString("password"); - sqlDelay = details.getInt("delay"); - } - } - - /////////////////////////////////////////////////////// - // // - // Class Settings // - // // - /////////////////////////////////////////////////////// - - private static final String CLASS_BASE = "Classes."; - private static final String CLASS_MODIFY = CLASS_BASE + "modify-health"; - private static final String CLASS_HP = CLASS_BASE + "classless-hp"; - private static final String CLASS_SHOW = CLASS_BASE + "show-auto-skills"; - private static final String CLASS_ATTRIB = CLASS_BASE + "attributes-enabled"; - private static final String CLASS_REFUND = CLASS_BASE + "attributes-downgrade"; - private static final String CLASS_LEVEL = CLASS_BASE + "level-up-skill"; - - private boolean modifyHealth; - private int defaultHealth; - private boolean showAutoSkills; - private boolean attributesEnabled; - private boolean attributesDowngrade; - private String levelUpSkill; - - /** - * Checks whether or not SkillAPI should modify the max health of players - * - * @return true if enabled, false otherwise - */ - public boolean isModifyHealth() { - return modifyHealth; - } - - /** - *

Retrieves the default health for players that do not have a class.

- * - * @return default health for classless players - */ - public int getDefaultHealth() { - return defaultHealth; - } - - /** - * Checks whether or not auto-leveled skills are to be shown. - * - * @return true if shown, false otherwise - */ - public boolean isShowingAutoSkills() { - return showAutoSkills; - } - - /** - * Checks whether or not attributes are enabled - * - * @return true if enabled, false otherwise - */ - public boolean isAttributesEnabled() { - return attributesEnabled; - } - - /** - * Checks whether or not attribute points can be refunded - * - * @return true if can refund, false otherwise - */ - public boolean isAttributesDowngrade() { - return attributesDowngrade; - } - - /** - * Checks whether or not the plugin has a valid skill for - * level up effects loaded. - * - * @return true if one is available, false otherwise - */ - public boolean hasLevelUpEffect() { - return getLevelUpSkill() != null; - } - - /** - * Retrieves the skill used for level up effects - * - * @return skill for level up effects - */ - public DynamicSkill getLevelUpSkill() { - Skill skill = SkillAPI.getSkill(levelUpSkill); - return (skill instanceof DynamicSkill) ? (DynamicSkill) skill : null; - } - - private void loadClassSettings() { - modifyHealth = config.getBoolean(CLASS_MODIFY); - defaultHealth = config.getInt(CLASS_HP); - showAutoSkills = config.getBoolean(CLASS_SHOW); - attributesEnabled = config.getBoolean(CLASS_ATTRIB); - attributesDowngrade = config.getBoolean(CLASS_REFUND); - levelUpSkill = config.getString(CLASS_LEVEL); - } - - /////////////////////////////////////////////////////// - // // - // Mana Settings // - // // - /////////////////////////////////////////////////////// - - private static final String MANA_BASE = "Mana."; - private static final String MANA_ENABLED = MANA_BASE + "enabled"; - private static final String MANA_FREQ = MANA_BASE + "freq"; - - private boolean manaEnabled; - private int gainFreq; - - /** - * Checks whether or not mana is enabled - * - * @return true if enabled, false otherwise - */ - public boolean isManaEnabled() { - return manaEnabled; - } - - /** - * Retrieves the frequency of mana gain - * - * @return the frequency of mana gain - */ - public int getGainFreq() { - return gainFreq; - } - - private void loadManaSettings() { - manaEnabled = config.getBoolean(MANA_ENABLED); - gainFreq = (int) (config.getDouble(MANA_FREQ) * 20); - } - - /////////////////////////////////////////////////////// - // // - // Skill Settings // - // // - /////////////////////////////////////////////////////// - - private static final String SKILL_BASE = "Skills."; - private static final String SKILL_DOWNGRADE = SKILL_BASE + "allow-downgrade"; - private static final String SKILL_MESSAGE = SKILL_BASE + "show-messages"; - private static final String SKILL_RADIUS = SKILL_BASE + "message-radius"; - private static final String SKILL_BLOCKS = SKILL_BASE + "block-filter"; - private static final String SKILL_KNOCKBACK = SKILL_BASE + "knockback-no-damage"; - - private ArrayList filteredBlocks; - - private boolean allowDowngrade; - private boolean showSkillMessages; - private boolean knockback; - private int messageRadius; - - /** - * Checks whether or not downgrades are allowed - * - * @return true if allowed, false otherwise - */ - public boolean isAllowDowngrade() { - return allowDowngrade; - } - - /** - * Checks whether or not skill messages are enabled - * - * @return true if enabled, false otherwise - */ - public boolean isShowSkillMessages() { - return showSkillMessages; - } - - /** - * @return whether or not knockback should be applied when dealing 0 damage - */ - public boolean isKnockback() { - return knockback; - } - - /** - * Gets the radius in which skill messages are sent out - * - * @return skill message radius - */ - public int getMessageRadius() { - return messageRadius; - } - - /** - * Retrieves the list of filtered blocks - * - * @return list of blocks - */ - public List getFilteredBlocks() { - return filteredBlocks; - } - - private void loadSkillSettings() { - allowDowngrade = config.getBoolean(SKILL_DOWNGRADE); - showSkillMessages = config.getBoolean(SKILL_MESSAGE); - messageRadius = config.getInt(SKILL_RADIUS); - knockback = config.getBoolean(SKILL_KNOCKBACK); - - filteredBlocks = new ArrayList(); - List list = config.getList(SKILL_BLOCKS); - for (String item : list) { - item = item.toUpperCase().replace(' ', '_'); - if (item.endsWith("*")) { - item = item.substring(0, item.length() - 1); - for (Material mat : Material.values()) { - if (mat.name().contains(item)) { - filteredBlocks.add(mat); - } - } - } else { - try { - Material mat = Material.valueOf(item); - filteredBlocks.add(mat); - } catch (Exception ex) { - Logger.invalid("Invalid block type \"" + item + "\""); - } - } - } - } - - /////////////////////////////////////////////////////// - // // - // Item Settings // - // // - /////////////////////////////////////////////////////// - - private static final String ITEM_BASE = "Items."; - private static final String ITEM_LORE = ITEM_BASE + "lore-requirements"; - private static final String ITEM_DROP = ITEM_BASE + "drop-weapon"; - private static final String ITEM_SKILLS = ITEM_BASE + "skill-requirements"; - private static final String ITEM_ATTRIBS = ITEM_BASE + "lore-attributes"; - private static final String ITEM_CLASS = ITEM_BASE + "lore-class-text"; - private static final String ITEM_SKILL = ITEM_BASE + "lore-skill-text"; - private static final String ITEM_LEVEL = ITEM_BASE + "lore-level-text"; - private static final String ITEM_EXCLUDE = ITEM_BASE + "lore-exclude-text"; - private static final String ITEM_ATTR = ITEM_BASE + "lore-attribute-text"; - private static final String ITEM_STATS = ITEM_BASE + "attribute-text"; - private static final String ITEM_SLOTS = ITEM_BASE + "slots"; - - private boolean checkLore; - private boolean checkAttribs; - private boolean checkSkills; - private boolean dropWeapon; - private String loreClassText; - private String loreLevelText; - private String loreExcludeText; - private int[] slots; - - private String skillPre, skillPost; - private String attrReqPre, attrReqPost; - private String attrPre, attrPost; - - /** - * Checks whether or not lore requirements are enabled - * - * @return true if enabled, false otherwise - */ - public boolean isCheckLore() { - return checkLore; - } - - /** - * @return true if should check for skill requirements - */ - public boolean isCheckSkillLore() { - return checkSkills; - } - - /** - * @return true if should check for attribute bonuses - */ - public boolean isCheckAttributes() { - return checkAttribs; - } - - /** - * @return checks if weapons are dropped when hovered - */ - public boolean isDropWeapon() { - return dropWeapon; - } - - /** - * @return lore for skill requirements - */ - public String getSkillText(String skill) { - return skillPre + skill + skillPost; - } - - /** - * Retrieves the text used for class requirements on items - * - * @return lore text for class requirements - */ - public String getLoreClassText() { - return loreClassText; - } - - /** - * Retrieves the text used for level requirements on items - * - * @return lore text for level requirements - */ - public String getLoreLevelText() { - return loreLevelText; - } - - /** - * Retrieves the text used for excluded classes on items - * - * @return lore text for excluded classes - */ - public String getLoreExcludeText() { - return loreExcludeText; - } - - /** - * Retrieves the text used for attribute requirements on items - * - * @return lore text for attributes - */ - public String getAttrReqText(String attr) { - return attrReqPre + attr + attrReqPost; - } - - /** - * @return lore text for giving attributes - */ - public String getAttrGiveText(String attr) { - return attrPre + attr + attrPost; - } - - /** - * @return slots checked for requirements and attributes - */ - public int[] getSlots() { - return slots; - } - - private void loadItemSettings() { - checkLore = config.getBoolean(ITEM_LORE); - dropWeapon = config.getBoolean(ITEM_DROP); - checkSkills = config.getBoolean(ITEM_SKILLS); - checkAttribs = config.getBoolean(ITEM_ATTRIBS); - loreClassText = config.getString(ITEM_CLASS).toLowerCase(); - loreLevelText = config.getString(ITEM_LEVEL).toLowerCase(); - loreExcludeText = config.getString(ITEM_EXCLUDE).toLowerCase(); - - String temp = config.getString(ITEM_SKILL).toLowerCase(); - int index = temp.indexOf('{'); - skillPre = temp.substring(0, index); - skillPost = temp.substring(index + 7); - - temp = config.getString(ITEM_ATTR).toLowerCase(); - index = temp.indexOf('{'); - attrReqPre = temp.substring(0, index); - attrReqPost = temp.substring(index + 6); - - temp = config.getString(ITEM_STATS).toLowerCase(); - index = temp.indexOf('{'); - attrPre = temp.substring(0, index); - attrPost = temp.substring(index + 6); - - List slotList = config.getList(ITEM_SLOTS); - if (!VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { slotList.remove("40"); } - slots = new int[slotList.size()]; - for (int i = 0; i < slots.length; i++) { slots[i] = NumberParser.parseInt(slotList.get(i)); } - } - - /////////////////////////////////////////////////////// - // // - // GUI Settings // - // // - /////////////////////////////////////////////////////// - - private static final String - GUI_BASE = "GUI.", - GUI_OLD = GUI_BASE + "old-health-bar", - GUI_FORCE = GUI_BASE + "force-scaling", - GUI_LVLBAR = GUI_BASE + "level-bar", - GUI_FOOD = GUI_BASE + "food-bar", - GUI_ACTION = GUI_BASE + "use-action-bar", - GUI_TEXT = GUI_BASE + "action-bar-text", - GUI_BOARD = GUI_BASE + "scoreboard-enabled", - GUI_NAME = GUI_BASE + "show-class-name", - GUI_LEVEL = GUI_BASE + "show-class-level", - GUI_BINDS = GUI_BASE + "show-binds", - GUI_BIND_TEXT = GUI_BASE + "show-bind-text", - GUI_LVLTXT = GUI_BASE + "class-level-text", - GUI_TITLE = GUI_BASE + "title-enabled", - GUI_DUR = GUI_BASE + "title-duration", - GUI_FADEI = GUI_BASE + "title-fade-in", - GUI_FADEO = GUI_BASE + "title-fade-out", - GUI_LIST = GUI_BASE + "title-messages"; - - private List titleMessages; - - private boolean oldHealth; - private boolean forceScaling; - private String levelBar; - private String foodBar; - private String levelText; - private boolean useActionBar; - private String actionText; - private boolean showScoreboard; - private boolean showClassName; - private boolean showClassLevel; - private boolean showBinds; - private String bindText; - private boolean useTitle; - private int titleDuration; - private int titleFadeIn; - private int titleFadeOut; - - /** - * Checks whether or not old health bars (fixed 10 hearts) are enabled - * - * @return true if enabled, false otherwise - */ - public boolean isOldHealth() { - return oldHealth; - } - - /** - * @return true if forces the SkillAPI health scaling, false otherwise - */ - public boolean isForceScaling() { - return forceScaling; - } - - /** - * Gets the setting for using the level bar - * - * @return level bar setting - */ - public String getLevelBar() { - return levelBar; - } - - /** - * Gets the setting for using the food bar - * - * @return food bar setting - */ - public String getFoodBar() { - return foodBar; - } - - /** - * Checks whether or not the action bar is being used - * - * @return true if used, false otherwise - */ - public boolean isUseActionBar() { - return useActionBar; - } - - /** - * Gets the text to display on the action bar - * - * @return action bar text - */ - public String getActionText() { - return actionText; - } - - /** - * Checks whether or not the stats scoreboard is to be shown - * - * @return true if shown, false otherwise - */ - public boolean isShowScoreboard() { - return showScoreboard; - } - - /** - * Checks whether or not a player's class name is to be - * shown next to their name - * - * @return true if shown, false otherwise - */ - public boolean isShowClassName() { - return showClassName; - } - - /** - * Checks whether or not a player's class level is to be - * shown below their name - * - * @return true if shown, false otherwise - */ - public boolean isShowClassLevel() { - return showClassLevel; - } - - public boolean isShowBinds() { - return showBinds; - } - - public String getBindText() { - return bindText; - } - - /** - * @return text shown alongside the class level - */ - public String getLevelText() { - return levelText; - } - - /** - * Check whether or not to use the title display - * on the given message type - * - * @param type type of message to check for - * - * @return true if should use title display, false otherwise - */ - public boolean useTitle(TitleType type) { - return useTitle && type != null && titleMessages.contains(type.name().toLowerCase()); - } - - /** - * @return duration of the title display in ticks - */ - public int getTitleDuration() { - return titleDuration; - } - - /** - * @return fade in time of the title display in ticks - */ - public int getTitleFadeIn() { - return titleFadeIn; - } - - /** - * @return fade out time of the title display in ticks - */ - public int getTitleFadeOut() { - return titleFadeOut; - } - - private void loadGUISettings() { - oldHealth = config.getBoolean(GUI_OLD); - forceScaling = config.getBoolean(GUI_FORCE); - levelBar = config.getString(GUI_LVLBAR); - levelText = TextFormatter.colorString(config.getString(GUI_LVLTXT, "Level")); - foodBar = config.getString(GUI_FOOD); - useActionBar = config.getBoolean(GUI_ACTION); - actionText = config.getString(GUI_TEXT); - showScoreboard = config.getBoolean(GUI_BOARD); - showClassName = config.getBoolean(GUI_NAME); - showClassLevel = config.getBoolean(GUI_LEVEL); - showBinds = config.getBoolean(GUI_BINDS); - bindText = config.getString(GUI_BIND_TEXT); - useTitle = config.getBoolean(GUI_TITLE); - titleDuration = (int) (20 * config.getFloat(GUI_DUR)); - titleFadeIn = (int) (20 * config.getFloat(GUI_FADEI)); - titleFadeOut = (int) (20 * config.getFloat(GUI_FADEO)); - titleMessages = config.getList(GUI_LIST); - } - - /////////////////////////////////////////////////////// - // // - // Cast Settings // - // // - /////////////////////////////////////////////////////// - - private static final String CAST_BASE = "Casting."; - private static final String CAST_ENABLED = CAST_BASE + "enabled"; - private static final String CAST_BARS = CAST_BASE + "bars"; - private static final String CAST_COMBAT = CAST_BASE + "combat"; - private static final String CAST_INDICATOR = CAST_BASE + "cast-indicator"; - private static final String CAST_SLOT = CAST_BASE + "slot"; - private static final String CAST_ITEM = CAST_BASE + "item"; - private static final String CAST_COOLDOWN = CAST_BASE + "cooldown"; - private static final String CAST_HOVER = CAST_BASE + "hover-item"; - private static final String CAST_INSTANT = CAST_BASE + "instant-item"; - - private boolean castEnabled; - private boolean castBars; - private boolean combatEnabled; - private int castSlot; - private long castCooldown; - private ItemStack castItem; - private ItemStack hoverItem; - private ItemStack instantItem; - - /** - * @return true if default casting is enabled - */ - public boolean isCastEnabled() { - return castEnabled; - } - - /** - * @return true if using bar format, false otherwise - */ - public boolean isUsingBars() { - return castEnabled && castBars && !combatEnabled; - } - - public boolean isUsingWand() { - return castEnabled && !castBars && !combatEnabled; - } - - public boolean isUsingCombat() { - return castEnabled && combatEnabled; - } - - /** - * @return slot the cast item is stored in - */ - public int getCastSlot() { - return castSlot; - } - - /** - * @return global cooldown for casting - */ - public long getCastCooldown() { - return castCooldown; - } - - /** - * @return cast item to use in the slot - */ - public ItemStack getCastItem() { - return castItem; - } - - public ItemStack getHoverItem() { - return hoverItem; - } - - public ItemStack getInstantItem() { - return instantItem; - } - - private void loadCastSettings() { - castEnabled = config.getBoolean(CAST_ENABLED); - castBars = config.getBoolean(CAST_BARS); - combatEnabled = config.getBoolean(CAST_COMBAT); - castSlot = config.getInt(CAST_SLOT) - 1; - castCooldown = (long) (config.getDouble(CAST_COOLDOWN) * 1000); - castItem = GUITool.parseItem(config.getSection(CAST_ITEM)); - hoverItem = GUITool.parseItem(config.getSection(CAST_HOVER)); - instantItem = GUITool.parseItem(config.getSection(CAST_INSTANT)); - castEnabled = castEnabled && castItem != null; - IndicatorSettings.load(config.getSection(CAST_INDICATOR)); - } - - /////////////////////////////////////////////////////// - // // - // Click Combo Settings // - // // - /////////////////////////////////////////////////////// - - private static final String COMBO_BASE = "Click Combos."; - private static final String COMBO_ENABLED = COMBO_BASE + "enabled"; - private static final String COMBO_CUSTOM = COMBO_BASE + "allow-custom"; - private static final String COMBO_CLICK = COMBO_BASE + "use-click-"; - private static final String COMBO_SIZE = COMBO_BASE + "combo-size"; - private static final String COMBO_TIME = COMBO_BASE + "click-time"; - private static final String COMBO_AUTO = COMBO_BASE + "auto-assign"; - - private boolean[] clicks; - private boolean combosEnabled; - private boolean customCombos; - private boolean autoAssignCombos; - private int comboSize; - private int clickTime; - - /** - * Checks whether or not click combos are enabled - * - * @return true if enabled, false otherwise - */ - public boolean isCombosEnabled() { - return combosEnabled; - } - - /** - * Checks whether or not players can customize their click combos - * - * @return true if can customize them, false otherwise - */ - public boolean isCustomCombosAllowed() { - return customCombos; - } - - public boolean shouldAutoAssignCombos() { - return autoAssignCombos; - } - - /** - * @return enabled clicks as an array of booleans indexed by click ID - */ - public boolean[] getEnabledClicks() { - return clicks; - } - - /** - * Retrieves the max length of combos to be used - * - * @return max length of combos to be used - */ - public int getComboSize() { - return comboSize; - } - - /** - * Retrieves the amount of seconds allowed between clicks before the combo resets - * - * @return number of seconds before a click combo resets - */ - public int getClickTime() { - return clickTime; - } - - private void loadComboSettings() { - combosEnabled = config.getBoolean(COMBO_ENABLED); - customCombos = combosEnabled && config.getBoolean(COMBO_CUSTOM); - autoAssignCombos = combosEnabled && config.getBoolean(COMBO_AUTO, true); - comboSize = config.getInt(COMBO_SIZE); - clickTime = (int) (1000 * config.getDouble(COMBO_TIME)); - - clicks = new boolean[Click.values().length + 1]; - for (int i = 1; i <= Click.values().length; i++) { - final String key = COMBO_CLICK + Click.getById(i).name().toLowerCase().replace('_', '-'); - clicks[i] = config.getBoolean(key); - } - if (clicks[Click.RIGHT_SHIFT.getId()] || clicks[Click.LEFT_SHIFT.getId()]) { - clicks[Click.SHIFT.getId()] = false; - } - } - - /////////////////////////////////////////////////////// - // // - // Exp Settings // - // // - /////////////////////////////////////////////////////// - - private final HashMap yields = new HashMap(); - - private ExpFormula expFormula; - private Formula expCustom; - private boolean useCustomExp; - private boolean useOrbs; - private boolean blockSpawner; - private boolean blockEgg; - private boolean blockCreative; - private boolean showExpMessages; - private boolean showLevelMessages; - private boolean showLossMessages; - private Set expLostBlacklist; - - /** - * Gets the required amount of experience at a given level - * - * @param level level of the class - * - * @return required experience to gain a level - */ - public int getRequiredExp(int level) { - if (useCustomExp) { return (int) expCustom.compute(level, 0); } else { return expFormula.calculate(level); } - } - - /** - * Gets the experience yield of a mob - * - * @param mob mob to get the yield of - * - * @return experience yield - */ - public double getYield(String mob) { - mob = mob.toLowerCase(); - if (!yields.containsKey(mob)) { - return 0; - } else { - return yields.get(mob); - } - } - - /** - * Checks whether or not experience is to be gained through - * vanilla experience orbs - * - * @return true if enabled, false otherwise - */ - public boolean isUseOrbs() { - return useOrbs; - } - - /** - * Checks whether or not experience from mobs spawned - * via a mob spawner is to be blocked. - * - * @return true if blocked, false otherwise - */ - public boolean isBlockSpawner() { - return blockSpawner; - } - - /** - * Checks whether or not experience from mobs spawned - * via eggs are to be blocked - * - * @return true if blocked, false otherwise - */ - public boolean isBlockEgg() { - return blockEgg; - } - - /** - * Checks whether or not players in creative mode - * are blocked from receiving experience. - * - * @return true if blocked, false otherwise - */ - public boolean isBlockCreative() { - return blockCreative; - } - - /** - * Checks whether or not messages should - * be displayed when a player gains experience - * - * @return true if enabled, false otherwise - */ - public boolean isShowExpMessages() { - return showExpMessages; - } - - /** - * Checks whether or not messages should be displayed - * when a player gains a level - * - * @return true if enabled, false otherwise - */ - public boolean isShowLevelMessages() { - return showLevelMessages; - } - - /** - * Checks whether or not messages should be displayed - * when a player dies and loses experience - * - * @return true if enabled, false otherwise - */ - public boolean isShowLossMessages() { - return showLossMessages; - } - - /** - * @param world world a player died in - * @return true if the world is blacklisted for losing experience - */ - public boolean shouldIgnoreExpLoss(final World world) { - return expLostBlacklist.contains(world.getName()); - } - - private static final String EXP_BASE = "Experience."; - - private void loadExpSettings() { - this.useOrbs = config.getBoolean(EXP_BASE + "use-exp-orbs"); - this.blockSpawner = config.getBoolean(EXP_BASE + "block-mob-spawner"); - this.blockEgg = config.getBoolean(EXP_BASE + "block-mob-egg"); - this.blockCreative = config.getBoolean(EXP_BASE + "block-creative"); - this.showExpMessages = config.getBoolean(EXP_BASE + "exp-message-enabled"); - this.showLevelMessages = config.getBoolean(EXP_BASE + "level-message-enabled"); - this.showLossMessages = config.getBoolean(EXP_BASE + "lose-exp-message"); - this.expLostBlacklist = new HashSet<>(config.getList(EXP_BASE + "lose-exp-blacklist")); - - DataSection formula = config.getSection(EXP_BASE + "formula"); - int x = formula.getInt("x"); - int y = formula.getInt("y"); - int z = formula.getInt("z"); - expFormula = new ExpFormula(x, y, z); - - expCustom = new Formula(config.getString(EXP_BASE + "custom-formula"), new CustomValue("lvl")); - useCustomExp = config.getBoolean(EXP_BASE + "use-custom") && expCustom.isValid(); - - DataSection yields = config.getSection(EXP_BASE + "yields"); - this.yields.clear(); - for (String key : yields.keys()) { - this.yields.put(key, yields.getDouble(key)); - } - } - - /////////////////////////////////////////////////////// - // // - // Skill Bar Settings // - // // - /////////////////////////////////////////////////////// - - private boolean skillBarEnabled; - private boolean skillBarCooldowns; - private ItemStack unassigned; - private boolean[] defaultBarLayout = new boolean[9]; - private boolean[] lockedSlots = new boolean[9]; - - /** - * Checks whether or not the skill bar is enabled - * - * @return true if enabled, false otherwise - */ - public boolean isSkillBarEnabled() { - return skillBarEnabled; - } - - /** - * Checks whether or not the skill bar is to display cooldowns - * - * @return true if enabled, false otherwise - */ - public boolean isSkillBarCooldowns() { - return skillBarCooldowns; - } - - /** - * Retrieves the indicator for an unassigned skill slot - * - * @return unassigned indicator - */ - public ItemStack getUnassigned() { - return unassigned; - } - - /** - * Retrieves the default skill bar layout - * - * @return default skill bar layout - */ - public boolean[] getDefaultBarLayout() { - return defaultBarLayout; - } - - /** - * Retrieves the list of locked skill bar slots - * - * @return list of locked skill bar slots - */ - public boolean[] getLockedSlots() { - return lockedSlots; - } - - private void loadSkillBarSettings() { - DataSection bar = config.getSection("Skill Bar"); - skillBarEnabled = bar.getBoolean("enabled", false) && !castEnabled; - skillBarCooldowns = bar.getBoolean("show-cooldown", true); - - DataSection icon = bar.getSection("empty-icon"); - Material mat = Material.matchMaterial(icon.getString("material", "PUMPKIN_SEEDS")); - if (mat == null) { mat = Material.PUMPKIN_SEEDS; } - unassigned = new ItemStack(mat); - - final int data = icon.getInt("data", 0); - unassigned.setDurability((short) data); - unassigned.setData(new MaterialData(mat, (byte) data)); - - ItemMeta meta = unassigned.getItemMeta(); - if (icon.isList("text")) { - List format = TextFormatter.colorStringList(icon.getList("text")); - meta.setDisplayName(format.remove(0)); - meta.setLore(format); - } else { meta.setDisplayName(TextFormatter.colorString(icon.getString("text", "&7Unassigned"))); } - unassigned.setItemMeta(meta); - - DataSection layout = bar.getSection("layout"); - int skillCount = 0; - for (int i = 0; i < 9; i++) { - DataSection slot = layout.getSection((i + 1) + ""); - defaultBarLayout[i] = slot.getBoolean("skill", i <= 5); - lockedSlots[i] = slot.getBoolean("locked", false); - if (isUsingCombat() && i == castSlot) { - lockedSlots[i] = true; - defaultBarLayout[i] = false; - } - if (defaultBarLayout[i]) { - skillCount++; - } - } - if (skillCount == 9) { - Logger.invalid("Invalid Skill Bar Setup - Cannot have all 9 skill slots!"); - Logger.invalid(" -> Setting last slot to be a weapon slot"); - defaultBarLayout[8] = false; - } - } - - /////////////////////////////////////////////////////// - // // - // Logging Settings // - // // - /////////////////////////////////////////////////////// - - private void loadLoggingSettings() { - Logger.loadLevels(config.getSection("Logging")); - } - - /////////////////////////////////////////////////////// - // // - // World Settings // - // // - /////////////////////////////////////////////////////// - - private static final String WORLD_BASE = "Worlds."; - private static final String WORLD_ENABLE = WORLD_BASE + "enable"; - private static final String WORLD_TYPE = WORLD_BASE + "use-as-enabling"; - private static final String WORLD_LIST = WORLD_BASE + "worlds"; - - private List worlds; - private boolean worldEnabled; - private boolean worldEnableList; - - /** - * Checks whether or not SkillAPI is active in the world - * - * @param world world to check - * - * @return true if active, false otherwise - */ - public boolean isWorldEnabled(World world) { - return isWorldEnabled(world.getName()); - } - - /** - * Checks whether or not SkillAPI is active in the world with - * the given name. - * - * @param world world name - * - * @return true if active, false otherwise - */ - public boolean isWorldEnabled(String world) { - return !worldEnabled || (worldEnableList == worlds.contains(world)); - } - - private void loadWorldSettings() { - worldEnabled = config.getBoolean(WORLD_ENABLE); - worldEnableList = config.getBoolean(WORLD_TYPE); - worlds = config.getList(WORLD_LIST); - } - - /////////////////////////////////////////////////////// - // // - // WorldGuard Settings // - // // - /////////////////////////////////////////////////////// - - private static final String WG_SKILLS = "disable-skills"; - private static final String WG_EXP = "disable-exp"; - - private Set skillDisabledRegions; - private Set expDisabledRegions; - - public boolean areSkillsDisabledForRegion(final String region) { - return skillDisabledRegions.contains(region); - } - - public boolean isExpDisabledForRegion(final String region) { - return expDisabledRegions.contains(region); - } - - private void loadWorldGuardSettings() { - final CommentedConfig config = new CommentedConfig(plugin, "worldGuard"); - config.checkDefaults(); - config.trim(); - config.save(); - final DataSection data = config.getConfig(); - - skillDisabledRegions = ImmutableSet.copyOf(data.getList(WG_SKILLS)); - expDisabledRegions = ImmutableSet.copyOf(data.getList(WG_EXP)); - } -} +/** + * SkillAPI + * com.sucy.skill.data.Settings + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.rit.sucy.config.CommentedConfig; +import com.rit.sucy.config.parse.DataSection; +import com.rit.sucy.config.parse.NumberParser; +import com.rit.sucy.text.TextFormatter; +import com.rit.sucy.version.VersionManager; +import com.sucy.party.Parties; +import com.sucy.party.Party; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.CombatProtection; +import com.sucy.skill.api.DefaultCombatProtection; +import com.sucy.skill.api.player.PlayerClass; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.cast.IndicatorSettings; +import com.sucy.skill.data.formula.Formula; +import com.sucy.skill.data.formula.value.CustomValue; +import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.gui.tool.GUITool; +import com.sucy.skill.log.Logger; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.Animals; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.entity.Tameable; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.MaterialData; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

The management class for SkillAPI's config.yml settings.

+ */ +public class Settings { + + private HashMap groups = new HashMap(); + + private SkillAPI plugin; + private DataSection config; + + /** + *

Initializes a new settings manager.

+ *

This is already set up by SkillAPI and shouldn't be + * instantiated elsewhere. Instead, get it from SkillAPI + * using the SkillAPI.getSettings() method.

+ * + * @param plugin SkillAPI plugin reference + */ + public Settings(SkillAPI plugin) { + this.plugin = plugin; + CommentedConfig file = new CommentedConfig(plugin, "config"); + file.checkDefaults(); + file.save(); + config = file.getConfig(); + reload(); + } + + /** + *

Reloads the settings from SkillAPI's config.yml file.

+ *

This will fill in any missing values with default values + * and trim any values that aren't supposed to be there.

+ */ + public void reload() { + loadExperienceSettings(); + loadAccountSettings(); + loadClassSettings(); + loadManaSettings(); + loadSkillSettings(); + loadItemSettings(); + loadGUISettings(); + loadCastSettings(); + loadComboSettings(); + loadExpSettings(); + loadSkillBarSettings(); + loadLoggingSettings(); + loadWorldSettings(); + loadSaveSettings(); + loadTargetingSettings(); + loadWorldGuardSettings(); + loadIsInstance(); + loadGlobalSkills(); + } + + /////////////////////////////////////////////////////// + // // + // Experience Settings // + // // + /////////////////////////////////////////////////////// + + private static final String DEFAULT_YIELD = "default"; + + private Map> breakYields; + private Map> placeYields; + private Map> craftYields; + + private boolean trackBreak; + private boolean yieldsEnabled; + + public void loadExperienceSettings() { + CommentedConfig file = new CommentedConfig(plugin, "exp"); + file.checkDefaults(); + file.save(); + DataSection config = file.getConfig(); + + DataSection breakData = config.getSection("break"); + yieldsEnabled = config.getBoolean("enabled", false); + trackBreak = breakData.getBoolean("allow-replace", true); + breakYields = loadYields(breakData.getSection("types")); + placeYields = loadYields(config.getSection("place")); + craftYields = loadYields(config.getSection("craft")); + } + + private Map> loadYields(DataSection config) { + Map> yields = new HashMap>(); + for (String className : config.keys()) { + HashMap map = new HashMap(); + DataSection classYields = config.getSection(className); + for (String type : classYields.keys()) { + map.put(type.toUpperCase().replace(" ", "_"), classYields.getDouble(type)); + } + yields.put(className, map); + } + return yields; + } + + public boolean trackBreaks() { + return trackBreak; + } + + public boolean yieldsEnabled() { + return yieldsEnabled; + } + + public double getBreakYield(PlayerClass playerClass, Material mat) { + return getYield(breakYields, playerClass, mat.name()); + } + + public double getPlaceYield(PlayerClass playerClass, Material mat) { + return getYield(placeYields, playerClass, mat.name()); + } + + public double getCraftYield(PlayerClass playerClass, Material mat) { + return getYield(craftYields, playerClass, mat.name()); + } + + private double getYield(Map> yields, PlayerClass playerClass, String key) { + double yield = getYield(yields.get(playerClass.getData().getName()), key); + return yield > 0 ? yield : getYield(yields.get(DEFAULT_YIELD), key); + } + + private double getYield(Map yields, String key) { + return yields == null ? 0 : (yields.containsKey(key) ? yields.get(key) : 0); + } + + /////////////////////////////////////////////////////// + // // + // Group Settings // + // // + /////////////////////////////////////////////////////// + + public void loadGroupSettings() { + CommentedConfig file = new CommentedConfig(plugin, "groups"); + DataSection config = file.getConfig(); + groups.clear(); + + for (String key : config.keys()) { + groups.put(key.toLowerCase(), new GroupSettings(config.getSection(key))); + } + for (String group : SkillAPI.getGroups()) { + if (!groups.containsKey(group.toLowerCase())) { + GroupSettings settings = new GroupSettings(); + groups.put(group.toLowerCase(), settings); + settings.save(config.createSection(group.toLowerCase())); + } + config.setComments(group.toLowerCase(), ImmutableList.of( + "", + " Settings for classes with the group " + group, + " If new classes are loaded with different groups,", + " the new groups will show up in this file after the first load.")); + } + + file.save(); + } + + /** + * Retrieves the settings for a class group + * + * @param group name of the group to retrieve the settings for + * + * @return settings for the class group + */ + public GroupSettings getGroupSettings(String group) { + if (!groups.containsKey(group.toLowerCase())) { + return new GroupSettings(); + } + return groups.get(group.toLowerCase()); + } + + /////////////////////////////////////////////////////// + // // + // Account Settings // + // // + /////////////////////////////////////////////////////// + + private static final String ACCOUNT_BASE = "Accounts."; + private static final String ACCOUNT_MAIN = ACCOUNT_BASE + "main-class-group"; + private static final String ACCOUNT_EACH = ACCOUNT_BASE + "one-per-class"; + private static final String ACCOUNT_MAX = ACCOUNT_BASE + "max-accounts"; + private static final String ACCOUNT_PERM = ACCOUNT_BASE + "perm-accounts"; + + private String mainGroup; + private boolean onePerClass; + private int maxAccounts; + + private HashMap permAccounts = new HashMap(); + + /** + * Retrieves the main class group for displaying prefixes + * or showing account information + * + * @return main class group + */ + public String getMainGroup() { + return mainGroup; + } + + /** + * Retrieves whether or not accounts should be initialized with + * one file per class. + * + * @return true if enabled, false otherwise + */ + public boolean isOnePerClass() { + return onePerClass; + } + + /** + * Retrieves the max accounts allowed for most players + * + * @return max accounts allowed for most players + */ + public int getMaxAccounts() { + return maxAccounts; + } + + /** + * Retrieves the max amount of accounts allowed for a specific player + * by checking permissions for additional accounts. + * + * @param player player to check the max allowed accounts for + * + * @return number of allowed accounts + */ + public int getMaxAccounts(Player player) { + if (player == null) { + return maxAccounts; + } + int max = maxAccounts; + for (Map.Entry entry : permAccounts.entrySet()) { + if (player.hasPermission(entry.getKey())) { + max = Math.max(max, entry.getValue()); + } + } + return max; + } + + private void loadAccountSettings() { + mainGroup = config.getString(ACCOUNT_MAIN); + onePerClass = config.getBoolean(ACCOUNT_EACH); + maxAccounts = config.getInt(ACCOUNT_MAX); + + // Permission account amounts + List list = config.getList(ACCOUNT_PERM); + for (String item : list) { + if (!item.contains(":")) { + continue; + } + + String[] pieces = item.split(":"); + if (pieces.length != 2) { + continue; + } + + try { + permAccounts.put(pieces[0], Integer.parseInt(pieces[1])); + } catch (Exception ex) { + // Invalid setting value + } + } + } + + /////////////////////////////////////////////////////// + // // + // Targeting Settings // + // // + /////////////////////////////////////////////////////// + + private static final String TARGET_BASE = "Targeting."; + private static final String TARGET_MONSTER = TARGET_BASE + "monsters-enemy"; + private static final String TARGET_PASSIVE = TARGET_BASE + "passive-ally"; + private static final String TARGET_PLAYER = TARGET_BASE + "player-ally"; + private static final String TARGET_PARTIES = TARGET_BASE + "parties-ally"; + private static final String TARGET_NPC = TARGET_BASE + "affect-npcs"; + private static final String TARGET_STANDS = TARGET_BASE + "affect-armor-stands"; + + private ArrayList monsterWorlds = new ArrayList(); + private ArrayList passiveWorlds = new ArrayList(); + private ArrayList playerWorlds = new ArrayList(); + + private boolean monsterEnemy; + private boolean passiveAlly; + private boolean playerAlly; + private boolean partiesAlly; + private boolean affectNpcs; + private boolean affectArmorStands; + + private CombatProtection combatProtection = new DefaultCombatProtection(); + + /** + * Checks whether or not something can be attacked + * + * @param attacker the attacking entity + * @param target the target entity + * + * @return true if can be attacked, false otherwise + */ + public boolean canAttack(LivingEntity attacker, LivingEntity target) { + if (attacker instanceof Player) { + final Player player = (Player) attacker; + if (target instanceof Animals && !(target instanceof Tameable)) { + if (passiveAlly || passiveWorlds.contains(attacker.getWorld().getName())) { return false; } + } else if (target instanceof Monster) { + if (monsterEnemy || monsterWorlds.contains(attacker.getWorld().getName())) { return true; } + } else if (target instanceof Player) { + if (playerAlly || playerWorlds.contains(attacker.getWorld().getName())) { return false; } + + if (partiesAlly) { + final Parties parties = Parties.getPlugin(Parties.class); + final Party p1 = parties.getJoinedParty(player); + final Party p2 = parties.getJoinedParty((Player) target); + return p1 == null || p1 != p2; + } + return combatProtection.canAttack(player, (Player) target); + } + return combatProtection.canAttack(player, target); + } else if (attacker instanceof Tameable) { + Tameable tameable = (Tameable) attacker; + if (tameable.isTamed() && (tameable.getOwner() instanceof LivingEntity)) { + return (tameable.getOwner() != target) + && canAttack((LivingEntity) tameable.getOwner(), target); + } + } else { return !(target instanceof Monster); } + + return combatProtection.canAttack(attacker, target); + } + + /** + * Checks whether or not something is an ally + * + * @param attacker the attacking entity + * @param target the target entity + * + * @return true if an ally, false otherwise + */ + public boolean isAlly(LivingEntity attacker, LivingEntity target) { + return !canAttack(attacker, target); + } + + /** + * Checks whether or not a target is a valid target. + * + * @param target target to check + * @return true if a valid target, false otherwise + */ + public boolean isValidTarget(final LivingEntity target) { + return (!target.hasMetadata("NPC") || affectNpcs) + && (!target.getType().name().equals("ARMOR_STAND") || affectArmorStands); + } + + /** + * Swaps out the default combat protection for a custom one + * + * @param combatProtection combat protection to use + */ + public void setCombatProtection(final CombatProtection combatProtection) { + this.combatProtection = combatProtection; + } + + private void loadTargetingSettings() { + if (config.isList(TARGET_MONSTER)) { + monsterWorlds.addAll(config.getList(TARGET_MONSTER)); + monsterEnemy = false; + } else { monsterEnemy = config.getBoolean(TARGET_MONSTER); } + + if (config.isList(TARGET_PASSIVE)) { + passiveWorlds.addAll(config.getList(TARGET_PASSIVE)); + passiveAlly = false; + } else { passiveAlly = config.getBoolean(TARGET_PASSIVE); } + + if (config.isList(TARGET_PLAYER)) { + playerWorlds.addAll(config.getList(TARGET_PLAYER)); + playerAlly = false; + } else { playerAlly = config.getBoolean(TARGET_PLAYER); } + + partiesAlly = config.getBoolean(TARGET_PARTIES); + affectArmorStands = config.getBoolean(TARGET_STANDS); + affectNpcs = config.getBoolean(TARGET_NPC); + } + + /////////////////////////////////////////////////////// + // // + // Saving Settings // + // // + /////////////////////////////////////////////////////// + + private static final String SAVE_BASE = "Saving."; + private static final String SAVE_AUTO = SAVE_BASE + "auto-save"; + private static final String SAVE_MINS = SAVE_BASE + "minutes"; + private static final String SAVE_SQL = SAVE_BASE + "sql-database"; + private static final String SAVE_SQLD = SAVE_BASE + "sql-details"; + + private boolean auto; + private boolean useSql; + private int minutes; + private int sqlDelay; + + private String sqlHost; + private String sqlPort; + private String sqlDatabase; + private String sqlUser; + private String sqlPass; + + /** + * Checks whether or not auto saving is enabled + * + * @return true if enabled, false otherwise + */ + public boolean isAutoSave() { + return auto; + } + + /** + * Retrieves the amount of ticks in between each auto save + * + * @return frequency of saves + */ + public int getSaveFreq() { + return minutes * 60 * 20; + } + + /** + * Checks whether or not the plugin is using SQL Database saving + * + * @return true if enabled, false otherwise + */ + public boolean isUseSql() { + return useSql; + } + + /** + * Retrieves the host IP for the database + * + * @return host IP for SQL database + */ + public String getSQLHost() { + return sqlHost; + } + + /** + * Retrieves the host port for the database + * + * @return host port for SQL database + */ + public String getSQLPort() { + return sqlPort; + } + + /** + * Retrieves the name of the SQL database + * + * @return SQL database name + */ + public String getSQLDatabase() { + return sqlDatabase; + } + + /** + * Retrieves the username for the database credentials + * + * @return SQL database username + */ + public String getSQLUser() { + return sqlUser; + } + + /** + * Retrieves the password for the database credentials + * + * @return SQL database password + */ + public String getSQLPass() { + return sqlPass; + } + + /** + * @return time in milliseconds to wait before loading SQL data + */ + public int getSqlDelay() { + return sqlDelay; + } + + private void loadSaveSettings() { + auto = config.getBoolean(SAVE_AUTO); + minutes = config.getInt(SAVE_MINS); + useSql = config.getBoolean(SAVE_SQL); + + DataSection details = config.getSection(SAVE_SQLD); + sqlDelay = details.getInt("delay"); + + if (useSql) { + sqlHost = details.getString("host"); + sqlPort = details.getString("port"); + sqlDatabase = details.getString("database"); + sqlUser = details.getString("username"); + sqlPass = details.getString("password"); + } + } + + /////////////////////////////////////////////////////// + // // + // Class Settings // + // // + /////////////////////////////////////////////////////// + + private static final String CLASS_BASE = "Classes."; + private static final String CLASS_MODIFY = CLASS_BASE + "modify-health"; + private static final String CLASS_HP = CLASS_BASE + "classless-hp"; + private static final String CLASS_SHOW = CLASS_BASE + "show-auto-skills"; + private static final String CLASS_ATTRIB = CLASS_BASE + "attributes-enabled"; + private static final String CLASS_REFUND = CLASS_BASE + "attributes-downgrade"; + private static final String CLASS_CRIT = CLASS_BASE + "dex-crit"; + private static final String CLASS_LEVEL = CLASS_BASE + "level-up-skill"; + + private boolean modifyHealth; + private int defaultHealth; + private boolean showAutoSkills; + private boolean attributesEnabled; + private boolean attributesDowngrade; + private double dexCrit; + private String levelUpSkill; + + /** + * Checks whether or not SkillAPI should modify the max health of players + * + * @return true if enabled, false otherwise + */ + public boolean isModifyHealth() { + return modifyHealth; + } + + /** + *

Retrieves the default health for players that do not have a class.

+ * + * @return default health for classless players + */ + public int getDefaultHealth() { + return defaultHealth; + } + + /** + * Checks whether or not auto-leveled skills are to be shown. + * + * @return true if shown, false otherwise + */ + public boolean isShowingAutoSkills() { + return showAutoSkills; + } + + /** + * Checks whether or not attributes are enabled + * + * @return true if enabled, false otherwise + */ + public boolean isAttributesEnabled() { + return attributesEnabled; + } + + /** + * Checks whether or not attribute points can be refunded + * + * @return true if can refund, false otherwise + */ + public boolean isAttributesDowngrade() { + return attributesDowngrade; + } + + public double getDexCrit() { + return dexCrit; + } + + /** + * Checks whether or not the plugin has a valid skill for + * level up effects loaded. + * + * @return true if one is available, false otherwise + */ + public boolean hasLevelUpEffect() { + return getLevelUpSkill() != null; + } + + /** + * Retrieves the skill used for level up effects + * + * @return skill for level up effects + */ + public DynamicSkill getLevelUpSkill() { + Skill skill = SkillAPI.getSkill(levelUpSkill); + return (skill instanceof DynamicSkill) ? (DynamicSkill) skill : null; + } + + private void loadClassSettings() { + modifyHealth = config.getBoolean(CLASS_MODIFY); + defaultHealth = config.getInt(CLASS_HP); + showAutoSkills = config.getBoolean(CLASS_SHOW); + attributesEnabled = config.getBoolean(CLASS_ATTRIB); + attributesDowngrade = config.getBoolean(CLASS_REFUND); + dexCrit = config.getDouble(CLASS_CRIT, 0.02); + levelUpSkill = config.getString(CLASS_LEVEL); + } + + /////////////////////////////////////////////////////// + // // + // Mana Settings // + // // + /////////////////////////////////////////////////////// + + private static final String MANA_BASE = "Mana."; + private static final String MANA_ENABLED = MANA_BASE + "enabled"; + private static final String MANA_FREQ = MANA_BASE + "freq"; + + private boolean manaEnabled; + private int gainFreq; + + /** + * Checks whether or not mana is enabled + * + * @return true if enabled, false otherwise + */ + public boolean isManaEnabled() { + return manaEnabled; + } + + /** + * Retrieves the frequency of mana gain + * + * @return the frequency of mana gain + */ + public int getGainFreq() { + return gainFreq; + } + + private void loadManaSettings() { + manaEnabled = config.getBoolean(MANA_ENABLED); + gainFreq = (int) (config.getDouble(MANA_FREQ) * 20); + } + + /////////////////////////////////////////////////////// + // // + // Skill Settings // + // // + /////////////////////////////////////////////////////// + + private static final String SKILL_BASE = "Skills."; + private static final String SKILL_DOWNGRADE = SKILL_BASE + "allow-downgrade"; + private static final String SKILL_MESSAGE = SKILL_BASE + "show-messages"; + private static final String SKILL_RADIUS = SKILL_BASE + "message-radius"; + private static final String SKILL_BLOCKS = SKILL_BASE + "block-filter"; + private static final String SKILL_KNOCKBACK = SKILL_BASE + "knockback-no-damage"; + + private ArrayList filteredBlocks; + + private boolean allowDowngrade; + private boolean showSkillMessages; + private boolean knockback; + private int messageRadius; + + /** + * Checks whether or not downgrades are allowed + * + * @return true if allowed, false otherwise + */ + public boolean isAllowDowngrade() { + return allowDowngrade; + } + + /** + * Checks whether or not skill messages are enabled + * + * @return true if enabled, false otherwise + */ + public boolean isShowSkillMessages() { + return showSkillMessages; + } + + /** + * @return whether or not knockback should be applied when dealing 0 damage + */ + public boolean isKnockback() { + return knockback; + } + + /** + * Gets the radius in which skill messages are sent out + * + * @return skill message radius + */ + public int getMessageRadius() { + return messageRadius; + } + + /** + * Retrieves the list of filtered blocks + * + * @return list of blocks + */ + public List getFilteredBlocks() { + return filteredBlocks; + } + + private void loadSkillSettings() { + allowDowngrade = config.getBoolean(SKILL_DOWNGRADE); + showSkillMessages = config.getBoolean(SKILL_MESSAGE); + messageRadius = config.getInt(SKILL_RADIUS); + knockback = config.getBoolean(SKILL_KNOCKBACK); + + filteredBlocks = new ArrayList(); + List list = config.getList(SKILL_BLOCKS); + for (String item : list) { + item = item.toUpperCase().replace(' ', '_'); + if (item.endsWith("*")) { + item = item.substring(0, item.length() - 1); + for (Material mat : Material.values()) { + if (mat.name().contains(item)) { + filteredBlocks.add(mat); + } + } + } else { + try { + Material mat = Material.valueOf(item); + filteredBlocks.add(mat); + } catch (Exception ex) { + Logger.invalid("Invalid block type \"" + item + "\""); + } + } + } + } + + /////////////////////////////////////////////////////// + // // + // Item Settings // + // // + /////////////////////////////////////////////////////// + + private static final String ITEM_BASE = "Items."; + private static final String ITEM_LORE = ITEM_BASE + "lore-requirements"; + private static final String ITEM_DROP = ITEM_BASE + "drop-weapon"; + private static final String ITEM_SKILLS = ITEM_BASE + "skill-requirements"; + private static final String ITEM_ATTRIBS = ITEM_BASE + "lore-attributes"; + private static final String ITEM_CLASS = ITEM_BASE + "lore-class-text"; + private static final String ITEM_SKILL = ITEM_BASE + "lore-skill-text"; + private static final String ITEM_LEVEL = ITEM_BASE + "lore-level-text"; + private static final String ITEM_EXCLUDE = ITEM_BASE + "lore-exclude-text"; + private static final String ITEM_ATTR = ITEM_BASE + "lore-attribute-text"; + private static final String ITEM_STATS = ITEM_BASE + "attribute-text"; + private static final String ITEM_SLOTS = ITEM_BASE + "slots"; + + private boolean checkLore; + private boolean checkAttribs; + private boolean checkSkills; + private boolean dropWeapon; + private String loreClassText; + private String loreLevelText; + private String loreExcludeText; + private int[] slots; + + private String skillPre, skillPost; + private String attrReqPre, attrReqPost; + private String attrPre, attrPost; + + /** + * Checks whether or not lore requirements are enabled + * + * @return true if enabled, false otherwise + */ + public boolean isCheckLore() { + return checkLore; + } + + /** + * @return true if should check for skill requirements + */ + public boolean isCheckSkillLore() { + return checkSkills; + } + + /** + * @return true if should check for attribute bonuses + */ + public boolean isCheckAttributes() { + return checkAttribs; + } + + /** + * @return checks if weapons are dropped when hovered + */ + public boolean isDropWeapon() { + return dropWeapon; + } + + /** + * @return lore for skill requirements + */ + public String getSkillText(String skill) { + return skillPre + skill + skillPost; + } + + /** + * Retrieves the text used for class requirements on items + * + * @return lore text for class requirements + */ + public String getLoreClassText() { + return loreClassText; + } + + /** + * Retrieves the text used for level requirements on items + * + * @return lore text for level requirements + */ + public String getLoreLevelText() { + return loreLevelText; + } + + /** + * Retrieves the text used for excluded classes on items + * + * @return lore text for excluded classes + */ + public String getLoreExcludeText() { + return loreExcludeText; + } + + /** + * Retrieves the text used for attribute requirements on items + * + * @return lore text for attributes + */ + public String getAttrReqText(String attr) { + return attrReqPre + attr + attrReqPost; + } + + /** + * @return lore text for giving attributes + */ + public String getAttrGiveText(String attr) { + return attrPre + attr + attrPost; + } + + /** + * @return slots checked for requirements and attributes + */ + public int[] getSlots() { + return slots; + } + + private void loadItemSettings() { + checkLore = config.getBoolean(ITEM_LORE); + dropWeapon = config.getBoolean(ITEM_DROP); + checkSkills = config.getBoolean(ITEM_SKILLS); + checkAttribs = config.getBoolean(ITEM_ATTRIBS); + loreClassText = config.getString(ITEM_CLASS).toLowerCase(); + loreLevelText = config.getString(ITEM_LEVEL).toLowerCase(); + loreExcludeText = config.getString(ITEM_EXCLUDE).toLowerCase(); + + String temp = config.getString(ITEM_SKILL).toLowerCase(); + int index = temp.indexOf('{'); + skillPre = temp.substring(0, index); + skillPost = temp.substring(index + 7); + + temp = config.getString(ITEM_ATTR).toLowerCase(); + index = temp.indexOf('{'); + attrReqPre = temp.substring(0, index); + attrReqPost = temp.substring(index + 6); + + temp = config.getString(ITEM_STATS).toLowerCase(); + index = temp.indexOf('{'); + attrPre = temp.substring(0, index); + attrPost = temp.substring(index + 6); + + List slotList = config.getList(ITEM_SLOTS); + if (!VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { slotList.remove("40"); } + slots = new int[slotList.size()]; + for (int i = 0; i < slots.length; i++) { slots[i] = NumberParser.parseInt(slotList.get(i)); } + } + + /////////////////////////////////////////////////////// + // // + // GUI Settings // + // // + /////////////////////////////////////////////////////// + + private static final String + GUI_BASE = "GUI.", + GUI_OLD = GUI_BASE + "old-health-bar", + GUI_FORCE = GUI_BASE + "force-scaling", + GUI_LVLBAR = GUI_BASE + "level-bar", + GUI_FOOD = GUI_BASE + "food-bar", + GUI_ACTION = GUI_BASE + "use-action-bar", + GUI_TEXT = GUI_BASE + "action-bar-text", + GUI_BOARD = GUI_BASE + "scoreboard-enabled", + GUI_NAME = GUI_BASE + "show-class-name", + GUI_LEVEL = GUI_BASE + "show-class-level", + GUI_BINDS = GUI_BASE + "show-binds", + GUI_BIND_TEXT = GUI_BASE + "show-bind-text", + GUI_LVLTXT = GUI_BASE + "class-level-text", + GUI_TITLE = GUI_BASE + "title-enabled", + GUI_DUR = GUI_BASE + "title-duration", + GUI_FADEI = GUI_BASE + "title-fade-in", + GUI_FADEO = GUI_BASE + "title-fade-out", + GUI_LIST = GUI_BASE + "title-messages"; + + private List titleMessages; + + private boolean oldHealth; + private boolean forceScaling; + private String levelBar; + private String foodBar; + private String levelText; + private boolean useActionBar; + private String actionText; + private boolean showScoreboard; + private boolean showClassName; + private boolean showClassLevel; + private boolean showBinds; + private String bindText; + private boolean useTitle; + private int titleDuration; + private int titleFadeIn; + private int titleFadeOut; + + /** + * Checks whether or not old health bars (fixed 10 hearts) are enabled + * + * @return true if enabled, false otherwise + */ + public boolean isOldHealth() { + return oldHealth; + } + + /** + * @return true if forces the SkillAPI health scaling, false otherwise + */ + public boolean isForceScaling() { + return forceScaling; + } + + /** + * Gets the setting for using the level bar + * + * @return level bar setting + */ + public String getLevelBar() { + return levelBar; + } + + /** + * Gets the setting for using the food bar + * + * @return food bar setting + */ + public String getFoodBar() { + return foodBar; + } + + /** + * Checks whether or not the action bar is being used + * + * @return true if used, false otherwise + */ + public boolean isUseActionBar() { + return useActionBar; + } + + /** + * Gets the text to display on the action bar + * + * @return action bar text + */ + public String getActionText() { + return actionText; + } + + /** + * Checks whether or not the stats scoreboard is to be shown + * + * @return true if shown, false otherwise + */ + public boolean isShowScoreboard() { + return showScoreboard; + } + + /** + * Checks whether or not a player's class name is to be + * shown next to their name + * + * @return true if shown, false otherwise + */ + public boolean isShowClassName() { + return showClassName; + } + + /** + * Checks whether or not a player's class level is to be + * shown below their name + * + * @return true if shown, false otherwise + */ + public boolean isShowClassLevel() { + return showClassLevel; + } + + public boolean isShowBinds() { + return showBinds; + } + + public String getBindText() { + return bindText; + } + + /** + * @return text shown alongside the class level + */ + public String getLevelText() { + return levelText; + } + + /** + * Check whether or not to use the title display + * on the given message type + * + * @param type type of message to check for + * + * @return true if should use title display, false otherwise + */ + public boolean useTitle(TitleType type) { + return useTitle && type != null && titleMessages.contains(type.name().toLowerCase()); + } + + /** + * @return duration of the title display in ticks + */ + public int getTitleDuration() { + return titleDuration; + } + + /** + * @return fade in time of the title display in ticks + */ + public int getTitleFadeIn() { + return titleFadeIn; + } + + /** + * @return fade out time of the title display in ticks + */ + public int getTitleFadeOut() { + return titleFadeOut; + } + + private void loadGUISettings() { + oldHealth = config.getBoolean(GUI_OLD); + forceScaling = config.getBoolean(GUI_FORCE); + levelBar = config.getString(GUI_LVLBAR); + levelText = TextFormatter.colorString(config.getString(GUI_LVLTXT, "Level")); + foodBar = config.getString(GUI_FOOD); + useActionBar = config.getBoolean(GUI_ACTION); + actionText = config.getString(GUI_TEXT); + showScoreboard = config.getBoolean(GUI_BOARD); + showClassName = config.getBoolean(GUI_NAME); + showClassLevel = config.getBoolean(GUI_LEVEL); + showBinds = config.getBoolean(GUI_BINDS); + bindText = config.getString(GUI_BIND_TEXT); + useTitle = config.getBoolean(GUI_TITLE); + titleDuration = (int) (20 * config.getFloat(GUI_DUR)); + titleFadeIn = (int) (20 * config.getFloat(GUI_FADEI)); + titleFadeOut = (int) (20 * config.getFloat(GUI_FADEO)); + titleMessages = config.getList(GUI_LIST); + } + + /////////////////////////////////////////////////////// + // // + // Cast Settings // + // // + /////////////////////////////////////////////////////// + + private static final String CAST_BASE = "Casting."; + private static final String CAST_ENABLED = CAST_BASE + "enabled"; + private static final String CAST_BARS = CAST_BASE + "bars"; + private static final String CAST_COMBAT = CAST_BASE + "combat"; + private static final String CAST_INDICATOR = CAST_BASE + "cast-indicator"; + private static final String CAST_SLOT = CAST_BASE + "slot"; + private static final String CAST_ITEM = CAST_BASE + "item"; + private static final String CAST_COOLDOWN = CAST_BASE + "cooldown"; + private static final String CAST_HOVER = CAST_BASE + "hover-item"; + private static final String CAST_INSTANT = CAST_BASE + "instant-item"; + + private boolean castEnabled; + private boolean castBars; + private boolean combatEnabled; + private int castSlot; + private long castCooldown; + private ItemStack castItem; + private ItemStack hoverItem; + private ItemStack instantItem; + + /** + * @return true if default casting is enabled + */ + public boolean isCastEnabled() { + return castEnabled; + } + + /** + * @return true if using bar format, false otherwise + */ + public boolean isUsingBars() { + return castEnabled && castBars && !combatEnabled; + } + + public boolean isUsingWand() { + return castEnabled && !castBars && !combatEnabled; + } + + public boolean isUsingCombat() { + return castEnabled && combatEnabled; + } + + /** + * @return slot the cast item is stored in + */ + public int getCastSlot() { + return castSlot; + } + + /** + * @return global cooldown for casting + */ + public long getCastCooldown() { + return castCooldown; + } + + /** + * @return cast item to use in the slot + */ + public ItemStack getCastItem() { + return castItem; + } + + public ItemStack getHoverItem() { + return hoverItem; + } + + public ItemStack getInstantItem() { + return instantItem; + } + + private void loadCastSettings() { + castEnabled = config.getBoolean(CAST_ENABLED); + castBars = config.getBoolean(CAST_BARS); + combatEnabled = config.getBoolean(CAST_COMBAT); + castSlot = config.getInt(CAST_SLOT) - 1; + castCooldown = (long) (config.getDouble(CAST_COOLDOWN) * 1000); + castItem = GUITool.parseItem(config.getSection(CAST_ITEM)); + hoverItem = GUITool.parseItem(config.getSection(CAST_HOVER)); + instantItem = GUITool.parseItem(config.getSection(CAST_INSTANT)); + castEnabled = castEnabled && castItem != null; + IndicatorSettings.load(config.getSection(CAST_INDICATOR)); + } + + /////////////////////////////////////////////////////// + // // + // Click Combo Settings // + // // + /////////////////////////////////////////////////////// + + private static final String COMBO_BASE = "Click Combos."; + private static final String COMBO_ENABLED = COMBO_BASE + "enabled"; + private static final String COMBO_CUSTOM = COMBO_BASE + "allow-custom"; + private static final String COMBO_CLICK = COMBO_BASE + "use-click-"; + private static final String COMBO_SIZE = COMBO_BASE + "combo-size"; + private static final String COMBO_TIME = COMBO_BASE + "click-time"; + private static final String COMBO_AUTO = COMBO_BASE + "auto-assign"; + + private boolean[] clicks; + private boolean combosEnabled; + private boolean customCombos; + private boolean autoAssignCombos; + private int comboSize; + private int clickTime; + + /** + * Checks whether or not click combos are enabled + * + * @return true if enabled, false otherwise + */ + public boolean isCombosEnabled() { + return combosEnabled; + } + + /** + * Checks whether or not players can customize their click combos + * + * @return true if can customize them, false otherwise + */ + public boolean isCustomCombosAllowed() { + return customCombos; + } + + public boolean shouldAutoAssignCombos() { + return autoAssignCombos; + } + + /** + * @return enabled clicks as an array of booleans indexed by click ID + */ + public boolean[] getEnabledClicks() { + return clicks; + } + + /** + * Retrieves the max length of combos to be used + * + * @return max length of combos to be used + */ + public int getComboSize() { + return comboSize; + } + + /** + * Retrieves the amount of seconds allowed between clicks before the combo resets + * + * @return number of seconds before a click combo resets + */ + public int getClickTime() { + return clickTime; + } + + private void loadComboSettings() { + combosEnabled = config.getBoolean(COMBO_ENABLED); + customCombos = combosEnabled && config.getBoolean(COMBO_CUSTOM); + autoAssignCombos = combosEnabled && config.getBoolean(COMBO_AUTO, true); + comboSize = config.getInt(COMBO_SIZE); + clickTime = (int) (1000 * config.getDouble(COMBO_TIME)); + + clicks = new boolean[Click.values().length + 1]; + for (int i = 1; i <= Click.values().length; i++) { + final String key = COMBO_CLICK + Click.getById(i).name().toLowerCase().replace('_', '-'); + clicks[i] = config.getBoolean(key); + } + if (clicks[Click.RIGHT_SHIFT.getId()] || clicks[Click.LEFT_SHIFT.getId()]) { + clicks[Click.SHIFT.getId()] = false; + } + } + + /////////////////////////////////////////////////////// + // // + // Exp Settings // + // // + /////////////////////////////////////////////////////// + + private final HashMap yields = new HashMap(); + + private ExpFormula expFormula; + private Formula expCustom; + private boolean useCustomExp; + private boolean useOrbs; + private boolean blockSpawner; + private boolean blockEgg; + private boolean blockCreative; + private boolean showExpMessages; + private boolean showLevelMessages; + private boolean showLossMessages; + private Set expLostBlacklist; + + /** + * Gets the required amount of experience at a given level + * + * @param level level of the class + * + * @return required experience to gain a level + */ + public int getRequiredExp(int level) { + if (useCustomExp) { return (int) expCustom.compute(level, 0); } else { return expFormula.calculate(level); } + } + + /** + * Gets the experience yield of a mob + * + * @param mob mob to get the yield of + * + * @return experience yield + */ + public double getYield(String mob) { + mob = mob.toLowerCase(); + if (!yields.containsKey(mob)) { + return 0; + } else { + return yields.get(mob); + } + } + + /** + * Checks whether or not experience is to be gained through + * vanilla experience orbs + * + * @return true if enabled, false otherwise + */ + public boolean isUseOrbs() { + return useOrbs; + } + + /** + * Checks whether or not experience from mobs spawned + * via a mob spawner is to be blocked. + * + * @return true if blocked, false otherwise + */ + public boolean isBlockSpawner() { + return blockSpawner; + } + + /** + * Checks whether or not experience from mobs spawned + * via eggs are to be blocked + * + * @return true if blocked, false otherwise + */ + public boolean isBlockEgg() { + return blockEgg; + } + + /** + * Checks whether or not players in creative mode + * are blocked from receiving experience. + * + * @return true if blocked, false otherwise + */ + public boolean isBlockCreative() { + return blockCreative; + } + + /** + * Checks whether or not messages should + * be displayed when a player gains experience + * + * @return true if enabled, false otherwise + */ + public boolean isShowExpMessages() { + return showExpMessages; + } + + /** + * Checks whether or not messages should be displayed + * when a player gains a level + * + * @return true if enabled, false otherwise + */ + public boolean isShowLevelMessages() { + return showLevelMessages; + } + + /** + * Checks whether or not messages should be displayed + * when a player dies and loses experience + * + * @return true if enabled, false otherwise + */ + public boolean isShowLossMessages() { + return showLossMessages; + } + + /** + * @param world world a player died in + * @return true if the world is blacklisted for losing experience + */ + public boolean shouldIgnoreExpLoss(final World world) { + return expLostBlacklist.contains(world.getName()); + } + + private static final String EXP_BASE = "Experience."; + + private void loadExpSettings() { + this.useOrbs = config.getBoolean(EXP_BASE + "use-exp-orbs"); + this.blockSpawner = config.getBoolean(EXP_BASE + "block-mob-spawner"); + this.blockEgg = config.getBoolean(EXP_BASE + "block-mob-egg"); + this.blockCreative = config.getBoolean(EXP_BASE + "block-creative"); + this.showExpMessages = config.getBoolean(EXP_BASE + "exp-message-enabled"); + this.showLevelMessages = config.getBoolean(EXP_BASE + "level-message-enabled"); + this.showLossMessages = config.getBoolean(EXP_BASE + "lose-exp-message"); + this.expLostBlacklist = new HashSet<>(config.getList(EXP_BASE + "lose-exp-blacklist")); + + DataSection formula = config.getSection(EXP_BASE + "formula"); + int x = formula.getInt("x"); + int y = formula.getInt("y"); + int z = formula.getInt("z"); + expFormula = new ExpFormula(x, y, z); + + expCustom = new Formula(config.getString(EXP_BASE + "custom-formula"), new CustomValue("lvl")); + useCustomExp = config.getBoolean(EXP_BASE + "use-custom") && expCustom.isValid(); + + DataSection yields = config.getSection(EXP_BASE + "yields"); + this.yields.clear(); + for (String key : yields.keys()) { + this.yields.put(key, yields.getDouble(key)); + } + } + + /////////////////////////////////////////////////////// + // // + // Skill Bar Settings // + // // + /////////////////////////////////////////////////////// + + private boolean skillBarEnabled; + private boolean skillBarCooldowns; + private ItemStack unassigned; + private boolean[] defaultBarLayout = new boolean[9]; + private boolean[] lockedSlots = new boolean[9]; + + /** + * Checks whether or not the skill bar is enabled + * + * @return true if enabled, false otherwise + */ + public boolean isSkillBarEnabled() { + return skillBarEnabled; + } + + /** + * Checks whether or not the skill bar is to display cooldowns + * + * @return true if enabled, false otherwise + */ + public boolean isSkillBarCooldowns() { + return skillBarCooldowns; + } + + /** + * Retrieves the indicator for an unassigned skill slot + * + * @return unassigned indicator + */ + public ItemStack getUnassigned() { + return unassigned; + } + + /** + * Retrieves the default skill bar layout + * + * @return default skill bar layout + */ + public boolean[] getDefaultBarLayout() { + return defaultBarLayout; + } + + /** + * Retrieves the list of locked skill bar slots + * + * @return list of locked skill bar slots + */ + public boolean[] getLockedSlots() { + return lockedSlots; + } + + private void loadSkillBarSettings() { + DataSection bar = config.getSection("Skill Bar"); + skillBarEnabled = bar.getBoolean("enabled", false) && !castEnabled; + skillBarCooldowns = bar.getBoolean("show-cooldown", true); + + DataSection icon = bar.getSection("empty-icon"); + Material mat = Material.matchMaterial(icon.getString("material", "PUMPKIN_SEEDS")); + if (mat == null) { mat = Material.PUMPKIN_SEEDS; } + unassigned = new ItemStack(mat); + + final int data = icon.getInt("data", 0); + unassigned.setDurability((short) data); + unassigned.setData(new MaterialData(mat, (byte) data)); + + ItemMeta meta = unassigned.getItemMeta(); + if (icon.isList("text")) { + List format = TextFormatter.colorStringList(icon.getList("text")); + meta.setDisplayName(format.remove(0)); + meta.setLore(format); + } else { meta.setDisplayName(TextFormatter.colorString(icon.getString("text", "&7Unassigned"))); } + unassigned.setItemMeta(meta); + + DataSection layout = bar.getSection("layout"); + int skillCount = 0; + for (int i = 0; i < 9; i++) { + DataSection slot = layout.getSection((i + 1) + ""); + defaultBarLayout[i] = slot.getBoolean("skill", i <= 5); + lockedSlots[i] = slot.getBoolean("locked", false); + if (isUsingCombat() && i == castSlot) { + lockedSlots[i] = true; + defaultBarLayout[i] = false; + } + if (defaultBarLayout[i]) { + skillCount++; + } + } + if (skillCount == 9) { + Logger.invalid("Invalid Skill Bar Setup - Cannot have all 9 skill slots!"); + Logger.invalid(" -> Setting last slot to be a weapon slot"); + defaultBarLayout[8] = false; + } + } + + /////////////////////////////////////////////////////// + // // + // Logging Settings // + // // + /////////////////////////////////////////////////////// + + private void loadLoggingSettings() { + Logger.loadLevels(config.getSection("Logging")); + } + + /////////////////////////////////////////////////////// + // // + // World Settings // + // // + /////////////////////////////////////////////////////// + + private static final String WORLD_BASE = "Worlds."; + private static final String WORLD_ENABLE = WORLD_BASE + "enable"; + private static final String WORLD_TYPE = WORLD_BASE + "use-as-enabling"; + private static final String WORLD_LIST = WORLD_BASE + "worlds"; + + private List worlds; + private boolean worldEnabled; + private boolean worldEnableList; + + /** + * Checks whether or not SkillAPI is active in the world + * + * @param world world to check + * + * @return true if active, false otherwise + */ + public boolean isWorldEnabled(World world) { + return isWorldEnabled(world.getName()); + } + + /** + * Checks whether or not SkillAPI is active in the world with + * the given name. + * + * @param world world name + * + * @return true if active, false otherwise + */ + public boolean isWorldEnabled(String world) { + return !worldEnabled || (worldEnableList == worlds.contains(world)); + } + + private void loadWorldSettings() { + worldEnabled = config.getBoolean(WORLD_ENABLE); + worldEnableList = config.getBoolean(WORLD_TYPE); + worlds = config.getList(WORLD_LIST); + } + + /////////////////////////////////////////////////////// + // // + // WorldGuard Settings // + // // + /////////////////////////////////////////////////////// + + private static final String WG_SKILLS = "disable-skills"; + private static final String WG_EXP = "disable-exp"; + + private Set skillDisabledRegions; + private Set expDisabledRegions; + + public boolean areSkillsDisabledForRegion(final String region) { + return skillDisabledRegions.contains(region); + } + + public boolean isExpDisabledForRegion(final String region) { + return expDisabledRegions.contains(region); + } + + private void loadWorldGuardSettings() { + final CommentedConfig config = new CommentedConfig(plugin, "worldGuard"); + config.checkDefaults(); + config.trim(); + config.save(); + final DataSection data = config.getConfig(); + + skillDisabledRegions = ImmutableSet.copyOf(data.getList(WG_SKILLS)); + expDisabledRegions = ImmutableSet.copyOf(data.getList(WG_EXP)); + } + + // Instance + private boolean isInstance; + private static final String IS_INSTANCE = "is-instance"; + private void loadIsInstance() { + if (new File(plugin.getDataFolder(), "instance").exists()) { + isInstance = true; + } + else { + isInstance = false; + } + } + + public boolean isInstance() { + return isInstance; + } + + // Global skills + private ArrayList globalSkills; + private static final String GLOBAL_SKILLS = "global-skills"; + private void loadGlobalSkills() { + this.globalSkills = (ArrayList) config.getList(GLOBAL_SKILLS); + } + + public ArrayList getGlobalSkills() { + return this.globalSkills; + } +} diff --git a/src/com/sucy/skill/data/TitleType.java b/src/main/java/com/sucy/skill/data/TitleType.java similarity index 100% rename from src/com/sucy/skill/data/TitleType.java rename to src/main/java/com/sucy/skill/data/TitleType.java diff --git a/src/com/sucy/skill/data/formula/Formula.java b/src/main/java/com/sucy/skill/data/formula/Formula.java similarity index 95% rename from src/com/sucy/skill/data/formula/Formula.java rename to src/main/java/com/sucy/skill/data/formula/Formula.java index 943cb0f6..64e1fb76 100644 --- a/src/com/sucy/skill/data/formula/Formula.java +++ b/src/main/java/com/sucy/skill/data/formula/Formula.java @@ -1,325 +1,328 @@ -/** - * SkillAPI - * com.sucy.skill.data.formula.Formula - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.data.formula; - -import com.sucy.skill.data.formula.func.*; -import com.sucy.skill.data.formula.operator.*; -import com.sucy.skill.data.formula.value.CustomValue; -import com.sucy.skill.data.formula.value.ValueNum; -import com.sucy.skill.log.Logger; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Represents a basic math equation read from left to right, ignoring - * order of operations. Currently this only supports addition, subtraction, - * multiplication, and division. - */ -public class Formula implements IValue -{ - public static final double DEG_TO_RAD = Math.PI / 180; - - private static final HashMap OPS = new HashMap() - {{ - put('+', new Addition()); - put('-', new Subtraction()); - put('*', new Multiplication()); - put('/', new Division()); - put('%', new Modulo()); - put('^', new Exponent()); - put('_', new Log()); - }}; - - private static final HashMap> FUNCS = new HashMap>() - {{ - put("abs", Abs.class); - put("ceil", Ceil.class); - put("cos", Cos.class); - put("floor", Floor.class); - put("sqrt", Root.class); - put("sign", Sign.class); - put("sin", Sin.class); - put("sq", Square.class); - put("tan", Tan.class); - }}; - - private IValue[] values; - private IOperator[] operations; - private boolean valid; - private boolean negative; - private String equation; - - /** - * Creates a new formula from a config string - * - * @param equation equation string - */ - public Formula(String equation, CustomValue... defined) - { - int i = 0; - for (CustomValue value : defined) - value.setIndex(i++); - - negative = false; - - // Empty formulas - if (equation == null || equation.length() == 0) - { - invalidate(defined); - return; - } - - // Clear out unused tokens - equation = equation.replaceAll("[ '\"]", ""); - this.equation = equation; - - // Parse the formula - ArrayList vals = new ArrayList(); - ArrayList ops = new ArrayList(); - int parens = 0, l = equation.length(), valStart = 0, lastOp = -1; - Class func = null; - for (i = 0; i < l; i++) - { - char c = equation.charAt(i); - - // Open parenthesis - if (c == '(') - { - if (parens == 0) - { - if (valStart != i) - { - String val = equation.substring(valStart, i); - if (FUNCS.containsKey(val)) - func = FUNCS.get(val); - else - { - vals.add(makeVal(val, defined)); - ops.add(OPS.get('*')); - } - } - valStart = i + 1; - lastOp = i; - } - parens++; - } - - // Close parenthesis - else if (c == ')') - { - parens--; - if (parens == 0) - { - if (func == null) - vals.add(makeVal(new Formula(equation.substring(valStart, i), defined))); - else - { - try - { - vals.add( - func.getConstructor(IValue.class).newInstance( - makeVal(new Formula(equation.substring(valStart, i), defined)) - ) - ); - } - catch (Exception ex) - { - ex.printStackTrace(); - invalidate(defined); - return; - } - } - valStart = i + 1; - } - } - - // Operators - else if (parens == 0 && OPS.containsKey(c)) - { - if (c == '-' && lastOp == i - 1) - { - negative = !negative; - valStart++; - lastOp++; - } - else - { - if (valStart != i) - { - vals.add(makeVal(equation.substring(valStart, i), defined)); - } - ops.add(OPS.get(c)); - lastOp = i; - valStart = i + 1; - } - } - } - - // End any lingering values - if (valStart != l) - { - vals.add(makeVal(equation.substring(valStart, equation.length()), defined)); - } - - negative = false; - - // Convert to arrays - values = vals.toArray(new IValue[vals.size()]); - operations = ops.toArray(new IOperator[ops.size()]); - - if (!validate()) - invalidate(defined); - else - valid = true; - } - - /** - * Invalidates the equation - * - * @param defined defined inputs - */ - private void invalidate(CustomValue... defined) - { - Logger.invalid("Invalid equation: " + equation); - equation = defined[0].getToken(); - values = new IValue[] { defined[0] }; - operations = new IOperator[0]; - valid = false; - } - - private IValue makeVal(String val, CustomValue... defined) - { - if (negative) - { - negative = false; - return new Formula(val, defined).negate(); - } - else - { - for (CustomValue value : defined) - { - if (value.getToken().equals(val)) - return value; - } - return new ValueNum(val); - } - } - - private IValue makeVal(Formula val) - { - if (negative && val.operations.length == 0 && val.values[0] instanceof ValueNum) - return new ValueNum(-val.values[0].compute()); - else if (negative) - { - val.negate(); - negative = false; - return val; - } - else if (val.operations.length == 0) - return val.values[0]; - else - return val; - } - - /** - * Whether or not the equation was valid when parsed. - * - * @return whether or not the equation was valid - */ - public boolean isValid() - { - return valid; - } - - /** - * Negates the output of the formula for future computations - * - * @return the negated Formula - */ - public Formula negate() - { - negative = !negative; - return this; - } - - /** - * Tries to validate the equation, making sure values are all valid values - * - * @return true if valid, false otherwise - */ - private boolean validate() - { - // Operators between values means there should - // always be one more value than operators - if (values.length != operations.length + 1) - { - return false; - } - - // Ensure valid sub equations - for (IValue value : values) - if (value instanceof Formula && !((Formula) value).validate()) - return false; - - // Nothing went wrong - return true; - } - - /** - * Calculates the formula using the given base value and attribute. - * If the formula is invalid, this returns the value. - * - * @param input the input data - * - * @return computed value - */ - public double compute(double... input) - { - double result = values[0].compute(input); - int i; - for (i = 1; i < values.length; i++) - { - double val = values[i].compute(input); - result = operations[i - 1].compute(result, val); - } - - if (negative) result = -result; - return result; - } - - /** - * Returns the equation string for toString - * - * @return the equation string - */ - @Override - public String toString() - { - return equation; - } -} +/** + * SkillAPI + * com.sucy.skill.data.formula.Formula + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.formula; + +import com.sucy.skill.data.formula.func.*; +import com.sucy.skill.data.formula.operator.*; +import com.sucy.skill.data.formula.value.CustomValue; +import com.sucy.skill.data.formula.value.ValueNum; +import com.sucy.skill.log.Logger; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Represents a basic math equation read from left to right, ignoring + * order of operations. Currently this only supports addition, subtraction, + * multiplication, and division. + */ +public class Formula implements IValue +{ + public static final double DEG_TO_RAD = Math.PI / 180; + + private static final HashMap OPS = new HashMap() + {{ + put('+', new Addition()); + put('-', new Subtraction()); + put('*', new Multiplication()); + put('/', new Division()); + put('%', new Modulo()); + put('^', new Exponent()); + put('_', new Log()); + put('<', new Minimum()); + put('>', new Maximum()); + }}; + + private static final HashMap> FUNCS = new HashMap>() + {{ + put("abs", Abs.class); + put("ceil", Ceil.class); + put("round", Round.class); + put("cos", Cos.class); + put("floor", Floor.class); + put("sqrt", Root.class); + put("sign", Sign.class); + put("sin", Sin.class); + put("sq", Square.class); + put("tan", Tan.class); + }}; + + private IValue[] values; + private IOperator[] operations; + private boolean valid; + private boolean negative; + private String equation; + + /** + * Creates a new formula from a config string + * + * @param equation equation string + */ + public Formula(String equation, CustomValue... defined) + { + int i = 0; + for (CustomValue value : defined) + value.setIndex(i++); + + negative = false; + + // Empty formulas + if (equation == null || equation.length() == 0) + { + invalidate(defined); + return; + } + + // Clear out unused tokens + equation = equation.replaceAll("[ '\"]", ""); + this.equation = equation; + + // Parse the formula + ArrayList vals = new ArrayList(); + ArrayList ops = new ArrayList(); + int parens = 0, l = equation.length(), valStart = 0, lastOp = -1; + Class func = null; + for (i = 0; i < l; i++) + { + char c = equation.charAt(i); + + // Open parenthesis + if (c == '(') + { + if (parens == 0) + { + if (valStart != i) + { + String val = equation.substring(valStart, i); + if (FUNCS.containsKey(val)) + func = FUNCS.get(val); + else + { + vals.add(makeVal(val, defined)); + ops.add(OPS.get('*')); + } + } + valStart = i + 1; + lastOp = i; + } + parens++; + } + + // Close parenthesis + else if (c == ')') + { + parens--; + if (parens == 0) + { + if (func == null) + vals.add(makeVal(new Formula(equation.substring(valStart, i), defined))); + else + { + try + { + vals.add( + func.getConstructor(IValue.class).newInstance( + makeVal(new Formula(equation.substring(valStart, i), defined)) + ) + ); + } + catch (Exception ex) + { + ex.printStackTrace(); + invalidate(defined); + return; + } + } + valStart = i + 1; + } + } + + // Operators + else if (parens == 0 && OPS.containsKey(c)) + { + if (c == '-' && lastOp == i - 1) + { + negative = !negative; + valStart++; + lastOp++; + } + else + { + if (valStart != i) + { + vals.add(makeVal(equation.substring(valStart, i), defined)); + } + ops.add(OPS.get(c)); + lastOp = i; + valStart = i + 1; + } + } + } + + // End any lingering values + if (valStart != l) + { + vals.add(makeVal(equation.substring(valStart, equation.length()), defined)); + } + + negative = false; + + // Convert to arrays + values = vals.toArray(new IValue[vals.size()]); + operations = ops.toArray(new IOperator[ops.size()]); + + if (!validate()) + invalidate(defined); + else + valid = true; + } + + /** + * Invalidates the equation + * + * @param defined defined inputs + */ + private void invalidate(CustomValue... defined) + { + Logger.invalid("Invalid equation: " + equation); + equation = defined[0].getToken(); + values = new IValue[] { defined[0] }; + operations = new IOperator[0]; + valid = false; + } + + private IValue makeVal(String val, CustomValue... defined) + { + if (negative) + { + negative = false; + return new Formula(val, defined).negate(); + } + else + { + for (CustomValue value : defined) + { + if (value.getToken().equals(val)) + return value; + } + return new ValueNum(val); + } + } + + private IValue makeVal(Formula val) + { + if (negative && val.operations.length == 0 && val.values[0] instanceof ValueNum) + return new ValueNum(-val.values[0].compute()); + else if (negative) + { + val.negate(); + negative = false; + return val; + } + else if (val.operations.length == 0) + return val.values[0]; + else + return val; + } + + /** + * Whether or not the equation was valid when parsed. + * + * @return whether or not the equation was valid + */ + public boolean isValid() + { + return valid; + } + + /** + * Negates the output of the formula for future computations + * + * @return the negated Formula + */ + public Formula negate() + { + negative = !negative; + return this; + } + + /** + * Tries to validate the equation, making sure values are all valid values + * + * @return true if valid, false otherwise + */ + private boolean validate() + { + // Operators between values means there should + // always be one more value than operators + if (values.length != operations.length + 1) + { + return false; + } + + // Ensure valid sub equations + for (IValue value : values) + if (value instanceof Formula && !((Formula) value).validate()) + return false; + + // Nothing went wrong + return true; + } + + /** + * Calculates the formula using the given base value and attribute. + * If the formula is invalid, this returns the value. + * + * @param input the input data + * + * @return computed value + */ + public double compute(double... input) + { + double result = values[0].compute(input); + int i; + for (i = 1; i < values.length; i++) + { + double val = values[i].compute(input); + result = operations[i - 1].compute(result, val); + } + + if (negative) result = -result; + return result; + } + + /** + * Returns the equation string for toString + * + * @return the equation string + */ + @Override + public String toString() + { + return equation; + } +} diff --git a/src/com/sucy/skill/data/formula/IOperator.java b/src/main/java/com/sucy/skill/data/formula/IOperator.java similarity index 100% rename from src/com/sucy/skill/data/formula/IOperator.java rename to src/main/java/com/sucy/skill/data/formula/IOperator.java diff --git a/src/com/sucy/skill/data/formula/IValue.java b/src/main/java/com/sucy/skill/data/formula/IValue.java similarity index 100% rename from src/com/sucy/skill/data/formula/IValue.java rename to src/main/java/com/sucy/skill/data/formula/IValue.java diff --git a/src/com/sucy/skill/data/formula/func/Abs.java b/src/main/java/com/sucy/skill/data/formula/func/Abs.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Abs.java rename to src/main/java/com/sucy/skill/data/formula/func/Abs.java diff --git a/src/com/sucy/skill/data/formula/func/Ceil.java b/src/main/java/com/sucy/skill/data/formula/func/Ceil.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Ceil.java rename to src/main/java/com/sucy/skill/data/formula/func/Ceil.java diff --git a/src/com/sucy/skill/data/formula/func/Cos.java b/src/main/java/com/sucy/skill/data/formula/func/Cos.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Cos.java rename to src/main/java/com/sucy/skill/data/formula/func/Cos.java diff --git a/src/com/sucy/skill/data/formula/func/Floor.java b/src/main/java/com/sucy/skill/data/formula/func/Floor.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Floor.java rename to src/main/java/com/sucy/skill/data/formula/func/Floor.java diff --git a/src/com/sucy/skill/data/formula/func/Root.java b/src/main/java/com/sucy/skill/data/formula/func/Root.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Root.java rename to src/main/java/com/sucy/skill/data/formula/func/Root.java diff --git a/src/main/java/com/sucy/skill/data/formula/func/Round.java b/src/main/java/com/sucy/skill/data/formula/func/Round.java new file mode 100644 index 00000000..7be7f2bc --- /dev/null +++ b/src/main/java/com/sucy/skill/data/formula/func/Round.java @@ -0,0 +1,58 @@ +/** + * SkillAPI + * com.sucy.skill.data.formula.func.Ceil + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.formula.func; + +import com.sucy.skill.data.formula.IValue; + +/** + * Ceilings a number + */ +public class Round implements IValue +{ + private IValue formula; + + /** + * @param formula wrapped formula + */ + public Round(IValue formula) + { + this.formula = formula; + } + + /** + * Gets the value using the inputs + * + * @param input the input data + * + * @return result value + */ + @Override + public double compute(double... input) + { + return Math.round(formula.compute(input)); + } +} diff --git a/src/com/sucy/skill/data/formula/func/Sign.java b/src/main/java/com/sucy/skill/data/formula/func/Sign.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Sign.java rename to src/main/java/com/sucy/skill/data/formula/func/Sign.java diff --git a/src/com/sucy/skill/data/formula/func/Sin.java b/src/main/java/com/sucy/skill/data/formula/func/Sin.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Sin.java rename to src/main/java/com/sucy/skill/data/formula/func/Sin.java diff --git a/src/com/sucy/skill/data/formula/func/Square.java b/src/main/java/com/sucy/skill/data/formula/func/Square.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Square.java rename to src/main/java/com/sucy/skill/data/formula/func/Square.java diff --git a/src/com/sucy/skill/data/formula/func/Tan.java b/src/main/java/com/sucy/skill/data/formula/func/Tan.java similarity index 100% rename from src/com/sucy/skill/data/formula/func/Tan.java rename to src/main/java/com/sucy/skill/data/formula/func/Tan.java diff --git a/src/com/sucy/skill/data/formula/operator/Addition.java b/src/main/java/com/sucy/skill/data/formula/operator/Addition.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Addition.java rename to src/main/java/com/sucy/skill/data/formula/operator/Addition.java diff --git a/src/com/sucy/skill/data/formula/operator/Division.java b/src/main/java/com/sucy/skill/data/formula/operator/Division.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Division.java rename to src/main/java/com/sucy/skill/data/formula/operator/Division.java diff --git a/src/com/sucy/skill/data/formula/operator/Exponent.java b/src/main/java/com/sucy/skill/data/formula/operator/Exponent.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Exponent.java rename to src/main/java/com/sucy/skill/data/formula/operator/Exponent.java diff --git a/src/com/sucy/skill/data/formula/operator/Log.java b/src/main/java/com/sucy/skill/data/formula/operator/Log.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Log.java rename to src/main/java/com/sucy/skill/data/formula/operator/Log.java diff --git a/src/main/java/com/sucy/skill/data/formula/operator/Maximum.java b/src/main/java/com/sucy/skill/data/formula/operator/Maximum.java new file mode 100644 index 00000000..e69c5464 --- /dev/null +++ b/src/main/java/com/sucy/skill/data/formula/operator/Maximum.java @@ -0,0 +1,48 @@ +/** + * SkillAPI + * com.sucy.skill.data.formula.operator.Addition + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.formula.operator; + +import com.sucy.skill.data.formula.IOperator; + +/** + * The addition operation used in formulas + */ +public class Maximum implements IOperator +{ + /** + * Performs the operation between the two values + * + * @param a first value + * @param b second value + * + * @return result + */ + public double compute(double a, double b) + { + return a >= b ? b : a; + } +} diff --git a/src/main/java/com/sucy/skill/data/formula/operator/Minimum.java b/src/main/java/com/sucy/skill/data/formula/operator/Minimum.java new file mode 100644 index 00000000..7adb3bed --- /dev/null +++ b/src/main/java/com/sucy/skill/data/formula/operator/Minimum.java @@ -0,0 +1,48 @@ +/** + * SkillAPI + * com.sucy.skill.data.formula.operator.Addition + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.formula.operator; + +import com.sucy.skill.data.formula.IOperator; + +/** + * The addition operation used in formulas + */ +public class Minimum implements IOperator +{ + /** + * Performs the operation between the two values + * + * @param a first value + * @param b second value + * + * @return result + */ + public double compute(double a, double b) + { + return a <= b ? b : a; + } +} diff --git a/src/com/sucy/skill/data/formula/operator/Modulo.java b/src/main/java/com/sucy/skill/data/formula/operator/Modulo.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Modulo.java rename to src/main/java/com/sucy/skill/data/formula/operator/Modulo.java diff --git a/src/com/sucy/skill/data/formula/operator/Multiplication.java b/src/main/java/com/sucy/skill/data/formula/operator/Multiplication.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Multiplication.java rename to src/main/java/com/sucy/skill/data/formula/operator/Multiplication.java diff --git a/src/com/sucy/skill/data/formula/operator/Subtraction.java b/src/main/java/com/sucy/skill/data/formula/operator/Subtraction.java similarity index 100% rename from src/com/sucy/skill/data/formula/operator/Subtraction.java rename to src/main/java/com/sucy/skill/data/formula/operator/Subtraction.java diff --git a/src/com/sucy/skill/data/formula/value/CustomValue.java b/src/main/java/com/sucy/skill/data/formula/value/CustomValue.java similarity index 96% rename from src/com/sucy/skill/data/formula/value/CustomValue.java rename to src/main/java/com/sucy/skill/data/formula/value/CustomValue.java index e833f1a3..13a257dc 100644 --- a/src/com/sucy/skill/data/formula/value/CustomValue.java +++ b/src/main/java/com/sucy/skill/data/formula/value/CustomValue.java @@ -1,81 +1,81 @@ -/** - * SkillAPI - * com.sucy.skill.data.formula.value.CustomValue - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.data.formula.value; - -import com.sucy.skill.data.formula.IValue; - -/** - * A custom defined value for a formula - */ -public class CustomValue implements IValue -{ - private String token; - private int index; - - /** - * A defined value used in formulas - * - * @param token equation token - */ - public CustomValue(String token) - { - this.token = token; - } - - /** - * Sets the argument index for the value. - * This is handled by formulas so you shouldn't - * need to use this. - * - * @param index argument index - */ - public void setIndex(int index) - { - this.index = index; - } - - /** - * @return defining token - */ - public String getToken() - { - return token; - } - - /** - * Gets the value using the inputs - * - * @param input the input data - * - * @return result value - */ - @Override - public double compute(double... input) - { - return input[index]; - } -} +/** + * SkillAPI + * com.sucy.skill.data.formula.value.CustomValue + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.formula.value; + +import com.sucy.skill.data.formula.IValue; + +/** + * A custom defined value for a formula + */ +public class CustomValue implements IValue +{ + private String token; + private int index; + + /** + * A defined value used in formulas + * + * @param token equation token + */ + public CustomValue(String token) + { + this.token = token; + } + + /** + * Sets the argument index for the value. + * This is handled by formulas so you shouldn't + * need to use this. + * + * @param index argument index + */ + public void setIndex(int index) + { + this.index = index; + } + + /** + * @return defining token + */ + public String getToken() + { + return token; + } + + /** + * Gets the value using the inputs + * + * @param input the input data + * + * @return result value + */ + @Override + public double compute(double... input) + { + return input[index]; + } +} diff --git a/src/com/sucy/skill/data/formula/value/ValueNum.java b/src/main/java/com/sucy/skill/data/formula/value/ValueNum.java similarity index 100% rename from src/com/sucy/skill/data/formula/value/ValueNum.java rename to src/main/java/com/sucy/skill/data/formula/value/ValueNum.java diff --git a/src/com/sucy/skill/data/io/ConfigIO.java b/src/main/java/com/sucy/skill/data/io/ConfigIO.java similarity index 91% rename from src/com/sucy/skill/data/io/ConfigIO.java rename to src/main/java/com/sucy/skill/data/io/ConfigIO.java index 0f510df6..14dcd0db 100644 --- a/src/com/sucy/skill/data/io/ConfigIO.java +++ b/src/main/java/com/sucy/skill/data/io/ConfigIO.java @@ -39,6 +39,8 @@ import java.util.ArrayList; import java.util.HashMap; +import org.bukkit.Bukkit; + /** * IO manager that saves/loads to a .yml configuration file */ @@ -56,7 +58,7 @@ public ConfigIO(SkillAPI plugin) public HashMap loadAll() { HashMap result = new HashMap(); - for (Player player : VersionManager.getOnlinePlayers()) { + for (Player player : Bukkit.getOnlinePlayers()) { result.put(new VersionPlayer(player).getIdString(), loadData(player)); } return result; @@ -97,6 +99,10 @@ public void saveData(PlayerAccounts data) { try { + if (data.getData(1).getClass("class") == null || data.getData(1).getClass("class").getData().getName() == null) { + Bukkit.getLogger().warning("[SkillAPI] Did not save " + data.getPlayerName() + ", class 1 was null"); + return; + } CommentedConfig config = new CommentedConfig(api, "players/" + new VersionPlayer(data.getOfflinePlayer()).getIdString()); config.clear(); diff --git a/src/com/sucy/skill/data/io/IOManager.java b/src/main/java/com/sucy/skill/data/io/IOManager.java similarity index 88% rename from src/com/sucy/skill/data/io/IOManager.java rename to src/main/java/com/sucy/skill/data/io/IOManager.java index 922818a4..ebc74c11 100644 --- a/src/com/sucy/skill/data/io/IOManager.java +++ b/src/main/java/com/sucy/skill/data/io/IOManager.java @@ -1,398 +1,424 @@ -/** - * SkillAPI - * com.sucy.skill.data.io.IOManager - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.data.io; - -import com.rit.sucy.config.parse.DataSection; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.player.*; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.log.Logger; -import com.sucy.skill.manager.ComboManager; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Base class for managers that handle saving and loading player data - */ -public abstract class IOManager -{ - private static final String - LIMIT = "limit", - ACTIVE = "active", - ACCOUNTS = "accounts", - ACCOUNT_PREFIX = "acc", - HEALTH = "health", - MANA = "mana", - CLASSES = "classes", - SKILLS = "skills", - BINDS = "binds", - LEVEL = "level", - EXP = "exp", - POINTS = "points", - SKILL_BAR = "bar", - HOVER = "hover", - EXTRA = "extra", - INSTANT = "instant", - ENABLED = "enabled", - SLOTS = "slots", - UNASSIGNED = "e", - COMBOS = "combos", - ATTRIBS = "attribs", - COOLDOWN = "cd", - HUNGER = "hunger", - ATTRIB_POINTS = "attrib-points"; - - /** - * API reference - */ - protected final SkillAPI api; - - /** - * Initializes a new IO manager - * - * @param api SkillAPI reference - */ - IOManager(SkillAPI api) - { - this.api = api; - } - - /** - * Loads player data for all online players - * - * @return loaded player data - */ - public abstract HashMap loadAll(); - - /** - * Loads data for the player - * - * @param player player to load for - * - * @return loaded player data - */ - public abstract PlayerAccounts loadData(OfflinePlayer player); - - /** - * Saves the player's data - * - * @param data data to save - */ - public abstract void saveData(PlayerAccounts data); - - /** - * Saves all player data - */ - public void saveAll() - { - for (PlayerAccounts data : SkillAPI.getPlayerAccountData().values()) - { - saveData(data); - } - } - - /** - * Loads data from the DataSection for the given player - * - * @param player player to load for - * @param file DataSection containing the account info - * - * @return the loaded player account data - */ - protected PlayerAccounts load(OfflinePlayer player, DataSection file) - { - PlayerAccounts data = new PlayerAccounts(player); - DataSection accounts = file.getSection(ACCOUNTS); - if (accounts == null) - { - data.getActiveData().endInit(); - return data; - } - for (String accountKey : accounts.keys()) - { - DataSection account = accounts.getSection(accountKey); - PlayerData acc = data.getData(Integer.parseInt(accountKey.replace(ACCOUNT_PREFIX, "")), player, true); - - // Load classes - DataSection classes = account.getSection(CLASSES); - if (classes != null) - { - for (String classKey : classes.keys()) - { - RPGClass rpgClass = SkillAPI.getClass(classKey); - if (rpgClass != null) - { - PlayerClass c = acc.setClass(rpgClass); - DataSection classData = classes.getSection(classKey); - int levels = classData.getInt(LEVEL); - if (levels > 0) - c.setLevel(levels); - c.setPoints(classData.getInt(POINTS)); - if (classData.has("total-exp")) - c.setExp(classData.getDouble("total-exp") - c.getTotalExp()); - else - c.setExp(classData.getDouble(EXP)); - } - } - } - - // Load skills - DataSection skills = account.getSection(SKILLS); - if (skills != null) - { - for (String skillKey : skills.keys()) - { - DataSection skill = skills.getSection(skillKey); - PlayerSkill skillData = acc.getSkill(skillKey); - if (skillData != null) - { - skillData.setLevel(skill.getInt(LEVEL)); - skillData.setPoints(skill.getInt(POINTS)); - skillData.addCooldown(skill.getInt(COOLDOWN, 0)); - } - } - } - - // Load skill bar - if (SkillAPI.getSettings().isSkillBarEnabled() || SkillAPI.getSettings().isUsingCombat()) - { - final DataSection skillBar = account.getSection(SKILL_BAR); - final PlayerSkillBar bar = acc.getSkillBar(); - if (skillBar != null && bar != null) - { - boolean enabled = skillBar.getBoolean(ENABLED, true); - for (final String key : skillBar.keys()) - { - final boolean[] locked = SkillAPI.getSettings().getLockedSlots(); - if (key.equals(SLOTS)) { - for (int i = 0; i < 9; i++) - if (!bar.isWeaponSlot(i) && !locked[i]) - bar.getData().remove(i + 1); - - final List slots = skillBar.getList(SLOTS); - for (final String slot : slots) { - int i = Integer.parseInt(slot); - if (!locked[i - 1]) - bar.getData().put(i, UNASSIGNED); - } - } - else if (SkillAPI.getSkill(key) != null) - bar.getData().put(skillBar.getInt(key), key); - } - - bar.applySettings(); - } - } - - // Load combos - if (SkillAPI.getSettings().isCustomCombosAllowed()) - { - DataSection combos = account.getSection(COMBOS); - PlayerCombos comboData = acc.getComboData(); - ComboManager cm = SkillAPI.getComboManager(); - if (combos != null && comboData != null) - { - for (String key : combos.keys()) - { - Skill skill = SkillAPI.getSkill(key); - if (acc.hasSkill(key) && skill != null && skill.canCast()) - { - int combo = cm.parseCombo(combos.getString(key)); - if (combo == -1) Logger.invalid("Invalid skill combo: " + combos.getString(key)); - else comboData.setSkill(skill, combo); - } - } - } - } - - // Load attributes - if (SkillAPI.getSettings().isAttributesEnabled()) - { - acc.setAttribPoints(account.getInt(ATTRIB_POINTS, 0)); - DataSection attribs = account.getSection(ATTRIBS); - if (attribs != null) - { - for (String key : attribs.keys()) - { - acc.getAttributeData().put(key, attribs.getInt(key)); - } - } - } - - // Load cast bars - if (SkillAPI.getSettings().isCastEnabled()) - { - acc.getCastBars().reset(); - acc.getCastBars().load(account.getSection(HOVER), true); - acc.getCastBars().load(account.getSection(INSTANT), false); - } - - acc.setHungerValue(account.getDouble(HUNGER, 1)); - - // Extra data - if (account.has(EXTRA)) { - acc.getExtraData().applyDefaults(account.getSection(EXTRA)); - } - - acc.endInit(); - - // Load binds - DataSection binds = account.getSection(BINDS); - if (binds != null) - { - for (String bindKey : binds.keys()) - { - acc.bind(Material.valueOf(bindKey), acc.getSkill(binds.getString(bindKey))); - } - } - } - data.setAccount(file.getInt(ACTIVE, data.getActiveId()), false); - data.getActiveData().setLastHealth(file.getDouble(HEALTH)); - data.getActiveData().setMana(file.getDouble(MANA, data.getActiveData().getMana())); - - return data; - } - - protected DataSection save(PlayerAccounts data) - { - try - { - DataSection file = new DataSection(); - file.set(LIMIT, data.getAccountLimit()); - file.set(ACTIVE, data.getActiveId()); - file.set(HEALTH, data.getActiveData().getLastHealth()); - file.set(MANA, data.getActiveData().getMana()); - DataSection accounts = file.createSection(ACCOUNTS); - for (Map.Entry entry : data.getAllData().entrySet()) - { - DataSection account = accounts.createSection(ACCOUNT_PREFIX + entry.getKey()); - PlayerData acc = entry.getValue(); - - // Save classes - DataSection classes = account.createSection(CLASSES); - for (PlayerClass c : acc.getClasses()) - { - DataSection classSection = classes.createSection(c.getData().getName()); - classSection.set(LEVEL, c.getLevel()); - classSection.set(POINTS, c.getPoints()); - classSection.set(EXP, c.getExp()); - } - - // Save skills - DataSection skills = account.createSection(SKILLS); - for (PlayerSkill skill : acc.getSkills()) - { - DataSection skillSection = skills.createSection(skill.getData().getName()); - skillSection.set(LEVEL, skill.getLevel()); - skillSection.set(POINTS, skill.getPoints()); - if (skill.isOnCooldown()) - skillSection.set(COOLDOWN, skill.getCooldown()); - } - - // Save binds - DataSection binds = account.createSection(BINDS); - for (Map.Entry bind : acc.getBinds().entrySet()) - { - if (bind.getKey() == null || bind.getValue() == null) continue; - binds.set(bind.getKey().name(), bind.getValue().getData().getName()); - } - - // Save skill bar - if ((SkillAPI.getSettings().isSkillBarEnabled() || SkillAPI.getSettings().isUsingCombat()) - && acc.getSkillBar() != null) - { - DataSection skillBar = account.createSection(SKILL_BAR); - PlayerSkillBar bar = acc.getSkillBar(); - skillBar.set(ENABLED, bar.isEnabled()); - skillBar.set(SLOTS, new ArrayList<>(bar.getData().keySet())); - for (Map.Entry slotEntry : bar.getData().entrySet()) - { - if (slotEntry.getValue().equals(UNASSIGNED)) - { - continue; - } - skillBar.set(slotEntry.getValue(), slotEntry.getKey()); - } - } - - // Save combos - if (SkillAPI.getSettings().isCustomCombosAllowed()) - { - DataSection combos = account.createSection(COMBOS); - PlayerCombos comboData = acc.getComboData(); - ComboManager cm = SkillAPI.getComboManager(); - if (combos != null && comboData != null) - { - HashMap comboMap = comboData.getSkillMap(); - for (Map.Entry combo : comboMap.entrySet()) - { - combos.set(combo.getValue(), cm.getSaveString(combo.getKey())); - } - } - } - - // Save attributes - if (SkillAPI.getSettings().isAttributesEnabled()) - { - account.set(ATTRIB_POINTS, acc.getAttributePoints()); - DataSection attribs = account.createSection(ATTRIBS); - for (String key : acc.getAttributeData().keySet()) - { - attribs.set(key, acc.getAttributeData().get(key)); - } - } - - // Save cast bars - if (SkillAPI.getSettings().isCastEnabled()) - { - acc.getCastBars().save(account.createSection(HOVER), true); - acc.getCastBars().save(account.createSection(INSTANT), false); - } - - account.set(HUNGER, acc.getHungerValue()); - - // Extra data - if (acc.getExtraData().size() > 0) { - account.set(EXTRA, acc.getExtraData()); - } - } - return file; - } - catch (Exception ex) - { - Logger.bug("Failed to save player data for " + data.getPlayer().getName()); - ex.printStackTrace(); - return null; - } - } -} +/** + * SkillAPI + * com.sucy.skill.data.io.IOManager + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.io; + +import com.rit.sucy.config.parse.DataSection; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.classes.RPGClass; +import com.sucy.skill.api.player.*; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.listener.MainListener; +import com.sucy.skill.log.Logger; +import com.sucy.skill.manager.ComboManager; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import me.neoblade298.neocore.bukkit.NeoCore; +import me.neoblade298.neocore.bukkit.InstanceType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Base class for managers that handle saving and loading player data + */ +public abstract class IOManager +{ + private static final String + LIMIT = "limit", + ACTIVE = "active", + ACCOUNTS = "accounts", + ACCOUNT_PREFIX = "acc", + HEALTH = "health", + MANA = "mana", + CLASSES = "classes", + SKILLS = "skills", + BINDS = "binds", + LEVEL = "level", + EXP = "exp", + POINTS = "points", + SKILL_BAR = "bar", + HOVER = "hover", + EXTRA = "extra", + INSTANT = "instant", + ENABLED = "enabled", + SLOTS = "slots", + UNASSIGNED = "e", + COMBOS = "combos", + ATTRIBS = "attribs", + COOLDOWN = "cd", + HUNGER = "hunger", + ATTRIB_POINTS = "attrib-points"; + private static boolean isSession = NeoCore.getInstanceType() == InstanceType.SESSIONS; + + /** + * API reference + */ + protected final SkillAPI api; + + /** + * Initializes a new IO manager + * + * @param api SkillAPI reference + */ + IOManager(SkillAPI api) + { + this.api = api; + } + + /** + * Loads player data for all online players + * + * @return loaded player data + */ + public abstract HashMap loadAll(); + + /** + * Loads data for the player + * + * @param player player to load for + * + * @return loaded player data + */ + public abstract PlayerAccounts loadData(OfflinePlayer player); + + /** + * Saves the player's data + * + * @param data data to save + */ + public abstract void saveData(PlayerAccounts data); + + /** + * Saves all player data + */ + public void saveAll() + { + for (PlayerAccounts data : SkillAPI.getPlayerAccountData().values()) + { + if (data.getPlayer() != null && data.getPlayer().isOnline() && + !MainListener.preloadingPlayers.contains(data.getOfflinePlayer().getUniqueId())) { + saveData(data); + } + } + } + + /** + * Loads data from the DataSection for the given player + * + * @param player player to load for + * @param file DataSection containing the account info + * + * @return the loaded player account data + */ + protected PlayerAccounts load(OfflinePlayer player, DataSection file) + { + PlayerAccounts data = new PlayerAccounts(player); + DataSection accounts = file.getSection(ACCOUNTS); + if (accounts == null || accounts.keys() == null) + { + data.getActiveData().endInit(); + return data; + } + for (String accountKey : accounts.keys()) + { + DataSection account = accounts.getSection(accountKey); + PlayerData acc = data.getData(Integer.parseInt(accountKey.replace(ACCOUNT_PREFIX, "")), player, true); + + // Load classes + DataSection classes = account.getSection(CLASSES); + if (classes != null) + { + for (String classKey : classes.keys()) + { + RPGClass rpgClass = SkillAPI.getClass(classKey); + if (rpgClass != null) + { + PlayerClass c = acc.setClass(rpgClass); + DataSection classData = classes.getSection(classKey); + int levels = classData.getInt(LEVEL); + if (levels > 0) + c.setLevel(levels); + c.setPoints(classData.getInt(POINTS)); + if (classData.has("total-exp")) + c.setExp(classData.getDouble("total-exp") - c.getTotalExp()); + else + c.setExp(classData.getDouble(EXP)); + } + } + } + + // Load skills + DataSection skills = account.getSection(SKILLS); + if (skills != null) + { + for (String skillKey : skills.keys()) + { + DataSection skill = skills.getSection(skillKey); + PlayerSkill skillData = acc.getSkill(skillKey); + if (skillData != null) + { + skillData.setLevel(skill.getInt(LEVEL)); + skillData.setPoints(skill.getInt(POINTS)); + if (!isSession) { + skillData.addCooldown(skill.getInt(COOLDOWN, 0)); + } + } + } + } + + // Load global skills + for (String skillKey : SkillAPI.getSettings().getGlobalSkills()) { + PlayerSkill skillData = acc.getSkill(skillKey); + if (skillData != null) + { + skillData.setLevel(1); + skillData.setPoints(0); + } + } + + // Load skill bar + if (SkillAPI.getSettings().isSkillBarEnabled() || SkillAPI.getSettings().isUsingCombat()) + { + final DataSection skillBar = account.getSection(SKILL_BAR); + final PlayerSkillBar bar = acc.getSkillBar(); + bar.setEnabled(true); + if (skillBar != null && bar != null) + { + for (final String key : skillBar.keys()) + { + final boolean[] locked = SkillAPI.getSettings().getLockedSlots(); + if (key.equals(SLOTS)) { + for (int i = 0; i < 9; i++) + if (!bar.isWeaponSlot(i) && !locked[i]) + bar.getData().remove(i + 1); + + final List slots = skillBar.getList(SLOTS); + for (final String slot : slots) { + int i = Integer.parseInt(slot); + if (!locked[i - 1]) + bar.getData().put(i, UNASSIGNED); + } + } + else if (SkillAPI.getSkill(key) != null) + bar.getData().put(skillBar.getInt(key), key); + else if (key.equals("enabled")) { + boolean enabled = skillBar.getBoolean("enabled"); + bar.setEnabled(enabled); + } + } + bar.applySettings(); + } + } + + // Load combos + if (SkillAPI.getSettings().isCustomCombosAllowed()) + { + DataSection combos = account.getSection(COMBOS); + PlayerCombos comboData = acc.getComboData(); + ComboManager cm = SkillAPI.getComboManager(); + if (combos != null && comboData != null) + { + for (String key : combos.keys()) + { + Skill skill = SkillAPI.getSkill(key); + if (acc.hasSkill(key) && skill != null && skill.canCast()) + { + int combo = cm.parseCombo(combos.getString(key)); + if (combo == -1) Logger.invalid("Invalid skill combo: " + combos.getString(key)); + else comboData.setSkill(skill, combo); + } + } + } + } + + // Load attributes + if (SkillAPI.getSettings().isAttributesEnabled()) + { + acc.setAttribPoints(account.getInt(ATTRIB_POINTS, 0)); + DataSection attribs = account.getSection(ATTRIBS); + if (attribs != null) + { + for (String key : attribs.keys()) + { + acc.getAttributeData().put(key, attribs.getInt(key)); + } + } + } + + // Load cast bars + if (SkillAPI.getSettings().isCastEnabled()) + { + acc.getCastBars().reset(); + acc.getCastBars().load(account.getSection(HOVER), true); + acc.getCastBars().load(account.getSection(INSTANT), false); + } + + acc.setHungerValue(account.getDouble(HUNGER, 1)); + + // Extra data + if (account.has(EXTRA)) { + acc.getExtraData().applyDefaults(account.getSection(EXTRA)); + } + + acc.endInit(); + + // Load binds + DataSection binds = account.getSection(BINDS); + if (binds != null) + { + for (String bindKey : binds.keys()) + { + acc.bind(Material.valueOf(bindKey), acc.getSkill(binds.getString(bindKey))); + } + } + } + data.setAccount(file.getInt(ACTIVE, data.getActiveId()), false); + data.getActiveData().setLastHealth(file.getDouble(HEALTH)); + data.getActiveData().setMana(file.getDouble(MANA, data.getActiveData().getMana())); + + return data; + } + + protected DataSection save(PlayerAccounts data) + { + try + { + DataSection file = new DataSection(); + file.set(LIMIT, data.getAccountLimit()); + file.set(ACTIVE, data.getActiveId()); + file.set(HEALTH, data.getActiveData().getLastHealth()); + file.set(MANA, data.getActiveData().getMana()); + DataSection accounts = file.createSection(ACCOUNTS); + for (Map.Entry entry : data.getAllData().entrySet()) + { + DataSection account = accounts.createSection(ACCOUNT_PREFIX + entry.getKey()); + PlayerData acc = entry.getValue(); + + // Save classes + DataSection classes = account.createSection(CLASSES); + for (PlayerClass c : acc.getClasses()) + { + DataSection classSection = classes.createSection(c.getData().getName()); + classSection.set(LEVEL, c.getLevel()); + classSection.set(POINTS, c.getPoints()); + classSection.set(EXP, c.getExp()); + } + + // Save skills + DataSection skills = account.createSection(SKILLS); + ArrayList globalSkills = SkillAPI.getSettings().getGlobalSkills(); + for (PlayerSkill skill : acc.getSkills()) + { + if (globalSkills.contains(skill.getData().getName())) { + continue; + } + DataSection skillSection = skills.createSection(skill.getData().getName()); + skillSection.set(LEVEL, skill.getLevel()); + skillSection.set(POINTS, skill.getPoints()); + if (skill.isOnCooldown()) + skillSection.set(COOLDOWN, skill.getCooldown()); + } + + // Save binds + DataSection binds = account.createSection(BINDS); + for (Map.Entry bind : acc.getBinds().entrySet()) + { + if (bind.getKey() == null || bind.getValue() == null) continue; + binds.set(bind.getKey().name(), bind.getValue().getData().getName()); + } + + // Save skill bar + if ((SkillAPI.getSettings().isSkillBarEnabled() || SkillAPI.getSettings().isUsingCombat()) + && acc.getSkillBar() != null) + { + DataSection skillBar = account.createSection(SKILL_BAR); + PlayerSkillBar bar = acc.getSkillBar(); + skillBar.set(ENABLED, bar.isEnabled()); + skillBar.set(SLOTS, new ArrayList<>(bar.getData().keySet())); + for (Map.Entry slotEntry : bar.getData().entrySet()) + { + if (slotEntry.getValue().equals(UNASSIGNED)) + { + continue; + } + skillBar.set(slotEntry.getValue(), slotEntry.getKey()); + } + } + + // Save combos + if (SkillAPI.getSettings().isCustomCombosAllowed()) + { + DataSection combos = account.createSection(COMBOS); + PlayerCombos comboData = acc.getComboData(); + ComboManager cm = SkillAPI.getComboManager(); + if (combos != null && comboData != null) + { + HashMap comboMap = comboData.getSkillMap(); + for (Map.Entry combo : comboMap.entrySet()) + { + combos.set(combo.getValue(), cm.getSaveString(combo.getKey())); + } + } + } + + // Save attributes + if (SkillAPI.getSettings().isAttributesEnabled()) + { + account.set(ATTRIB_POINTS, acc.getAttributePoints()); + DataSection attribs = account.createSection(ATTRIBS); + for (String key : acc.getAttributeData().keySet()) + { + attribs.set(key, acc.getAttributeData().get(key)); + } + } + + // Save cast bars + if (SkillAPI.getSettings().isCastEnabled()) + { + acc.getCastBars().save(account.createSection(HOVER), true); + acc.getCastBars().save(account.createSection(INSTANT), false); + } + + account.set(HUNGER, acc.getHungerValue()); + + // Extra data + if (acc.getExtraData().size() > 0) { + account.set(EXTRA, acc.getExtraData()); + } + } + return file; + } + catch (Exception ex) + { + Logger.bug("Failed to save player data for " + data.getPlayerName()); + ex.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/src/com/sucy/skill/data/io/SQLIO.java b/src/main/java/com/sucy/skill/data/io/SQLIO.java similarity index 65% rename from src/com/sucy/skill/data/io/SQLIO.java rename to src/main/java/com/sucy/skill/data/io/SQLIO.java index acc19ee5..1c69e6e9 100644 --- a/src/com/sucy/skill/data/io/SQLIO.java +++ b/src/main/java/com/sucy/skill/data/io/SQLIO.java @@ -1,160 +1,190 @@ -/** - * SkillAPI - * com.sucy.skill.data.io.SQLIO - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.data.io; - -import com.rit.sucy.config.parse.DataSection; -import com.rit.sucy.config.parse.YAMLParser; -import com.rit.sucy.sql.ColumnType; -import com.rit.sucy.sql.direct.SQLDatabase; -import com.rit.sucy.sql.direct.SQLTable; -import com.rit.sucy.version.VersionManager; -import com.rit.sucy.version.VersionPlayer; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.player.PlayerAccounts; -import com.sucy.skill.data.Settings; -import com.sucy.skill.log.Logger; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Loads player data from the SQL Database - */ -public class SQLIO extends IOManager -{ - public static final String ID = "id"; - public static final String DATA = "data"; - public static final char STRING = '√'; - - /** - * Initializes the SQL IO Manager - * - * @param api API reference - */ - public SQLIO(SkillAPI api) - { - super(api); - } - - private SQLConnection openConnection() { - SQLConnection connection = new SQLConnection(); - - Settings settings = SkillAPI.getSettings(); - connection.database = new SQLDatabase(api, settings.getSQLHost(), settings.getSQLPort(), settings.getSQLDatabase(), settings.getSQLUser(), settings.getSQLPass()); - connection.database.openConnection(); - connection.table = connection.database.createTable(api, "players"); - - connection.table.createColumn(ID, ColumnType.INCREMENT); - connection.table.createColumn(DATA, ColumnType.TEXT); - return connection; - } - - @Override - public HashMap loadAll() { - SQLConnection connection = openConnection(); - - HashMap result = new HashMap(); - for (Player player : VersionManager.getOnlinePlayers()) { - result.put(new VersionPlayer(player).getIdString(), load(connection, player)); - } - - connection.database.closeConnection(); - - return result; - } - - @Override - public PlayerAccounts loadData(OfflinePlayer player) - { - if (player == null) return null; - - SQLConnection connection = openConnection(); - - PlayerAccounts result = load(connection, player); - - connection.database.closeConnection(); - - return result; - } - - private PlayerAccounts load(SQLConnection connection, OfflinePlayer player) { - try - { - String playerKey = new VersionPlayer(player).getIdString(); - DataSection file = YAMLParser.parseText(connection.table.createEntry(playerKey).getString(DATA), STRING); - return load(player, file); - } - catch (Exception ex) - { - Logger.bug("Failed to load data from the SQL Database - " + ex.getMessage()); - return null; - } - } - - @Override - public void saveData(PlayerAccounts data) - { - SQLConnection connection = openConnection(); - saveSingle(connection, data); - connection.database.closeConnection(); - } - - @Override - public void saveAll() - { - SQLConnection connection = openConnection(); - HashMap data = SkillAPI.getPlayerAccountData(); - ArrayList keys = new ArrayList(data.keySet()); - for (String key : keys) - { - saveSingle(connection, data.get(key)); - } - connection.database.closeConnection(); - } - - private void saveSingle(SQLConnection connection, PlayerAccounts data) - { - DataSection file = save(data); - - try - { - String playerKey = new VersionPlayer(data.getOfflinePlayer()).getIdString(); - connection.table.createEntry(playerKey).set(DATA, file.toString(STRING)); - } - catch (Exception ex) - { - Logger.bug("Failed to save data for invalid player"); - } - } - - private class SQLConnection { - private SQLDatabase database; - private SQLTable table; - } -} +/** + * SkillAPI + * com.sucy.skill.data.io.SQLIO + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.data.io; + +import com.rit.sucy.config.parse.DataSection; +import com.rit.sucy.config.parse.YAMLParser; +import com.rit.sucy.sql.ColumnType; +import com.rit.sucy.sql.direct.SQLDatabase; +import com.rit.sucy.sql.direct.SQLTable; +import com.rit.sucy.version.VersionManager; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.player.PlayerAccounts; +import com.sucy.skill.data.Settings; +import com.sucy.skill.log.Logger; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.UUID; +import org.bukkit.Bukkit; + +/** + * Loads player data from the SQL Database + */ +public class SQLIO extends IOManager +{ + public static final String ID = "id"; + public static final String DATA = "data"; + public static final char QUOTE = '\''; + + private static HashMap lastSaved; + + /** + * Initializes the SQL IO Manager + * + * @param api API reference + */ + public SQLIO(SkillAPI api) + { + super(api); + lastSaved = new HashMap(); + } + + private SQLConnection openConnection() { + SQLConnection connection = new SQLConnection(); + + Settings settings = SkillAPI.getSettings(); + connection.database = new SQLDatabase(api, settings.getSQLHost(), settings.getSQLPort(), settings.getSQLDatabase(), settings.getSQLUser(), settings.getSQLPass()); + connection.database.openConnection(); + connection.table = connection.database.createTable(api, "players"); + + connection.table.createColumn(ID, ColumnType.INCREMENT); + connection.table.createColumn(DATA, ColumnType.TEXT); + return connection; + } + + @Override + public HashMap loadAll() { + SQLConnection connection = openConnection(); + + HashMap result = new HashMap(); + for (Player player : Bukkit.getOnlinePlayers()) { + result.put(player.getUniqueId().toString(), load(connection, player)); + } + + connection.database.closeConnection(); + + return result; + } + + @Override + public PlayerAccounts loadData(OfflinePlayer player) + { + if (player == null) return null; + + SQLConnection connection = openConnection(); + + PlayerAccounts result = load(connection, player); + + connection.database.closeConnection(); + + return result; + } + + private PlayerAccounts load(SQLConnection connection, OfflinePlayer player) { + String data = connection.table.createEntry(player.getUniqueId().toString()).getString(DATA); + try + { + DataSection file = YAMLParser.parseText(data, QUOTE); + return load(player, file); + } + catch (Exception ex) + { + Logger.bug("Failed to load data for " + player.getName() + " from the SQL Database - " + ex.getMessage()); + ex.printStackTrace(); + return null; + } + } + + @Override + public void saveData(PlayerAccounts data) + { + long now = System.currentTimeMillis(); + if (lastSaved.containsKey(data)) { + if (lastSaved.get(data) + 10000 >= now) { + return; + } + } + lastSaved.put(data, now); + BukkitRunnable save = new BukkitRunnable() { + public void run() { + SQLConnection connection = openConnection(); + saveSingle(connection, data); + connection.database.closeConnection(); + } + }; + save.runTaskAsynchronously(api); + } + + @Override + public void saveAll() + { + SQLConnection connection = openConnection(); + HashMap data = SkillAPI.getPlayerAccountData(); + ArrayList keys = new ArrayList(data.keySet()); + for (String key : keys) + { + // Only save online players + if (Bukkit.getPlayer(UUID.fromString(key)) != null) { + saveSingle(connection, data.get(key)); + } + } + connection.database.closeConnection(); + } + + private void saveSingle(SQLConnection connection, PlayerAccounts data) + { + long start = System.currentTimeMillis(); + if (data.getPlayer() != null && data.getPlayer().hasMetadata("NPC")) return; + if (data.getData(1).getClass("class") == null || data.getData(1).getClass("class").getData().getName() == null) { + Bukkit.getLogger().warning("[SkillAPI] Did not save " + data.getPlayerName() + ", class 1 was null"); + return; + } + + DataSection file = save(data); + + try + { + connection.table.createEntry(data.getPlayer().getUniqueId().toString()).set(DATA, file.toString(QUOTE)); + long timer = System.currentTimeMillis() - start; + Logger.log("[SkillAPI] Successfully saved " + data.getPlayerName() + " in " + timer + "ms"); + } + catch (Exception ex) + { + Logger.bug("[SkillAPI] Failed to save data for invalid player"); + ex.printStackTrace(); + } + } + + private class SQLConnection { + private SQLDatabase database; + private SQLTable table; + } +} diff --git a/src/com/sucy/skill/dynamic/ComponentRegistry.java b/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java similarity index 76% rename from src/com/sucy/skill/dynamic/ComponentRegistry.java rename to src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java index 88ac5ec6..cb8f28f8 100644 --- a/src/com/sucy/skill/dynamic/ComponentRegistry.java +++ b/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java @@ -1,398 +1,353 @@ -package com.sucy.skill.dynamic; - -import com.sucy.skill.SkillAPI; -import com.sucy.skill.dynamic.condition.ArmorCondition; -import com.sucy.skill.dynamic.condition.AttributeCondition; -import com.sucy.skill.dynamic.condition.BiomeCondition; -import com.sucy.skill.dynamic.condition.BlockCondition; -import com.sucy.skill.dynamic.condition.CastLevelCondition; -import com.sucy.skill.dynamic.condition.CeilingCondition; -import com.sucy.skill.dynamic.condition.ChanceCondition; -import com.sucy.skill.dynamic.condition.ClassCondition; -import com.sucy.skill.dynamic.condition.ClassLevelCondition; -import com.sucy.skill.dynamic.condition.CombatCondition; -import com.sucy.skill.dynamic.condition.CrouchCondition; -import com.sucy.skill.dynamic.condition.DirectionCondition; -import com.sucy.skill.dynamic.condition.ElevationCondition; -import com.sucy.skill.dynamic.condition.ElseCondition; -import com.sucy.skill.dynamic.condition.EntityTypeCondition; -import com.sucy.skill.dynamic.condition.FireCondition; -import com.sucy.skill.dynamic.condition.FlagCondition; -import com.sucy.skill.dynamic.condition.GroundCondition; -import com.sucy.skill.dynamic.condition.HealthCondition; -import com.sucy.skill.dynamic.condition.InventoryCondition; -import com.sucy.skill.dynamic.condition.ItemCondition; -import com.sucy.skill.dynamic.condition.LightCondition; -import com.sucy.skill.dynamic.condition.LoreCondition; -import com.sucy.skill.dynamic.condition.ManaCondition; -import com.sucy.skill.dynamic.condition.NameCondition; -import com.sucy.skill.dynamic.condition.OffhandCondition; -import com.sucy.skill.dynamic.condition.PermissionCondition; -import com.sucy.skill.dynamic.condition.PotionCondition; -import com.sucy.skill.dynamic.condition.SkillLevelCondition; -import com.sucy.skill.dynamic.condition.SlotCondition; -import com.sucy.skill.dynamic.condition.StatusCondition; -import com.sucy.skill.dynamic.condition.TimeCondition; -import com.sucy.skill.dynamic.condition.ToolCondition; -import com.sucy.skill.dynamic.condition.ValueCondition; -import com.sucy.skill.dynamic.condition.WaterCondition; -import com.sucy.skill.dynamic.condition.WeatherCondition; -import com.sucy.skill.dynamic.custom.CustomComponent; -import com.sucy.skill.dynamic.custom.CustomEffectComponent; -import com.sucy.skill.dynamic.custom.EditorOption; -import com.sucy.skill.dynamic.mechanic.AttributeMechanic; -import com.sucy.skill.dynamic.mechanic.BlockMechanic; -import com.sucy.skill.dynamic.mechanic.BuffMechanic; -import com.sucy.skill.dynamic.mechanic.CancelEffectMechanic; -import com.sucy.skill.dynamic.mechanic.CancelMechanic; -import com.sucy.skill.dynamic.mechanic.ChannelMechanic; -import com.sucy.skill.dynamic.mechanic.CleanseMechanic; -import com.sucy.skill.dynamic.mechanic.CommandMechanic; -import com.sucy.skill.dynamic.mechanic.CooldownMechanic; -import com.sucy.skill.dynamic.mechanic.DamageBuffMechanic; -import com.sucy.skill.dynamic.mechanic.DamageLoreMechanic; -import com.sucy.skill.dynamic.mechanic.DamageMechanic; -import com.sucy.skill.dynamic.mechanic.DefenseBuffMechanic; -import com.sucy.skill.dynamic.mechanic.DelayMechanic; -import com.sucy.skill.dynamic.mechanic.DisguiseMechanic; -import com.sucy.skill.dynamic.mechanic.DurabilityMechanic; -import com.sucy.skill.dynamic.mechanic.ExplosionMechanic; -import com.sucy.skill.dynamic.mechanic.FireMechanic; -import com.sucy.skill.dynamic.mechanic.FlagClearMechanic; -import com.sucy.skill.dynamic.mechanic.FlagMechanic; -import com.sucy.skill.dynamic.mechanic.FlagToggleMechanic; -import com.sucy.skill.dynamic.mechanic.FoodMechanic; -import com.sucy.skill.dynamic.mechanic.ForgetTargetsMechanic; -import com.sucy.skill.dynamic.mechanic.HealMechanic; -import com.sucy.skill.dynamic.mechanic.HealthSetMechanic; -import com.sucy.skill.dynamic.mechanic.HeldItemMechanic; -import com.sucy.skill.dynamic.mechanic.ImmunityMechanic; -import com.sucy.skill.dynamic.mechanic.InterruptMechanic; -import com.sucy.skill.dynamic.mechanic.ItemMechanic; -import com.sucy.skill.dynamic.mechanic.ItemProjectileMechanic; -import com.sucy.skill.dynamic.mechanic.ItemRemoveMechanic; -import com.sucy.skill.dynamic.mechanic.LaunchMechanic; -import com.sucy.skill.dynamic.mechanic.LightningMechanic; -import com.sucy.skill.dynamic.mechanic.ManaMechanic; -import com.sucy.skill.dynamic.mechanic.MessageMechanic; -import com.sucy.skill.dynamic.mechanic.ParticleAnimationMechanic; -import com.sucy.skill.dynamic.mechanic.ParticleEffectMechanic; -import com.sucy.skill.dynamic.mechanic.ParticleMechanic; -import com.sucy.skill.dynamic.mechanic.ParticleProjectileMechanic; -import com.sucy.skill.dynamic.mechanic.PassiveMechanic; -import com.sucy.skill.dynamic.mechanic.PermissionMechanic; -import com.sucy.skill.dynamic.mechanic.PotionMechanic; -import com.sucy.skill.dynamic.mechanic.PotionProjectileMechanic; -import com.sucy.skill.dynamic.mechanic.ProjectileMechanic; -import com.sucy.skill.dynamic.mechanic.PurgeMechanic; -import com.sucy.skill.dynamic.mechanic.PushMechanic; -import com.sucy.skill.dynamic.mechanic.RememberTargetsMechanic; -import com.sucy.skill.dynamic.mechanic.RepeatMechanic; -import com.sucy.skill.dynamic.mechanic.SoundMechanic; -import com.sucy.skill.dynamic.mechanic.SpeedMechanic; -import com.sucy.skill.dynamic.mechanic.StatusMechanic; -import com.sucy.skill.dynamic.mechanic.TauntMechanic; -import com.sucy.skill.dynamic.mechanic.TriggerMechanic; -import com.sucy.skill.dynamic.mechanic.ValueAddMechanic; -import com.sucy.skill.dynamic.mechanic.ValueAttributeMechanic; -import com.sucy.skill.dynamic.mechanic.ValueCopyMechanic; -import com.sucy.skill.dynamic.mechanic.ValueDistanceMechanic; -import com.sucy.skill.dynamic.mechanic.ValueHealthMechanic; -import com.sucy.skill.dynamic.mechanic.ValueLocationMechanic; -import com.sucy.skill.dynamic.mechanic.ValueLoreMechanic; -import com.sucy.skill.dynamic.mechanic.ValueLoreSlotMechanic; -import com.sucy.skill.dynamic.mechanic.ValueManaMechanic; -import com.sucy.skill.dynamic.mechanic.ValueMultiplyMechanic; -import com.sucy.skill.dynamic.mechanic.ValuePlaceholderMechanic; -import com.sucy.skill.dynamic.mechanic.ValueRandomMechanic; -import com.sucy.skill.dynamic.mechanic.ValueSetMechanic; -import com.sucy.skill.dynamic.mechanic.WarpLocMechanic; -import com.sucy.skill.dynamic.mechanic.WarpMechanic; -import com.sucy.skill.dynamic.mechanic.WarpRandomMechanic; -import com.sucy.skill.dynamic.mechanic.WarpSwapMechanic; -import com.sucy.skill.dynamic.mechanic.WarpTargetMechanic; -import com.sucy.skill.dynamic.mechanic.WarpValueMechanic; -import com.sucy.skill.dynamic.mechanic.WolfMechanic; -import com.sucy.skill.dynamic.target.AreaTarget; -import com.sucy.skill.dynamic.target.ConeTarget; -import com.sucy.skill.dynamic.target.LinearTarget; -import com.sucy.skill.dynamic.target.LocationTarget; -import com.sucy.skill.dynamic.target.NearestTarget; -import com.sucy.skill.dynamic.target.OffsetTarget; -import com.sucy.skill.dynamic.target.RememberTarget; -import com.sucy.skill.dynamic.target.SelfTarget; -import com.sucy.skill.dynamic.target.SingleTarget; -import com.sucy.skill.dynamic.trigger.BlockBreakTrigger; -import com.sucy.skill.dynamic.trigger.BlockPlaceTrigger; -import com.sucy.skill.dynamic.trigger.CrouchTrigger; -import com.sucy.skill.dynamic.trigger.DeathTrigger; -import com.sucy.skill.dynamic.trigger.EnvironmentalTrigger; -import com.sucy.skill.dynamic.trigger.KillTrigger; -import com.sucy.skill.dynamic.trigger.LandTrigger; -import com.sucy.skill.dynamic.trigger.LaunchTrigger; -import com.sucy.skill.dynamic.trigger.MoveTrigger; -import com.sucy.skill.dynamic.trigger.PhysicalDealtTrigger; -import com.sucy.skill.dynamic.trigger.PhysicalTakenTrigger; -import com.sucy.skill.dynamic.trigger.SkillDealtTrigger; -import com.sucy.skill.dynamic.trigger.SkillTakenTrigger; -import com.sucy.skill.dynamic.trigger.Trigger; -import org.bukkit.event.Event; -import org.bukkit.plugin.EventExecutor; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - -/** - * SkillAPI © 2018 - * com.sucy.skill.dynamic.ComponentRegistry - */ -public class ComponentRegistry { - - static final Map>> COMPONENTS = new EnumMap<>(ComponentType.class); - - static final Map> TRIGGERS = new HashMap<>(); - private static final Map, EventExecutor> EXECUTORS = new HashMap<>(); - - public static Trigger getTrigger(final String key) { - return TRIGGERS.get(key.toUpperCase().replace(' ', '_')); - } - - static EffectComponent getComponent(final ComponentType type, final String key) { - final Class componentClass = COMPONENTS.get(type).get(key.toLowerCase()); - if (componentClass == null) { - throw new IllegalArgumentException("Invalid component key - " + key); - } - try { - return (EffectComponent) componentClass.newInstance(); - } catch (final Exception ex) { - throw new IllegalArgumentException("Invalid component - does not have a default constructor"); - } - } - - static EventExecutor getExecutor(final Trigger trigger) { - return EXECUTORS.get(trigger); - } - - @SuppressWarnings("unchecked") - public static void register(final Trigger trigger) { - if (getTrigger(trigger.getKey()) != null) { - throw new IllegalArgumentException("Trigger with key " + trigger.getKey() + " already exists"); - } else if (trigger.getKey().contains("-")) { - throw new IllegalArgumentException(trigger.getKey() + " is not a valid key: must not contain dashes"); - } - - TRIGGERS.put(trigger.getKey(), trigger); - EXECUTORS.put(trigger, (listener, event) -> { - if (!trigger.getEvent().isInstance(event)) return; - ((TriggerHandler) listener).apply((T) event, trigger); - }); - } - - public static void register(final CustomEffectComponent component) { - register((EffectComponent) component); - } - - public static void save() { - final StringBuilder builder = new StringBuilder("["); - TRIGGERS.values().forEach(trigger -> append(trigger, builder)); - COMPONENTS.forEach((type, map) -> map.keySet().forEach(key -> append(getComponent(type, key), builder))); - if (builder.length() > 2) { - builder.replace(builder.length() - 1, builder.length(), "]"); - } else { - builder.append(']'); - } - - final File file = new File(SkillAPI.getPlugin(SkillAPI.class).getDataFolder(), "tool-config.json"); - try (final FileOutputStream out = new FileOutputStream(file)) { - final BufferedWriter write = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); - write.write(builder.toString()); - write.close(); - } catch (Exception var4) { - var4.printStackTrace(); - } - } - - private static void append(final Object obj, final StringBuilder builder) { - if (!(obj instanceof CustomComponent)) { - return; - } - - final CustomComponent component = (CustomComponent) obj; - builder.append("{\"type\":\"").append(component.getType().name()) - .append("\",\"key\":\"").append(component.getKey()) - .append("\",\"display\":\"").append(component.getDisplayName()) - .append("\",\"container\":\"").append(component.isContainer()) - .append("\",\"description\":\"").append(component.getDescription()) - .append("\",\"options\":["); - - boolean first = true; - for (EditorOption option : component.getOptions()) { - if (!first) { - builder.append(','); - } - first = false; - - builder.append("{\"type\":\"").append(option.type) - .append("\",\"key\":\"").append(option.key) - .append("\",\"display\":\"").append(option.name) - .append("\",\"description\":\"").append(option.description) - .append("\""); - option.extra.forEach((key, value) -> builder.append(",\"").append(key).append("\":").append(value)); - builder.append("}"); - } - - builder.append("]},"); - } - - private static void register(final EffectComponent component) { - COMPONENTS.computeIfAbsent(component.getType(), t -> new HashMap<>()) - .put(component.getKey().toLowerCase(), component.getClass()); - } - - static { - - // Triggers - register(new BlockBreakTrigger()); - register(new BlockPlaceTrigger()); - register(new CrouchTrigger()); - register(new DeathTrigger()); - register(new EnvironmentalTrigger()); - register(new KillTrigger()); - register(new LandTrigger()); - register(new LaunchTrigger()); - register(new MoveTrigger()); - register(new PhysicalDealtTrigger()); - register(new PhysicalTakenTrigger()); - register(new SkillDealtTrigger()); - register(new SkillTakenTrigger()); - - // Targets - register(new AreaTarget()); - register(new ConeTarget()); - register(new LinearTarget()); - register(new LocationTarget()); - register(new NearestTarget()); - register(new OffsetTarget()); - register(new RememberTarget()); - register(new SelfTarget()); - register(new SingleTarget()); - - // Conditions - register(new ArmorCondition()); - register(new AttributeCondition()); - register(new BiomeCondition()); - register(new BlockCondition()); - register(new CastLevelCondition()); - register(new CeilingCondition()); - register(new ChanceCondition()); - register(new ClassCondition()); - register(new ClassLevelCondition()); - register(new CombatCondition()); - register(new CrouchCondition()); - register(new DirectionCondition()); - register(new ElevationCondition()); - register(new ElseCondition()); - register(new EntityTypeCondition()); - register(new FireCondition()); - register(new FlagCondition()); - register(new GroundCondition()); - register(new HealthCondition()); - register(new InventoryCondition()); - register(new ItemCondition()); - register(new LightCondition()); - register(new LoreCondition()); - register(new ManaCondition()); - register(new NameCondition()); - register(new OffhandCondition()); - register(new PermissionCondition()); - register(new PotionCondition()); - register(new SkillLevelCondition()); - register(new SlotCondition()); - register(new StatusCondition()); - register(new TimeCondition()); - register(new ToolCondition()); - register(new ValueCondition()); - register(new WaterCondition()); - register(new WeatherCondition()); - - // Mechanics - register(new AttributeMechanic()); - register(new BlockMechanic()); - register(new BuffMechanic()); - register(new CancelEffectMechanic()); - register(new CancelMechanic()); - register(new ChannelMechanic()); - register(new CleanseMechanic()); - register(new CommandMechanic()); - register(new CooldownMechanic()); - register(new DamageMechanic()); - register(new DamageBuffMechanic()); - register(new DamageLoreMechanic()); - register(new DefenseBuffMechanic()); - register(new DelayMechanic()); - register(new DisguiseMechanic()); - register(new DurabilityMechanic()); - register(new ExplosionMechanic()); - register(new FireMechanic()); - register(new FlagMechanic()); - register(new FlagClearMechanic()); - register(new FlagToggleMechanic()); - register(new FoodMechanic()); - register(new ForgetTargetsMechanic()); - register(new HealMechanic()); - register(new HealthSetMechanic()); - register(new HeldItemMechanic()); - register(new ImmunityMechanic()); - register(new InterruptMechanic()); - register(new ItemMechanic()); - register(new ItemProjectileMechanic()); - register(new ItemRemoveMechanic()); - register(new LaunchMechanic()); - register(new LightningMechanic()); - register(new ManaMechanic()); - register(new MessageMechanic()); - register(new ParticleMechanic()); - register(new ParticleAnimationMechanic()); - register(new ParticleEffectMechanic()); - register(new ParticleProjectileMechanic()); - register(new PassiveMechanic()); - register(new PermissionMechanic()); - register(new PotionMechanic()); - register(new PotionProjectileMechanic()); - register(new ProjectileMechanic()); - register(new PurgeMechanic()); - register(new PushMechanic()); - register(new RememberTargetsMechanic()); - register(new RepeatMechanic()); - register(new SpeedMechanic()); - register(new SoundMechanic()); - register(new StatusMechanic()); - register(new TauntMechanic()); - register(new TriggerMechanic()); - register(new ValueAddMechanic()); - register(new ValueAttributeMechanic()); - register(new ValueCopyMechanic()); - register(new ValueDistanceMechanic()); - register(new ValueHealthMechanic()); - register(new ValueLocationMechanic()); - register(new ValueLoreMechanic()); - register(new ValueLoreSlotMechanic()); - register(new ValueManaMechanic()); - register(new ValueMultiplyMechanic()); - register(new ValuePlaceholderMechanic()); - register(new ValueRandomMechanic()); - register(new ValueSetMechanic()); - register(new WarpMechanic()); - register(new WarpLocMechanic()); - register(new WarpRandomMechanic()); - register(new WarpSwapMechanic()); - register(new WarpTargetMechanic()); - register(new WarpValueMechanic()); - register(new WolfMechanic()); - } -} +package com.sucy.skill.dynamic; + +import com.sucy.skill.SkillAPI; +import com.sucy.skill.dynamic.condition.ArmorCondition; +import com.sucy.skill.dynamic.condition.AttributeCondition; +import com.sucy.skill.dynamic.condition.BiomeCondition; +import com.sucy.skill.dynamic.condition.BlockCondition; +import com.sucy.skill.dynamic.condition.CastLevelCondition; +import com.sucy.skill.dynamic.condition.CeilingCondition; +import com.sucy.skill.dynamic.condition.ChanceCondition; +import com.sucy.skill.dynamic.condition.ClassCondition; +import com.sucy.skill.dynamic.condition.ClassLevelCondition; +import com.sucy.skill.dynamic.condition.CombatCondition; +import com.sucy.skill.dynamic.condition.CrouchCondition; +import com.sucy.skill.dynamic.condition.DirectionCondition; +import com.sucy.skill.dynamic.condition.ElevationCondition; +import com.sucy.skill.dynamic.condition.ElseCondition; +import com.sucy.skill.dynamic.condition.EntityTypeCondition; +import com.sucy.skill.dynamic.condition.FireCondition; +import com.sucy.skill.dynamic.condition.FlagCondition; +import com.sucy.skill.dynamic.condition.GroundCondition; +import com.sucy.skill.dynamic.condition.HealthCondition; +import com.sucy.skill.dynamic.condition.InventoryCondition; +import com.sucy.skill.dynamic.condition.ItemCondition; +import com.sucy.skill.dynamic.condition.LightCondition; +import com.sucy.skill.dynamic.condition.LoreCondition; +import com.sucy.skill.dynamic.condition.ManaCondition; +import com.sucy.skill.dynamic.condition.NameCondition; +import com.sucy.skill.dynamic.condition.OffhandCondition; +import com.sucy.skill.dynamic.condition.PermissionCondition; +import com.sucy.skill.dynamic.condition.PotionCondition; +import com.sucy.skill.dynamic.condition.SkillLevelCondition; +import com.sucy.skill.dynamic.condition.SlotCondition; +import com.sucy.skill.dynamic.condition.StatusCondition; +import com.sucy.skill.dynamic.condition.TimeCondition; +import com.sucy.skill.dynamic.condition.ToolCondition; +import com.sucy.skill.dynamic.condition.ValueCondition; +import com.sucy.skill.dynamic.condition.WaterCondition; +import com.sucy.skill.dynamic.condition.WeatherCondition; +import com.sucy.skill.dynamic.custom.CustomComponent; +import com.sucy.skill.dynamic.custom.CustomEffectComponent; +import com.sucy.skill.dynamic.custom.EditorOption; +import com.sucy.skill.dynamic.mechanic.*; +import com.sucy.skill.dynamic.target.AreaTarget; +import com.sucy.skill.dynamic.target.ConeTarget; +import com.sucy.skill.dynamic.target.LinearTarget; +import com.sucy.skill.dynamic.target.LocationTarget; +import com.sucy.skill.dynamic.target.NearestTarget; +import com.sucy.skill.dynamic.target.OffsetTarget; +import com.sucy.skill.dynamic.target.RememberTarget; +import com.sucy.skill.dynamic.target.SelfTarget; +import com.sucy.skill.dynamic.target.SingleTarget; +import com.sucy.skill.dynamic.trigger.BlockBreakTrigger; +import com.sucy.skill.dynamic.trigger.BlockPlaceTrigger; +import com.sucy.skill.dynamic.trigger.AccountChangeTrigger; +import com.sucy.skill.dynamic.trigger.ClickComboTrigger; +import com.sucy.skill.dynamic.trigger.CrouchTrigger; +import com.sucy.skill.dynamic.trigger.DamageDeathTrigger; +import com.sucy.skill.dynamic.trigger.DeathTrigger; +import com.sucy.skill.dynamic.trigger.EnvironmentalTrigger; +import com.sucy.skill.dynamic.trigger.FlagSetTrigger; +import com.sucy.skill.dynamic.trigger.KillTrigger; +import com.sucy.skill.dynamic.trigger.LandTrigger; +import com.sucy.skill.dynamic.trigger.LaunchTrigger; +import com.sucy.skill.dynamic.trigger.LeftClickTrigger; +import com.sucy.skill.dynamic.trigger.LoadTrigger; +import com.sucy.skill.dynamic.trigger.MoveTrigger; +import com.sucy.skill.dynamic.trigger.PhysicalDealtTrigger; +import com.sucy.skill.dynamic.trigger.PhysicalTakenTrigger; +import com.sucy.skill.dynamic.trigger.PotionApplyTrigger; +import com.sucy.skill.dynamic.trigger.RightClickEntityTrigger; +import com.sucy.skill.dynamic.trigger.RightClickTrigger; +import com.sucy.skill.dynamic.trigger.ShootBowTrigger; +import com.sucy.skill.dynamic.trigger.SkillCastTrigger; +import com.sucy.skill.dynamic.trigger.SkillDealtTrigger; +import com.sucy.skill.dynamic.trigger.SkillHealTrigger; +import com.sucy.skill.dynamic.trigger.SkillTakenTrigger; +import com.sucy.skill.dynamic.trigger.Trigger; +import org.bukkit.event.Event; +import org.bukkit.plugin.EventExecutor; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.ComponentRegistry + */ +public class ComponentRegistry { + + static final Map>> COMPONENTS = new EnumMap<>(ComponentType.class); + + static final Map> TRIGGERS = new HashMap<>(); + private static final Map, EventExecutor> EXECUTORS = new HashMap<>(); + + public static Trigger getTrigger(final String key) { + return TRIGGERS.get(key.toUpperCase().replace(' ', '_')); + } + + static EffectComponent getComponent(final ComponentType type, final String key) { + final Class componentClass = COMPONENTS.get(type).get(key.toLowerCase()); + if (componentClass == null) { + throw new IllegalArgumentException("Invalid component key - " + key); + } + try { + return (EffectComponent) componentClass.newInstance(); + } catch (final Exception ex) { + throw new IllegalArgumentException("Invalid component - does not have a default constructor"); + } + } + + static EventExecutor getExecutor(final Trigger trigger) { + return EXECUTORS.get(trigger); + } + + @SuppressWarnings("unchecked") + public static void register(final Trigger trigger) { + if (getTrigger(trigger.getKey()) != null) { + throw new IllegalArgumentException("Trigger with key " + trigger.getKey() + " already exists"); + } else if (trigger.getKey().contains("-")) { + throw new IllegalArgumentException(trigger.getKey() + " is not a valid key: must not contain dashes"); + } + + TRIGGERS.put(trigger.getKey(), trigger); + EXECUTORS.put(trigger, (listener, event) -> { + if (!trigger.getEvent().isInstance(event)) return; + ((TriggerHandler) listener).apply((T) event, trigger); + }); + } + + public static void register(final CustomEffectComponent component) { + register((EffectComponent) component); + } + + public static void save() { + final StringBuilder builder = new StringBuilder("["); + TRIGGERS.values().forEach(trigger -> append(trigger, builder)); + COMPONENTS.forEach((type, map) -> map.keySet().forEach(key -> append(getComponent(type, key), builder))); + if (builder.length() > 2) { + builder.replace(builder.length() - 1, builder.length(), "]"); + } else { + builder.append(']'); + } + + final File file = new File(SkillAPI.getPlugin(SkillAPI.class).getDataFolder(), "tool-config.json"); + try (final FileOutputStream out = new FileOutputStream(file)) { + final BufferedWriter write = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); + write.write(builder.toString()); + write.close(); + } catch (Exception var4) { + var4.printStackTrace(); + } + } + + private static void append(final Object obj, final StringBuilder builder) { + if (!(obj instanceof CustomComponent)) { + return; + } + + final CustomComponent component = (CustomComponent) obj; + builder.append("{\"type\":\"").append(component.getType().name()) + .append("\",\"key\":\"").append(component.getKey()) + .append("\",\"display\":\"").append(component.getDisplayName()) + .append("\",\"container\":\"").append(component.isContainer()) + .append("\",\"description\":\"").append(component.getDescription()) + .append("\",\"options\":["); + + boolean first = true; + for (EditorOption option : component.getOptions()) { + if (!first) { + builder.append(','); + } + first = false; + + builder.append("{\"type\":\"").append(option.type) + .append("\",\"key\":\"").append(option.key) + .append("\",\"display\":\"").append(option.name) + .append("\",\"description\":\"").append(option.description) + .append("\""); + option.extra.forEach((key, value) -> builder.append(",\"").append(key).append("\":").append(value)); + builder.append("}"); + } + + builder.append("]},"); + } + + private static void register(final EffectComponent component) { + COMPONENTS.computeIfAbsent(component.getType(), t -> new HashMap<>()) + .put(component.getKey().toLowerCase(), component.getClass()); + } + + static { + + // Triggers + register(new BlockBreakTrigger()); + register(new BlockPlaceTrigger()); + register(new CrouchTrigger()); + register(new DeathTrigger()); + register(new EnvironmentalTrigger()); + register(new KillTrigger()); + register(new LandTrigger()); + register(new LaunchTrigger()); + register(new MoveTrigger()); + register(new PhysicalDealtTrigger()); + register(new PhysicalTakenTrigger()); + register(new SkillDealtTrigger()); + register(new SkillTakenTrigger()); + + // Custom Triggers + register(new SkillCastTrigger()); + register(new SkillHealTrigger()); + register(new LeftClickTrigger()); + register(new RightClickEntityTrigger()); + register(new RightClickTrigger()); + register(new FlagSetTrigger()); + register(new PotionApplyTrigger()); + register(new DamageDeathTrigger()); + register(new ClickComboTrigger()); + register(new LoadTrigger()); + register(new AccountChangeTrigger()); + register(new ShootBowTrigger()); + + // Targets + register(new AreaTarget()); + register(new ConeTarget()); + register(new LinearTarget()); + register(new LocationTarget()); + register(new NearestTarget()); + register(new OffsetTarget()); + register(new RememberTarget()); + register(new SelfTarget()); + register(new SingleTarget()); + + // Conditions + register(new ArmorCondition()); + register(new AttributeCondition()); + register(new BiomeCondition()); + register(new BlockCondition()); + register(new CastLevelCondition()); + register(new CeilingCondition()); + register(new ChanceCondition()); + register(new ClassCondition()); + register(new ClassLevelCondition()); + register(new CombatCondition()); + register(new CrouchCondition()); + register(new DirectionCondition()); + register(new ElevationCondition()); + register(new ElseCondition()); + register(new EntityTypeCondition()); + register(new FireCondition()); + register(new FlagCondition()); + register(new GroundCondition()); + register(new HealthCondition()); + register(new InventoryCondition()); + register(new ItemCondition()); + register(new LightCondition()); + register(new LoreCondition()); + register(new ManaCondition()); + register(new NameCondition()); + register(new OffhandCondition()); + register(new PermissionCondition()); + register(new PotionCondition()); + register(new SkillLevelCondition()); + register(new SlotCondition()); + register(new StatusCondition()); + register(new TimeCondition()); + register(new ToolCondition()); + register(new ValueCondition()); + register(new WaterCondition()); + register(new WeatherCondition()); + + // Mechanics + register(new AttributeMechanic()); + register(new BlockMechanic()); + register(new BuffMechanic()); + register(new CancelEffectMechanic()); + register(new CancelMechanic()); + register(new ChannelMechanic()); + register(new CleanseMechanic()); + register(new CommandMechanic()); + register(new CooldownMechanic()); + register(new DamageMechanic()); + register(new DamageBuffMechanic()); + register(new DamageLoreMechanic()); + register(new DefenseBuffMechanic()); + register(new DelayMechanic()); + register(new DisguiseMechanic()); + register(new DurabilityMechanic()); + register(new ExplosionMechanic()); + register(new FireMechanic()); + register(new FlagMechanic()); + register(new FlagClearMechanic()); + register(new FlagToggleMechanic()); + register(new FoodMechanic()); + register(new ForgetTargetsMechanic()); + register(new HealMechanic()); + register(new HealthSetMechanic()); + register(new HeldItemMechanic()); + register(new ImmunityMechanic()); + register(new InterruptMechanic()); + register(new ItemMechanic()); + register(new ItemProjectileMechanic()); + register(new ItemRemoveMechanic()); + register(new LaunchMechanic()); + register(new LightningMechanic()); + register(new ManaMechanic()); + register(new MessageMechanic()); + register(new ParticleMechanic()); + register(new ParticleAnimationMechanic()); + register(new ParticleEffectMechanic()); + register(new ParticleLineMechanic()); + register(new ParticleProjectileMechanic()); + register(new PassiveMechanic()); + register(new PermissionMechanic()); + register(new PotionMechanic()); + register(new PotionProjectileMechanic()); + register(new ProjectileMechanic()); + register(new PurgeMechanic()); + register(new PushMechanic()); + register(new RememberTargetsMechanic()); + register(new RepeatMechanic()); + register(new SpeedMechanic()); + register(new SoundMechanic()); + register(new StatusMechanic()); + register(new TauntMechanic()); + register(new TriggerMechanic()); + register(new ValueAddMechanic()); + register(new ValueAttributeMechanic()); + register(new ValueCopyMechanic()); + register(new ValueDistanceMechanic()); + register(new ValueHealthMechanic()); + register(new ValueLocationMechanic()); + register(new ValueLoreMechanic()); + register(new ValueLoreSlotMechanic()); + register(new ValueManaMechanic()); + register(new ValueMultiplyMechanic()); + register(new ValuePlaceholderMechanic()); + register(new ValueRandomMechanic()); + register(new ValueSetMechanic()); + register(new WarpMechanic()); + register(new WarpLocMechanic()); + register(new WarpRandomMechanic()); + register(new WarpSwapMechanic()); + register(new WarpTargetMechanic()); + register(new WarpValueMechanic()); + register(new WolfMechanic()); + } +} diff --git a/src/com/sucy/skill/dynamic/ComponentType.java b/src/main/java/com/sucy/skill/dynamic/ComponentType.java similarity index 100% rename from src/com/sucy/skill/dynamic/ComponentType.java rename to src/main/java/com/sucy/skill/dynamic/ComponentType.java diff --git a/src/com/sucy/skill/dynamic/DynamicClass.java b/src/main/java/com/sucy/skill/dynamic/DynamicClass.java similarity index 100% rename from src/com/sucy/skill/dynamic/DynamicClass.java rename to src/main/java/com/sucy/skill/dynamic/DynamicClass.java diff --git a/src/com/sucy/skill/dynamic/DynamicSkill.java b/src/main/java/com/sucy/skill/dynamic/DynamicSkill.java similarity index 89% rename from src/com/sucy/skill/dynamic/DynamicSkill.java rename to src/main/java/com/sucy/skill/dynamic/DynamicSkill.java index c6e81996..0749b1a0 100644 --- a/src/com/sucy/skill/dynamic/DynamicSkill.java +++ b/src/main/java/com/sucy/skill/dynamic/DynamicSkill.java @@ -30,13 +30,18 @@ import com.rit.sucy.config.parse.DataSection; import com.rit.sucy.text.TextFormatter; import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.event.PlayerCriticalCheckEvent; +import com.sucy.skill.api.event.PlayerCriticalSuccessEvent; import com.sucy.skill.api.skills.PassiveSkill; import com.sucy.skill.api.skills.Skill; import com.sucy.skill.api.skills.SkillShot; import com.sucy.skill.cast.IIndicator; import com.sucy.skill.dynamic.trigger.TriggerComponent; import com.sucy.skill.log.Logger; + +import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; @@ -46,6 +51,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import static com.sucy.skill.dynamic.ComponentRegistry.getTrigger; @@ -58,6 +64,7 @@ public class DynamicSkill extends Skill implements SkillShot, PassiveSkill, List private final Map active = new HashMap<>(); private static final HashMap> castData = new HashMap<>(); + private static Random gen = new Random(); private TriggerComponent castTrigger; private TriggerComponent initializeTrigger; @@ -186,7 +193,15 @@ public static void clearCastData(final LivingEntity entity) { */ public void registerEvents(final SkillAPI plugin) { for (final TriggerHandler triggerHandler : triggers) { - triggerHandler.register(plugin); + if (triggerHandler.getTrigger().getKey().equals("LEFT_CLICK")) { + triggerHandler.registerNoIgnore(plugin); + } + else if (triggerHandler.getTrigger().getKey().equals("RIGHT_CLICK")) { + triggerHandler.registerNoIgnore(plugin); + } + else { + triggerHandler.register(plugin); + } } } @@ -316,7 +331,7 @@ protected Object getAttr(final LivingEntity caster, final String key, final int final String[] path = key.split("\\."); final String attr = path[1].toLowerCase(); if (attribKeys.containsKey(path[0]) && attribKeys.get(path[0]).settings.has(attr)) { - return format(attribKeys.get(path[0]).parseValues(caster, attr, level, 0)); + return format(attribKeys.get(path[0]).parseValues(caster, attr, level, 0, 0)); } else { return 0; } } @@ -329,7 +344,24 @@ private boolean trigger( final LivingEntity target, final int level, final TriggerComponent component) { - return component != null && component.trigger(user, target, level); + if (component == null) return false; + double critChance = component.getSettings().getDouble("crit-chance", 0); + double augmentCritChance = critChance; + + if (user instanceof Player && critChance > 0) { + PlayerCriticalCheckEvent e = new PlayerCriticalCheckEvent(SkillAPI.getPlayerData((Player) user), critChance); + Bukkit.getPluginManager().callEvent(e); + augmentCritChance = e.getChance(); + } + + boolean isCrit = augmentCritChance > gen.nextDouble(); + critChance = isCrit ? critChance : 0; + boolean success = component.trigger(user, target, level, critChance); + if (success && isCrit) { + ((Player) user).playSound(user.getLocation(), Sound.ITEM_TRIDENT_RIPTIDE_1, 1.0F, 1.0F); + Bukkit.getPluginManager().callEvent(new PlayerCriticalSuccessEvent(SkillAPI.getPlayerData((Player) user), critChance)); + } + return success; } /** diff --git a/src/com/sucy/skill/dynamic/EffectComponent.java b/src/main/java/com/sucy/skill/dynamic/EffectComponent.java similarity index 91% rename from src/com/sucy/skill/dynamic/EffectComponent.java rename to src/main/java/com/sucy/skill/dynamic/EffectComponent.java index 11a9502f..a9fc8d8a 100644 --- a/src/com/sucy/skill/dynamic/EffectComponent.java +++ b/src/main/java/com/sucy/skill/dynamic/EffectComponent.java @@ -30,11 +30,14 @@ import com.rit.sucy.mobs.MobManager; import com.sucy.skill.SkillAPI; import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.PlayerCriticalDamageEvent; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.api.player.PlayerSkill; import com.sucy.skill.cast.IIndicator; import com.sucy.skill.cast.IndicatorType; import com.sucy.skill.log.Logger; + +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -71,6 +74,8 @@ public abstract class EffectComponent { * Type of indicators to show */ protected IndicatorType indicatorType; + + protected boolean onlyCaster; /** * Whether or not the component has preview effects @@ -127,21 +132,29 @@ private boolean hasEffect() { * @param key key of the value to grab * @param level level of the skill * @param fallback default value for the attribute + * @param critChance If >0, crit happened, and this is the decimal chance * * @return the value with attribute modifications if applicable */ - protected double parseValues(LivingEntity caster, String key, int level, double fallback) { + protected double parseValues(LivingEntity caster, String key, int level, double fallback, double critChance) { double base = getNum(caster, key + "-base", fallback); double scale = getNum(caster, key + "-scale", 0); - double value = base + (level - 1) * scale; + double oldValue = base + (level - 1) * scale; + double newValue = oldValue; // Apply global modifiers if (SkillAPI.getSettings().isAttributesEnabled() && caster instanceof Player) { PlayerData data = SkillAPI.getPlayerData((Player) caster); - value = data.scaleDynamic(this, key, value); + newValue += data.scaleDynamic(this, key, oldValue); } - return value; + return newValue; + } + + protected double getValue(LivingEntity caster, String key, int level, double fallback) { + double base = getNum(caster, key + "-base", fallback); + double scale = getNum(caster, key + "-scale", 0); + return base + (level - 1) * scale; } /** @@ -201,7 +214,7 @@ protected boolean lastPassed() { * * @return true if executed, false if conditions not met */ - protected boolean executeChildren(LivingEntity caster, int level, List targets) { + protected boolean executeChildren(LivingEntity caster, int level, List targets, double critChance) { if (targets.isEmpty()) { return false; } @@ -209,7 +222,7 @@ protected boolean executeChildren(LivingEntity caster, int level, List targets); + public abstract boolean execute(LivingEntity caster, int level, List targets, double critChance); /** * Creates the list of indicators for the skill @@ -305,6 +318,7 @@ public void makeIndicators(List list, Player caster, List list, Player caster, List set, int i) { return null; } + public Block getTargetBlock(int i, + TargetBlockInfo.FluidMode fluidMode) { + return null; + } + + public BlockFace getTargetBlockFace(int i, + TargetBlockInfo.FluidMode fluidMode) { + return null; + } + + + public TargetBlockInfo getTargetBlockInfo(int i, + TargetBlockInfo.FluidMode fluidMode) { + return null; + } + + + public Entity getTargetEntity(int i, boolean b) { + return null; + } + + + public TargetEntityInfo getTargetEntityInfo(int i, + boolean b) { + return null; + } + public List getLastTwoTargetBlocks(HashSet hashSet, int i) { return null; } @@ -151,6 +198,31 @@ public void setMaximumAir(int i) { } + + public int getArrowCooldown() { + return 0; + } + + + public void setArrowCooldown(int i) { + + } + + + public int getArrowsInBody() { + return 0; + } + + + public void setArrowsInBody(int i) { + + } + + @Override + public SpawnCategory getSpawnCategory() { + return null; + } + public int getMaximumNoDamageTicks() { return 0; } @@ -187,6 +259,11 @@ public Player getKiller() { return null; } + + public void setKiller( Player player) { + + } + public boolean addPotionEffect(PotionEffect potionEffect) { return false; } @@ -243,6 +320,16 @@ public void setCustomName(String s) { } + + public Component customName() { + return null; + } + + + public void customName( Component component) { + + } + public String getCustomName() { return null; } @@ -341,6 +428,21 @@ public boolean hasAI() { return false; } + + public void attack( Entity entity) { + + } + + + public void swingMainHand() { + + } + + + public void swingOffHand() { + + } + public void setCollidable(boolean b) { } @@ -349,6 +451,11 @@ public boolean isCollidable() { return false; } + + public Set getCollidableExemptions() { + return null; + } + public void damage(double v) { } @@ -436,6 +543,11 @@ public boolean isOnGround() { return true; } + + public boolean isInWater() { + return false; + } + public World getWorld() { return target.getLocation().getWorld(); } @@ -480,6 +592,36 @@ public void setFireTicks(int i) { } + @Override + public void setVisualFire(boolean bl) { + + } + + @Override + public boolean isVisualFire() { + return false; + } + + @Override + public int getFreezeTicks() { + return 0; + } + + @Override + public int getMaxFreezeTicks() { + return 0; + } + + @Override + public void setFreezeTicks(int i) { + + } + + @Override + public boolean isFrozen() { + return false; + } + public void remove() { } @@ -500,6 +642,17 @@ public void sendMessage(String[] strings) { } + + public void sendMessage( UUID uuid, String s) { + + } + + + public void sendMessage( UUID uuid, + String[] strings) { + + } + public Server getServer() { return Bukkit.getServer(); } @@ -662,4 +815,243 @@ public void setOp(boolean b) { public AttributeInstance getAttribute(Attribute attribute) { return null; } + + + public void registerAttribute( Attribute attribute) { + + } + + + public double getAbsorptionAmount() { + return 0; + } + + @Override + public void setAbsorptionAmount(double arg0) { + + } + + @Override + public BoundingBox getBoundingBox() { + return null; + } + + @Override + public BlockFace getFacing() { + return null; + } + + @Override + public Pose getPose() { + return null; + } + + @Override + public @NotNull Spigot spigot() { + return null; + } + + public Location getOrigin() { + return null; + } + + + public boolean fromMobSpawner() { + return false; + } + + + public Chunk getChunk() { + return null; + } + + + public CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + return null; + } + + + public boolean isInRain() { + return false; + } + + + public boolean isInBubbleColumn() { + return false; + } + + + public boolean isInWaterOrRain() { + return false; + } + + + public boolean isInWaterOrBubbleColumn() { + return false; + } + + + public boolean isInWaterOrRainOrBubbleColumn() { + return false; + } + + + public boolean isInLava() { + return false; + } + + + public boolean isTicking() { + return false; + } + + + public boolean isPersistent() { + return false; + } + + @Override + public void setPersistent(boolean arg0) { + + } + + @Override + public void setRotation(float arg0, float arg1) { + + } + + @Override + public PersistentDataContainer getPersistentDataContainer() { + return null; + } + + @Override + public T getMemory(@Nonnull MemoryKey arg0) { + return null; + } + + @Override + public @Nullable Block getTargetBlockExact(int arg0) { + return null; + } + + @Override + public @Nullable Block getTargetBlockExact(int arg0, @Nonnull FluidCollisionMode arg1) { + return null; + } + + @Override + public boolean isRiptiding() { + return false; + } + + @Override + public boolean isSleeping() { + return false; + } + + @Override + public boolean isClimbing() { + return false; + } + + @Override + public @Nullable RayTraceResult rayTraceBlocks(double arg0) { + return null; + } + + @Override + public @Nullable RayTraceResult rayTraceBlocks(double arg0, @Nonnull FluidCollisionMode arg1) { + return null; + } + + @Override + public void setMemory(@Nonnull MemoryKey arg0, @Nullable T arg1) { + + } + + + public EntityCategory getCategory() { + return null; + } + + + public void setInvisible(boolean b) { + + } + + + public boolean isInvisible() { + return false; + } + + + public int getArrowsStuck() { + return 0; + } + + + public void setArrowsStuck(int i) { + + } + + + public int getShieldBlockingDelay() { + return 0; + } + + + public void setShieldBlockingDelay(int i) { + + } + + + public ItemStack getActiveItem() { + return null; + } + + + public void clearActiveItem() { + + } + + + public int getItemUseRemainingTime() { + return 0; + } + + + public int getHandRaisedTime() { + return 0; + } + + + public boolean isHandRaised() { + return false; + } + + + public boolean isJumping() { + return false; + } + + + public void setJumping(boolean b) { + + } + + + public void playPickupItemAnimation(Item item, int i) { + + } + + + public float getHurtDirection() { + return 0; + } + + + public void setHurtDirection(float v) { + + } } diff --git a/src/com/sucy/skill/dynamic/TriggerHandler.java b/src/main/java/com/sucy/skill/dynamic/TriggerHandler.java similarity index 71% rename from src/com/sucy/skill/dynamic/TriggerHandler.java rename to src/main/java/com/sucy/skill/dynamic/TriggerHandler.java index 75edc087..da3395b4 100644 --- a/src/com/sucy/skill/dynamic/TriggerHandler.java +++ b/src/main/java/com/sucy/skill/dynamic/TriggerHandler.java @@ -2,19 +2,26 @@ import com.sucy.skill.SkillAPI; import com.sucy.skill.api.enums.ManaCost; +import com.sucy.skill.api.event.PlayerCriticalCheckEvent; +import com.sucy.skill.api.event.PlayerCriticalSuccessEvent; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.api.player.PlayerSkill; import com.sucy.skill.dynamic.trigger.Trigger; import com.sucy.skill.dynamic.trigger.TriggerComponent; + +import org.bukkit.Bukkit; +import org.bukkit.Sound; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; import java.util.HashMap; import java.util.Objects; +import java.util.Random; import static com.sucy.skill.dynamic.ComponentRegistry.getExecutor; @@ -30,6 +37,7 @@ public class TriggerHandler implements Listener { private final String key; private final Trigger trigger; private final TriggerComponent component; + private static Random gen = new Random(); public TriggerHandler( final DynamicSkill skill, @@ -79,6 +87,16 @@ public void register(final SkillAPI plugin) { trigger.getEvent(), this, EventPriority.HIGHEST, getExecutor(trigger), plugin, true); } + /** + * Registers needed events for the skill, intentionally not ignoring unused events + * + * @param plugin plugin reference + */ + public void registerNoIgnore(final SkillAPI plugin) { + plugin.getServer().getPluginManager().registerEvent( + trigger.getEvent(), this, EventPriority.HIGHEST, getExecutor(trigger), plugin, false); + } + void apply(final T event, final Trigger trigger) { final LivingEntity caster = trigger.getCaster(event); if (caster == null || !active.containsKey(caster.getEntityId())) { return; } @@ -104,19 +122,34 @@ boolean trigger(final LivingEntity user, final LivingEntity target, final int le final PlayerSkill skill = data.getSkill(this.skill.getName()); final boolean cd = component.getSettings().getBool("cooldown", false); final boolean mana = component.getSettings().getBool("mana", false); + double critChance = component.getSettings().getDouble("crit-chance", 0); + double augmentCritChance = critChance; + + if (critChance > 0) { + PlayerCriticalCheckEvent e = new PlayerCriticalCheckEvent(data, critChance); + Bukkit.getPluginManager().callEvent(e); + augmentCritChance = e.getChance(); + } + boolean isCrit = augmentCritChance > gen.nextDouble(); + + critChance = isCrit ? critChance : 0; if ((cd || mana) && !data.check(skill, cd, mana)) { return false; } - if (component.trigger(user, target, level)) { + if (component.trigger(user, target, level, critChance)) { if (cd) { skill.startCooldown(); } if (mana) { data.useMana(skill.getManaCost(), ManaCost.SKILL_CAST); } + if (isCrit) { + Bukkit.getPluginManager().callEvent(new PlayerCriticalSuccessEvent(data, critChance)); + ((Player) user).playSound(user.getLocation(), Sound.ITEM_TRIDENT_RIPTIDE_1, 1.0F, 1.0F); + } return true; } else { return false; } } else { - return component.trigger(user, target, level); + return component.trigger(user, target, level, 0); } } } diff --git a/src/com/sucy/skill/dynamic/condition/ArmorCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ArmorCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/ArmorCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ArmorCondition.java index a1169f97..68215e34 100644 --- a/src/com/sucy/skill/dynamic/condition/ArmorCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ArmorCondition.java @@ -74,7 +74,7 @@ private List> determineGetters() { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final EntityEquipment equipment = target.getEquipment(); return equipment != null && getters.stream().anyMatch( getter -> ItemChecker.check(getter.apply(equipment), level, settings)); diff --git a/src/com/sucy/skill/dynamic/condition/AttributeCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/AttributeCondition.java similarity index 94% rename from src/com/sucy/skill/dynamic/condition/AttributeCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/AttributeCondition.java index b76eeb77..d7105b6e 100644 --- a/src/com/sucy/skill/dynamic/condition/AttributeCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/AttributeCondition.java @@ -38,12 +38,12 @@ public class AttributeCondition extends ConditionComponent private static final String MAX = "max"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { if (!(target instanceof Player)) return false; final String attr = settings.getString(ATTR, null); - final int min = (int) parseValues(caster, MIN, level, 0); - final int max = (int) parseValues(caster, MAX, level, 999); + final int min = (int) parseValues(caster, MIN, level, 0, 0); + final int max = (int) parseValues(caster, MAX, level, 999, 0); final PlayerData data = SkillAPI.getPlayerData((Player) target); final int value = data.getAttribute(attr); diff --git a/src/com/sucy/skill/dynamic/condition/BiomeCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/BiomeCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/BiomeCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/BiomeCondition.java index 741c77a0..9b6006bc 100644 --- a/src/com/sucy/skill/dynamic/condition/BiomeCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/BiomeCondition.java @@ -56,7 +56,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return biomes.contains(target.getLocation().getBlock().getBiome().name()) == requiresIn; } } diff --git a/src/com/sucy/skill/dynamic/condition/BlockCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/BlockCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/BlockCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/BlockCondition.java index 46ab7446..8eb1aa8e 100644 --- a/src/com/sucy/skill/dynamic/condition/BlockCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/BlockCondition.java @@ -60,7 +60,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final Block in = target.getLocation().getBlock(); final Block tested = this.in ? in : in.getRelative(BlockFace.DOWN); return negated != types.contains(tested.getType().name()); diff --git a/src/com/sucy/skill/dynamic/condition/CastLevelCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/CastLevelCondition.java similarity index 91% rename from src/com/sucy/skill/dynamic/condition/CastLevelCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/CastLevelCondition.java index 1a68807c..9cb9317d 100644 --- a/src/com/sucy/skill/dynamic/condition/CastLevelCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/CastLevelCondition.java @@ -51,12 +51,12 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return level >= min && level <= max; } } diff --git a/src/com/sucy/skill/dynamic/condition/CeilingCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/CeilingCondition.java similarity index 93% rename from src/com/sucy/skill/dynamic/condition/CeilingCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/CeilingCondition.java index eb6a56f9..10b9b30b 100644 --- a/src/com/sucy/skill/dynamic/condition/CeilingCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/CeilingCondition.java @@ -9,9 +9,9 @@ public class CeilingCondition extends ConditionComponent private static final String AT_LEAST = "at-least"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean atLeast = settings.getBool(AT_LEAST, true); - final int distance = (int) parseValues(caster, DISTANCE, level, 5); + final int distance = (int) parseValues(caster, DISTANCE, level, 5, 0); final Block block = target.getLocation().getBlock(); boolean ceiling = false; diff --git a/src/com/sucy/skill/dynamic/condition/ChanceCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ChanceCondition.java similarity index 96% rename from src/com/sucy/skill/dynamic/condition/ChanceCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ChanceCondition.java index 0d631e5e..fc1acdc7 100644 --- a/src/com/sucy/skill/dynamic/condition/ChanceCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ChanceCondition.java @@ -36,8 +36,8 @@ public class ChanceCondition extends ConditionComponent private static final Random random = new Random(); @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { - final double chance = parseValues(caster, CHANCE, level, 25) / 100.0; + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { + final double chance = parseValues(caster, CHANCE, level, 25, 0) / 100.0; return random.nextDouble() < chance; } diff --git a/src/com/sucy/skill/dynamic/condition/ClassCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ClassCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/ClassCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ClassCondition.java index d0832305..fde6dde3 100644 --- a/src/com/sucy/skill/dynamic/condition/ClassCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ClassCondition.java @@ -37,7 +37,7 @@ public class ClassCondition extends ConditionComponent { private static final String EXACT = "exact"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { if (!(target instanceof Player)) return false; final RPGClass rpgClass = SkillAPI.getClass(settings.getString(CLASS)); diff --git a/src/com/sucy/skill/dynamic/condition/ClassLevelCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ClassLevelCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/ClassLevelCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ClassLevelCondition.java index 4e55a9e4..9a9d43d0 100644 --- a/src/com/sucy/skill/dynamic/condition/ClassLevelCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ClassLevelCondition.java @@ -53,7 +53,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { if (!(target instanceof Player)) return false; final PlayerClass playerClass = SkillAPI.getPlayerData((Player) target).getMainClass(); diff --git a/src/com/sucy/skill/dynamic/condition/CombatCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/CombatCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/CombatCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/CombatCondition.java index 6fbb2395..aa3ac53b 100644 --- a/src/com/sucy/skill/dynamic/condition/CombatCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/CombatCondition.java @@ -57,7 +57,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return target instanceof Player && Combat.isInCombat((Player) target, seconds) == combat; } } diff --git a/src/com/sucy/skill/dynamic/condition/ConditionComponent.java b/src/main/java/com/sucy/skill/dynamic/condition/ConditionComponent.java similarity index 82% rename from src/com/sucy/skill/dynamic/condition/ConditionComponent.java rename to src/main/java/com/sucy/skill/dynamic/condition/ConditionComponent.java index ecd440d9..9ce6eae1 100644 --- a/src/com/sucy/skill/dynamic/condition/ConditionComponent.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ConditionComponent.java @@ -22,14 +22,14 @@ public ComponentType getType() { /** {@inheritDoc} */ @Override public boolean execute( - final LivingEntity caster, final int level, final List targets) { + final LivingEntity caster, final int level, final List targets, double critChance) { final List filtered = targets.stream() - .filter(t -> test(caster, level, t)) + .filter(t -> test(caster, level, t, critChance)) .collect(Collectors.toList()); - return filtered.size() > 0 && executeChildren(caster, level, filtered); + return filtered.size() > 0 && executeChildren(caster, level, filtered, critChance); } - abstract boolean test(final LivingEntity caster, final int level, final LivingEntity target); + abstract boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance); } diff --git a/src/com/sucy/skill/dynamic/condition/CrouchCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/CrouchCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/CrouchCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/CrouchCondition.java index ec4436bd..49189f02 100644 --- a/src/com/sucy/skill/dynamic/condition/CrouchCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/CrouchCondition.java @@ -48,7 +48,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return target instanceof Player && ((Player) target).isSneaking() == crouch; } } diff --git a/src/com/sucy/skill/dynamic/condition/DirectionCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/DirectionCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java index 53d71bf1..c2a8c71d 100644 --- a/src/com/sucy/skill/dynamic/condition/DirectionCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java @@ -59,7 +59,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return test.test(caster, target) == towards; } } diff --git a/src/com/sucy/skill/dynamic/condition/ElevationCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ElevationCondition.java similarity index 89% rename from src/com/sucy/skill/dynamic/condition/ElevationCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ElevationCondition.java index 2df55a50..4cee8af1 100644 --- a/src/com/sucy/skill/dynamic/condition/ElevationCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ElevationCondition.java @@ -54,10 +54,10 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String type = settings.getString(TYPE).toLowerCase(); - double min = parseValues(caster, MIN, level, 0); - double max = parseValues(caster, MAX, level, 255); + double min = parseValues(caster, MIN, level, 0, 0); + double max = parseValues(caster, MAX, level, 255, 0); ArrayList list = new ArrayList(); for (LivingEntity target : targets) { @@ -71,14 +71,14 @@ public boolean execute(LivingEntity caster, int level, List target list.add(target); } } - return list.size() > 0 && executeChildren(caster, level, list); + return list.size() > 0 && executeChildren(caster, level, list, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String type = settings.getString(TYPE); - final double min = parseValues(caster, MIN, level, 0); - final double max = parseValues(caster, MAX, level, 255); + final double min = parseValues(caster, MIN, level, 0, 0); + final double max = parseValues(caster, MAX, level, 255, 0); double value; if (type.equalsIgnoreCase("difference")) { diff --git a/src/com/sucy/skill/dynamic/condition/ElseCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ElseCondition.java similarity index 89% rename from src/com/sucy/skill/dynamic/condition/ElseCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ElseCondition.java index 07d3e849..3e9b6312 100644 --- a/src/com/sucy/skill/dynamic/condition/ElseCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ElseCondition.java @@ -41,12 +41,12 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return !lastPassed(); } } diff --git a/src/com/sucy/skill/dynamic/condition/EntityTypeCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/EntityTypeCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/EntityTypeCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/EntityTypeCondition.java index 843e3501..d89fff5b 100644 --- a/src/com/sucy/skill/dynamic/condition/EntityTypeCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/EntityTypeCondition.java @@ -53,7 +53,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return types.contains(target.getType().name()); } } diff --git a/src/com/sucy/skill/dynamic/condition/FireCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/FireCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/FireCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/FireCondition.java index 7d31eb56..7171fc7e 100644 --- a/src/com/sucy/skill/dynamic/condition/FireCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/FireCondition.java @@ -35,7 +35,7 @@ public class FireCondition extends ConditionComponent { private static final String TYPE = "type"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean onFire = !settings.getString(TYPE, "on fire").toLowerCase().equals("not on fire"); return (target.getFireTicks() > 0) == onFire; } diff --git a/src/com/sucy/skill/dynamic/condition/FlagCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/FlagCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/FlagCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/FlagCondition.java index c5d03241..27a58e5d 100644 --- a/src/com/sucy/skill/dynamic/condition/FlagCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/FlagCondition.java @@ -37,7 +37,7 @@ public class FlagCondition extends ConditionComponent { private static final String KEY = "key"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String flag = settings.getString(KEY); final boolean set = !settings.getString(TYPE, "set").toLowerCase().equals("not set"); return FlagManager.hasFlag(target, flag) == set; diff --git a/src/com/sucy/skill/dynamic/condition/GroundCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/GroundCondition.java similarity index 93% rename from src/com/sucy/skill/dynamic/condition/GroundCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/GroundCondition.java index adf9f222..4800042c 100644 --- a/src/com/sucy/skill/dynamic/condition/GroundCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/GroundCondition.java @@ -10,7 +10,7 @@ public class GroundCondition extends ConditionComponent { private static final String type = "type"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean onGround = target.isOnGround(); final boolean wantOnGround = settings.getString(type, "on ground").equalsIgnoreCase("on ground"); return onGround == wantOnGround; diff --git a/src/com/sucy/skill/dynamic/condition/HealthCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/HealthCondition.java similarity index 93% rename from src/com/sucy/skill/dynamic/condition/HealthCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/HealthCondition.java index ddf431c9..ecac68c6 100644 --- a/src/com/sucy/skill/dynamic/condition/HealthCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/HealthCondition.java @@ -37,10 +37,10 @@ public class HealthCondition extends ConditionComponent { private static final String MAX = "max-value"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String type = settings.getString(TYPE).toLowerCase(); - final double min = parseValues(caster, MIN, level, 0); - final double max = parseValues(caster, MAX, level, 999); + final double min = parseValues(caster, MIN, level, 0, 0); + final double max = parseValues(caster, MAX, level, 999, 0); double value; switch (type) { diff --git a/src/com/sucy/skill/dynamic/condition/InventoryCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/InventoryCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/InventoryCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/InventoryCondition.java index ca32b2d9..2be2687e 100644 --- a/src/com/sucy/skill/dynamic/condition/InventoryCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/InventoryCondition.java @@ -35,7 +35,7 @@ */ public class InventoryCondition extends ConditionComponent { @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return target instanceof Player && ItemChecker.check((Player) target, level, this, false); } diff --git a/src/com/sucy/skill/dynamic/condition/ItemCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ItemCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/ItemCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ItemCondition.java index 47877141..40094f5d 100644 --- a/src/com/sucy/skill/dynamic/condition/ItemCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ItemCondition.java @@ -34,7 +34,7 @@ */ public class ItemCondition extends ConditionComponent { @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return target.getEquipment() != null && ItemChecker.check( target.getEquipment().getItemInHand(), level, diff --git a/src/com/sucy/skill/dynamic/condition/LightCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/LightCondition.java similarity index 91% rename from src/com/sucy/skill/dynamic/condition/LightCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/LightCondition.java index db9c455e..386d1919 100644 --- a/src/com/sucy/skill/dynamic/condition/LightCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/LightCondition.java @@ -36,9 +36,9 @@ public class LightCondition extends ConditionComponent { private static final String MAX = "max-light"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { - final double min = parseValues(caster, MIN, level, 0); - final double max = parseValues(caster, MAX, level, 0); + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { + final double min = parseValues(caster, MIN, level, 0, 0); + final double max = parseValues(caster, MAX, level, 0, 0); final double light = target.getLocation().getBlock().getLightLevel(); return light >= min && light <= max; } diff --git a/src/com/sucy/skill/dynamic/condition/LoreCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/LoreCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/LoreCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/LoreCondition.java index 440fcf99..a3473d0d 100644 --- a/src/com/sucy/skill/dynamic/condition/LoreCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/LoreCondition.java @@ -60,7 +60,7 @@ public void load(DynamicSkill skill, DataSection config) { } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final EntityEquipment items = target.getEquipment(); if (items == null || items.getItemInHand() == null || !items.getItemInHand().hasItemMeta()) { return false; } diff --git a/src/com/sucy/skill/dynamic/condition/ManaCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ManaCondition.java similarity index 93% rename from src/com/sucy/skill/dynamic/condition/ManaCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ManaCondition.java index 68090f22..a5e6e538 100644 --- a/src/com/sucy/skill/dynamic/condition/ManaCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ManaCondition.java @@ -38,14 +38,14 @@ public class ManaCondition extends ConditionComponent { private static final String MAX = "max-value"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { if (!(target instanceof Player)) { return false; } final String type = settings.getString(TYPE).toLowerCase(); - final double min = parseValues(caster, MIN, level, 0); - final double max = parseValues(caster, MAX, level, 99); + final double min = parseValues(caster, MIN, level, 0, 0); + final double max = parseValues(caster, MAX, level, 99, 0); final PlayerData data = SkillAPI.getPlayerData((Player) target); final PlayerSkill skill = getSkillData(caster); final double mana = data.getMana(); diff --git a/src/com/sucy/skill/dynamic/condition/NameCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/NameCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/NameCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/NameCondition.java index 6652f026..89a2fcbc 100644 --- a/src/com/sucy/skill/dynamic/condition/NameCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/NameCondition.java @@ -39,7 +39,7 @@ public class NameCondition extends ConditionComponent { private static final String STRING = "str"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { boolean contains = !settings.getString(CONTAINS, "true").toLowerCase().equals("false"); boolean regex = settings.getString(REGEX, "false").toLowerCase().equals("true"); String str = settings.getString(STRING, ""); diff --git a/src/com/sucy/skill/dynamic/condition/OffhandCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/OffhandCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/OffhandCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/OffhandCondition.java index 9d059410..8e1afe1d 100644 --- a/src/com/sucy/skill/dynamic/condition/OffhandCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/OffhandCondition.java @@ -35,7 +35,7 @@ */ public class OffhandCondition extends ConditionComponent { @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final EntityEquipment equipment = target.getEquipment(); return equipment != null && ItemChecker.check(target.getEquipment().getItemInOffHand(), level, settings); } diff --git a/src/com/sucy/skill/dynamic/condition/PermissionCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/PermissionCondition.java similarity index 89% rename from src/com/sucy/skill/dynamic/condition/PermissionCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/PermissionCondition.java index e82a4e69..cb549645 100644 --- a/src/com/sucy/skill/dynamic/condition/PermissionCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/PermissionCondition.java @@ -39,12 +39,12 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { return caster.hasPermission(settings.getString(PERM)); } } diff --git a/src/com/sucy/skill/dynamic/condition/PotionCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/PotionCondition.java similarity index 92% rename from src/com/sucy/skill/dynamic/condition/PotionCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/PotionCondition.java index 51934524..8a645dda 100644 --- a/src/com/sucy/skill/dynamic/condition/PotionCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/PotionCondition.java @@ -43,25 +43,27 @@ public class PotionCondition extends ConditionComponent { private static final String MAX_RANK = "max-rank"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean active = !settings.getString(TYPE, "active").toLowerCase().equals("not active"); final Collection effects = target.getActivePotionEffects(); - if (effects.isEmpty()) return !active; + if (effects.isEmpty()) { + return !active; + } final String potion = settings.getString(POTION, "").toUpperCase().replace(' ', '_'); - final int minRank = (int) parseValues(caster, MIN_RANK, level, 0); - final int maxRank = (int) parseValues(caster, MAX_RANK, level, 999); + final int minRank = (int) parseValues(caster, MIN_RANK, level, 0, 0); + final int maxRank = (int) parseValues(caster, MAX_RANK, level, 999, 0); try { final PotionEffectType type = PotionEffectType.getByName(potion); return has(target, type, minRank, maxRank) == active; } catch (Exception ex) { for (final PotionEffect check : effects) { - if (check.getAmplifier() >= minRank && check.getAmplifier() <= maxRank) { - return true; + if (check.getAmplifier() >= minRank && check.getAmplifier() <= maxRank && check.getType().equals(PotionEffectType.getByName(potion))) { + return active; } } + return !active; } - return false; } private boolean has(LivingEntity target, PotionEffectType type, int min, int max) { diff --git a/src/com/sucy/skill/dynamic/condition/SkillLevelCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/SkillLevelCondition.java similarity index 92% rename from src/com/sucy/skill/dynamic/condition/SkillLevelCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/SkillLevelCondition.java index d4a607ad..1a28f6c4 100644 --- a/src/com/sucy/skill/dynamic/condition/SkillLevelCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/SkillLevelCondition.java @@ -42,12 +42,12 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final int min = settings.getInt(MIN_LEVEL, 1); final int max = settings.getInt(MAX_LEVEL, 99); diff --git a/src/com/sucy/skill/dynamic/condition/SlotCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/SlotCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/SlotCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/SlotCondition.java index 38309d82..cf42f429 100644 --- a/src/com/sucy/skill/dynamic/condition/SlotCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/SlotCondition.java @@ -36,7 +36,7 @@ public class SlotCondition extends ConditionComponent private static final String SLOT = "slot"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { if (!(target instanceof Player)) return false; final PlayerInventory inventory = ((Player) target).getInventory(); diff --git a/src/com/sucy/skill/dynamic/condition/StatusCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/StatusCondition.java similarity index 98% rename from src/com/sucy/skill/dynamic/condition/StatusCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/StatusCondition.java index 9da98331..e9262c7b 100644 --- a/src/com/sucy/skill/dynamic/condition/StatusCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/StatusCondition.java @@ -40,7 +40,7 @@ public class StatusCondition extends ConditionComponent { private static final String STATUS = "status"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean active = !settings.getString(TYPE, "active").equals("not active"); final String status = settings.getString(STATUS).toLowerCase(); diff --git a/src/com/sucy/skill/dynamic/condition/TimeCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/TimeCondition.java similarity index 90% rename from src/com/sucy/skill/dynamic/condition/TimeCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/TimeCondition.java index e1f0f2d1..da99b124 100644 --- a/src/com/sucy/skill/dynamic/condition/TimeCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/TimeCondition.java @@ -42,12 +42,12 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean night = settings.getString(TIME).toLowerCase().equals("night"); return night == (caster.getWorld().getTime() >= 12300 && caster.getWorld().getTime() <= 23850); } diff --git a/src/com/sucy/skill/dynamic/condition/ToolCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ToolCondition.java similarity index 78% rename from src/com/sucy/skill/dynamic/condition/ToolCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ToolCondition.java index e45c044e..3bebb9a6 100644 --- a/src/com/sucy/skill/dynamic/condition/ToolCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ToolCondition.java @@ -37,14 +37,25 @@ public class ToolCondition extends ConditionComponent { private static final String TOOL = "tool"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String material = settings.getString(MATERIAL, "").toUpperCase(); - final String tool = "_" + settings.getString(TOOL, "").toUpperCase().replace("SHOVEL", "SPADE"); + final String tool = settings.getString(TOOL, "").toUpperCase().replace("SHOVEL", "SPADE"); final EntityEquipment equipment = target.getEquipment(); if (equipment == null || equipment.getItemInHand() == null) return false; final String hand = equipment.getItemInHand().getType().name(); + + // Custom tools + if (tool.equalsIgnoreCase("BOW")) { + return hand.equalsIgnoreCase("Bow") || hand.equalsIgnoreCase("Crossbow"); + } + else if (tool.equalsIgnoreCase("WEAPON")) { + return hand.contains("AXE") || hand.contains("SWORD") || hand.contains("TRIDENT"); + } + else if (tool.equalsIgnoreCase("HEAVY")) { + return hand.contains("AXE") || hand.contains("TRIDENT"); + } return (material.equals("ANY") || hand.contains(material)) && (tool.equals("_ANY") || hand.contains(tool)); } diff --git a/src/com/sucy/skill/dynamic/condition/ValueCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/ValueCondition.java similarity index 85% rename from src/com/sucy/skill/dynamic/condition/ValueCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/ValueCondition.java index 1306da17..2f92e5ba 100644 --- a/src/com/sucy/skill/dynamic/condition/ValueCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/ValueCondition.java @@ -42,16 +42,16 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { - return test(caster, level, null) && executeChildren(caster, level, targets); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + return test(caster, level, null, critChance) && executeChildren(caster, level, targets, critChance); } @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String key = settings.getString(KEY); - final double min = parseValues(caster, MIN, level, 1); - final double max = parseValues(caster, MAX, level, 999); - final Object data = DynamicSkill.getCastData(caster).get(key); + final double min = parseValues(caster, MIN, level, 1, 0); + final double max = parseValues(caster, MAX, level, 999, 0); + final Object data = DynamicSkill.getCastData(caster).getOrDefault(key, 0D); if (data != null) { double value = (Double) data; diff --git a/src/com/sucy/skill/dynamic/condition/WaterCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/WaterCondition.java similarity index 97% rename from src/com/sucy/skill/dynamic/condition/WaterCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/WaterCondition.java index 4c94b499..54783a4f 100644 --- a/src/com/sucy/skill/dynamic/condition/WaterCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/WaterCondition.java @@ -36,7 +36,7 @@ public class WaterCondition extends ConditionComponent { private static final String STATE = "state"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final boolean out = settings.getString(STATE).toLowerCase().equals("out of water"); final Material block = target.getLocation().getBlock().getType(); return out != (block.name().contains("WATER")); diff --git a/src/com/sucy/skill/dynamic/condition/WeatherCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/WeatherCondition.java similarity index 96% rename from src/com/sucy/skill/dynamic/condition/WeatherCondition.java rename to src/main/java/com/sucy/skill/dynamic/condition/WeatherCondition.java index 88d0125f..2a0efb8f 100644 --- a/src/com/sucy/skill/dynamic/condition/WeatherCondition.java +++ b/src/main/java/com/sucy/skill/dynamic/condition/WeatherCondition.java @@ -12,7 +12,7 @@ public class WeatherCondition extends ConditionComponent { private String TYPE = "type"; @Override - boolean test(final LivingEntity caster, final int level, final LivingEntity target) { + boolean test(final LivingEntity caster, final int level, final LivingEntity target, double critChance) { final String type = settings.getString(TYPE).toLowerCase(); final World world = target.getWorld(); final Location loc = target.getLocation(); diff --git a/src/com/sucy/skill/dynamic/custom/CustomComponent.java b/src/main/java/com/sucy/skill/dynamic/custom/CustomComponent.java similarity index 100% rename from src/com/sucy/skill/dynamic/custom/CustomComponent.java rename to src/main/java/com/sucy/skill/dynamic/custom/CustomComponent.java diff --git a/src/com/sucy/skill/dynamic/custom/CustomEffectComponent.java b/src/main/java/com/sucy/skill/dynamic/custom/CustomEffectComponent.java similarity index 100% rename from src/com/sucy/skill/dynamic/custom/CustomEffectComponent.java rename to src/main/java/com/sucy/skill/dynamic/custom/CustomEffectComponent.java diff --git a/src/com/sucy/skill/dynamic/custom/CustomTrigger.java b/src/main/java/com/sucy/skill/dynamic/custom/CustomTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/custom/CustomTrigger.java rename to src/main/java/com/sucy/skill/dynamic/custom/CustomTrigger.java diff --git a/src/com/sucy/skill/dynamic/custom/EditorOption.java b/src/main/java/com/sucy/skill/dynamic/custom/EditorOption.java similarity index 100% rename from src/com/sucy/skill/dynamic/custom/EditorOption.java rename to src/main/java/com/sucy/skill/dynamic/custom/EditorOption.java diff --git a/src/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java index fdf78390..a7b079a7 100644 --- a/src/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/AttributeMechanic.java @@ -59,15 +59,15 @@ public class AttributeMechanic extends MechanicComponent { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String key = settings.getString(KEY, ""); if (targets.size() == 0 || SkillAPI.getAttributeManager().getAttribute(key) == null) { return false; } final Map casterTasks = tasks.computeIfAbsent(caster.getEntityId(), HashMap::new); - final int amount = (int) parseValues(caster, AMOUNT, level, 5); - final double seconds = parseValues(caster, SECONDS, level, 3.0); + final int amount = (int) parseValues(caster, AMOUNT, level, 5, 0); + final double seconds = parseValues(caster, SECONDS, level, 3.0, 0); final boolean stackable = settings.getString(STACKABLE, "false").equalsIgnoreCase("true"); final int ticks = (int) (seconds * 20); @@ -125,7 +125,7 @@ public void stop() { if (!stopped) { stopped = true; run(); - if (running) { + if (!running) { cancel(); } } diff --git a/src/com/sucy/skill/dynamic/mechanic/BlockMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/BlockMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/BlockMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/BlockMechanic.java index 3d1a9af4..ddab801c 100644 --- a/src/com/sucy/skill/dynamic/mechanic/BlockMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/BlockMechanic.java @@ -78,7 +78,7 @@ public class BlockMechanic extends MechanicComponent { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } Material block = Material.ICE; @@ -89,23 +89,23 @@ public boolean execute(LivingEntity caster, int level, List target } boolean sphere = settings.getString(SHAPE, "sphere").toLowerCase().equals("sphere"); - int ticks = (int) (20 * parseValues(caster, SECONDS, level, 5)); + int ticks = (int) (20 * parseValues(caster, SECONDS, level, 5, 0)); byte data = (byte) settings.getInt(DATA, 0); String type = settings.getString(TYPE, "solid").toLowerCase(); boolean solid = type.equals("solid"); boolean air = type.equals("air"); - double forward = parseValues(caster, FORWARD, level, 0); - double upward = parseValues(caster, UPWARD, level, 0); - double right = parseValues(caster, RIGHT, level, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); + double upward = parseValues(caster, UPWARD, level, 0, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); List blocks = new ArrayList(); World w = caster.getWorld(); // Grab blocks in a sphere if (sphere) { - double radius = parseValues(caster, RADIUS, level, 3); + double radius = parseValues(caster, RADIUS, level, 3, 0); double x, y, z, dx, dy, dz; double rSq = radius * radius; for (LivingEntity t : targets) { @@ -144,9 +144,9 @@ public boolean execute(LivingEntity caster, int level, List target // Grab blocks in a cuboid else { // Cuboid options - double width = (parseValues(caster, WIDTH, level, 5) - 1) / 2; - double height = (parseValues(caster, HEIGHT, level, 5) - 1) / 2; - double depth = (parseValues(caster, DEPTH, level, 5) - 1) / 2; + double width = (parseValues(caster, WIDTH, level, 5, 0) - 1) / 2; + double height = (parseValues(caster, HEIGHT, level, 5, 0) - 1) / 2; + double depth = (parseValues(caster, DEPTH, level, 5, 0) - 1) / 2; double x, y, z; for (LivingEntity t : targets) { diff --git a/src/com/sucy/skill/dynamic/mechanic/BuffMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/BuffMechanic.java similarity index 71% rename from src/com/sucy/skill/dynamic/mechanic/BuffMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/BuffMechanic.java index 38f00f57..1942b961 100644 --- a/src/com/sucy/skill/dynamic/mechanic/BuffMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/BuffMechanic.java @@ -1,8 +1,11 @@ package com.sucy.skill.dynamic.mechanic; +import com.sucy.skill.api.event.SkillBuffEvent; import com.sucy.skill.api.util.Buff; import com.sucy.skill.api.util.BuffManager; import com.sucy.skill.api.util.BuffType; + +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import java.util.List; @@ -35,11 +38,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) return false; boolean immediate = settings.getString(IMMEDIATE, "false").equalsIgnoreCase("true"); - double value = parseValues(caster, VALUE, level, 1.0); + double value = parseValues(caster, VALUE, level, 1.0, 0); boolean percent = settings.getString(MODIFIER, "flat").equalsIgnoreCase("multiplier"); if (immediate) { @@ -48,15 +51,20 @@ public boolean execute(LivingEntity caster, int level, List target } BuffType buffType = BuffType.valueOf(settings.getString(TYPE, "DAMAGE")); - double seconds = parseValues(caster, SECONDS, level, 3.0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); String category = settings.getString(CATEGORY, null); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { - BuffManager.getBuffData(target).addBuff( - buffType, - category, - new Buff(this.skill.getName() + "-" + caster.getName(), value, percent), - ticks); + SkillBuffEvent event = new SkillBuffEvent(caster, target, value, ticks, buffType, percent); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + BuffManager.getBuffData(target).addBuff( + buffType, + category, + new Buff(this.skill.getName() + "-" + caster.getName(), event.getAmount(), percent), + event.getTicks()); + } } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java index 72246c8f..6f221f76 100644 --- a/src/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/CancelEffectMechanic.java @@ -43,7 +43,7 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String key = settings.getString(KEY, skill.getName()); for (LivingEntity target : targets) { diff --git a/src/com/sucy/skill/dynamic/mechanic/CancelMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/CancelMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/CancelMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/CancelMechanic.java index b8e47a93..806a130a 100644 --- a/src/com/sucy/skill/dynamic/mechanic/CancelMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/CancelMechanic.java @@ -49,7 +49,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { skill.cancelTrigger(); return true; } diff --git a/src/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java similarity index 89% rename from src/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java index 82682946..bbdaf4e4 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ChannelMechanic.java @@ -55,23 +55,23 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(final LivingEntity caster, final int level, final List targets) { + public boolean execute(final LivingEntity caster, final int level, final List targets, double critChance) { if (targets.size() == 0) { return false; } boolean still = settings.getBool(STILL); - int ticks = (int) (20 * parseValues(caster, SECONDS, level, 2.0)); - if (still) { FlagManager.addFlag(caster, StatusFlag.CHANNELING, ticks + 2); } + int ticks = (int) (20 * parseValues(caster, SECONDS, level, 2.0, 0)); + if (still) { FlagManager.addFlag(caster, caster, StatusFlag.CHANNELING, ticks + 2); } Bukkit.getScheduler().runTaskLater( Bukkit.getPluginManager().getPlugin("SkillAPI"), () -> { if (FlagManager.hasFlag(caster, StatusFlag.CHANNEL)) { FlagManager.removeFlag(caster, StatusFlag.CHANNEL); FlagManager.removeFlag(caster, StatusFlag.CHANNELING); - executeChildren(caster, level, targets); + executeChildren(caster, level, targets, critChance); } }, ticks ); - FlagManager.addFlag(caster, StatusFlag.CHANNEL, ticks + 2); + FlagManager.addFlag(caster, caster, StatusFlag.CHANNEL, ticks + 2); return true; } } diff --git a/src/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java index 74e62f52..cf712b3d 100644 --- a/src/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/CleanseMechanic.java @@ -63,7 +63,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean worked = false; String status = settings.getString(STATUS, "None").toLowerCase(); String potion = settings.getString(POTION).toUpperCase().replace(' ', '_'); diff --git a/src/com/sucy/skill/dynamic/mechanic/CommandMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/CommandMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/CommandMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/CommandMechanic.java index 0d898c4e..a723bfb3 100644 --- a/src/com/sucy/skill/dynamic/mechanic/CommandMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/CommandMechanic.java @@ -54,7 +54,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(COMMAND)) { return false; } diff --git a/src/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java similarity index 65% rename from src/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java index 5df863b3..aeaf5e7c 100644 --- a/src/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/CooldownMechanic.java @@ -57,38 +57,43 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!(caster instanceof Player)) { return false; } String skill = settings.getString(SKILL, ""); String type = settings.getString(TYPE, "all").toLowerCase(); - double value = parseValues(caster, VALUE, level, 0); + double value = parseValues(caster, VALUE, level, 0, 0); - PlayerData playerData = SkillAPI.getPlayerData((Player) caster); - - PlayerSkill skillData = playerData.getSkill(skill); - if (skillData == null && !skill.equals("all")) { - skillData = playerData.getSkill(this.skill.getName()); - } - - boolean worked = false; - if (skill.equals("all")) { - for (PlayerSkill data : playerData.getSkills()) { - if (type.equals("percent")) { - data.subtractCooldown(value * data.getCooldown() / 100); - } else { - data.subtractCooldown(value); - } - worked = true; - } - } else if (skillData != null) { - if (type.equals("percent")) { - skillData.subtractCooldown(value * skillData.getCooldown() / 100); - } else { - skillData.subtractCooldown(value); - } - worked = true; + for (LivingEntity ent : targets) { + if (!(ent instanceof Player)) continue; + Player target = (Player) ent; + PlayerData playerData = SkillAPI.getPlayerData(target); + + PlayerSkill skillData = playerData.getSkill(skill); + if (skillData == null && !skill.equals("all")) { + skillData = playerData.getSkill(this.skill.getName()); + } + + boolean worked = false; + if (skill.equals("all")) { + for (PlayerSkill data : playerData.getSkills()) { + if (type.equals("percent")) { + data.subtractCooldown(value * data.getCooldown() / 100); + } else { + data.subtractCooldown(value); + } + worked = true; + } + } else if (skillData != null) { + if (type.equals("percent")) { + skillData.subtractCooldown(value * skillData.getCooldown() / 100); + } else { + skillData.subtractCooldown(value); + } + worked = true; + } + return worked; } - return worked; + return false; } } diff --git a/src/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java similarity index 82% rename from src/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java index 3358e365..26e7b4ec 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageBuffMechanic.java @@ -26,9 +26,12 @@ */ package com.sucy.skill.dynamic.mechanic; +import com.sucy.skill.api.event.SkillBuffEvent; import com.sucy.skill.api.util.Buff; import com.sucy.skill.api.util.BuffManager; import com.sucy.skill.api.util.BuffType; + +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import java.util.List; @@ -57,20 +60,23 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } boolean skill = settings.getString(SKILL, "false").equalsIgnoreCase("true"); boolean percent = settings.getString(TYPE, "flat").toLowerCase().equals("multiplier"); - double value = parseValues(caster, VALUE, level, 1.0); - double seconds = parseValues(caster, SECONDS, level, 3.0); + double value = parseValues(caster, VALUE, level, 1.0, 0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { + BuffType type = skill ? BuffType.SKILL_DAMAGE : BuffType.DAMAGE; + SkillBuffEvent event = new SkillBuffEvent(caster, target, value, ticks, type, percent); + Bukkit.getPluginManager().callEvent(event); BuffManager.addBuff( target, - skill ? BuffType.SKILL_DAMAGE : BuffType.DAMAGE, - new Buff(this.skill.getName(), value, percent), - ticks); + type, + new Buff(this.skill.getName(), event.getAmount(), percent), + event.getTicks()); } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java index 1b48e9a8..807d95fe 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageLoreMechanic.java @@ -61,11 +61,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String regex = settings.getString(REGEX, "Damage: {value}"); regex = regex.replace("{value}", "([0-9]+)"); Pattern pattern = Pattern.compile(regex); - double m = parseValues(caster, MULTIPLIER, level, 1.0); + double m = parseValues(caster, MULTIPLIER, level, 1.0, 0); boolean worked = false; boolean offhand = VersionManager.isVersionAtLeast(VersionManager.V1_9_0) && settings.getString(HAND).equalsIgnoreCase("offhand"); diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/DamageMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageMechanic.java new file mode 100644 index 00000000..34277fa9 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DamageMechanic.java @@ -0,0 +1,115 @@ +/** + * SkillAPI + * com.sucy.skill.dynamic.mechanic.DamageMechanic + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.dynamic.mechanic; + +import org.bukkit.Bukkit; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.event.PlayerCriticalDamageEvent; +import com.sucy.skill.api.player.PlayerData; + +import java.util.List; + +/** + * Deals damage to each target + */ +public class DamageMechanic extends MechanicComponent { + private static final String TYPE = "type"; + private static final String DAMAGE = "value"; + private static final String TRUE = "true"; + private static final String CLASSIFIER = "classifier"; + + @Override + public String getKey() { + return "damage"; + } + + /** + * Executes the component + * + * @param caster caster of the skill + * @param level level of the skill + * @param targets targets to apply to + * + * @return true if applied to something, false otherwise + */ + @Override + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + String pString = settings.getString(TYPE, "damage").toLowerCase(); + boolean percent = pString.equals("multiplier") || pString.equals("percent"); + boolean missing = pString.equals("percent missing"); + boolean left = pString.equals("percent left"); + boolean trueDmg = settings.getBool(TRUE, false); + critChance = pString.equalsIgnoreCase("damage") && !trueDmg ? critChance : 0; + double basedamage = getValue(caster, DAMAGE, level, 1.0); + double damage = parseValues(caster, DAMAGE, level, 1.0, critChance); + String classification = settings.getString(CLASSIFIER, "default"); + if (damage < 0) { + return false; + } + + + for (LivingEntity target : targets) { + if (target.isDead()) { + continue; + } + double critDamage = 0; + if (critChance > 0) { + PlayerData data = SkillAPI.getPlayerData((Player) caster); + critDamage = data.getCritBonus(this, basedamage, critChance); + PlayerCriticalDamageEvent e = new PlayerCriticalDamageEvent(caster, target, critDamage); + Bukkit.getPluginManager().callEvent(e); + critDamage = e.getDamage(); + } + + double amount = damage + critDamage; + if (target instanceof Player) { + amount *= 0.3; // classpvp damage limiting + } + + if (percent) { + amount = damage * target.getMaxHealth() / 100; + } + else if (missing) { + amount = damage * (target.getMaxHealth() - target.getHealth()) / 100; + } + else if (left) { + amount = damage * target.getHealth() / 100; + } + + if (trueDmg) { + skill.trueDamage(target, amount, caster); + } + else { + skill.damage(target, amount, caster, classification); + } + } + return targets.size() > 0; + } +} diff --git a/src/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java similarity index 82% rename from src/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java index 89f016ad..a2d33d0b 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DefenseBuffMechanic.java @@ -26,9 +26,12 @@ */ package com.sucy.skill.dynamic.mechanic; +import com.sucy.skill.api.event.SkillBuffEvent; import com.sucy.skill.api.util.Buff; import com.sucy.skill.api.util.BuffManager; import com.sucy.skill.api.util.BuffType; + +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import java.util.List; @@ -57,20 +60,23 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } boolean skill = settings.getString(SKILL, "false").equalsIgnoreCase("true"); boolean percent = settings.getString(TYPE, "flat").toLowerCase().equals("multiplier"); - double value = parseValues(caster, VALUE, level, 1.0); - double seconds = parseValues(caster, SECONDS, level, 3.0); + double value = parseValues(caster, VALUE, level, 1.0, 0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { + BuffType type = skill ? BuffType.SKILL_DEFENSE : BuffType.DEFENSE; + SkillBuffEvent event = new SkillBuffEvent(caster, target, value, ticks, type, percent); + Bukkit.getPluginManager().callEvent(event); BuffManager.addBuff( target, - skill ? BuffType.SKILL_DEFENSE : BuffType.DEFENSE, - new Buff(this.skill.getName(), value, percent), - ticks); + type, + new Buff(this.skill.getName(), event.getAmount(), percent), + event.getTicks()); } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/DelayMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DelayMechanic.java similarity index 93% rename from src/com/sucy/skill/dynamic/mechanic/DelayMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DelayMechanic.java index 9296bfae..04c7f104 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DelayMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DelayMechanic.java @@ -52,14 +52,14 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(final LivingEntity caster, final int level, final List targets) { + public boolean execute(final LivingEntity caster, final int level, final List targets, double critChance) { if (targets.size() == 0) { return false; } - double seconds = parseValues(caster, SECONDS, level, 2.0); + double seconds = parseValues(caster, SECONDS, level, 2.0, 0); Bukkit.getScheduler().runTaskLater( Bukkit.getPluginManager().getPlugin("SkillAPI"), - () -> executeChildren(caster, level, targets), + () -> executeChildren(caster, level, targets, critChance), (long) (seconds * 20) ); return true; diff --git a/src/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java similarity index 96% rename from src/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java index 836b2420..b4489dc2 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DisguiseMechanic.java @@ -62,7 +62,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!PluginChecker.isDisguiseActive()) { return false; } String type = settings.getString(TYPE); @@ -100,9 +100,9 @@ else if (type.equalsIgnoreCase("misc")) { else { return false; } // Apply Flag duration - int ticks = (int) (parseValues(caster, DURATION, level, -1) * 20); + int ticks = (int) (parseValues(caster, DURATION, level, -1, 0) * 20); for (LivingEntity target : targets) { - if (!(target instanceof TempEntity)) { FlagManager.addFlag(target, MechanicListener.DISGUISE_KEY, ticks); } + if (!(target instanceof TempEntity)) { FlagManager.addFlag(caster, target, MechanicListener.DISGUISE_KEY, ticks); } } return targets.size() > 0; diff --git a/src/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java index 7ee270df..c7d6bf17 100644 --- a/src/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/DurabilityMechanic.java @@ -24,7 +24,7 @@ public String getKey() { @Override public boolean execute( - final LivingEntity caster, final int level, final List targets) { + final LivingEntity caster, final int level, final List targets, double critChance) { if (!(caster instanceof Player)) { return false; @@ -32,7 +32,7 @@ public boolean execute( final Player player = (Player) caster; final boolean offhand = settings.getBool(OFFHAND, false); - final short amount = (short) (parseValues(caster, AMOUNT, level, 1) * targets.size()); + final short amount = (short) (parseValues(caster, AMOUNT, level, 1, 0) * targets.size()); final ItemStack item; if (offhand && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java index 88fc8d45..4160e573 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ExplosionMechanic.java @@ -54,11 +54,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } - double power = parseValues(caster, POWER, level, 4); + double power = parseValues(caster, POWER, level, 4, 0); boolean fire = settings.getBool(FIRE, false); boolean damage = settings.getBool(DAMAGE, false); for (LivingEntity target : targets) { diff --git a/src/com/sucy/skill/dynamic/mechanic/FireMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/FireMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/FireMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/FireMechanic.java index f5faf27d..42b21ff6 100644 --- a/src/com/sucy/skill/dynamic/mechanic/FireMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/FireMechanic.java @@ -51,11 +51,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } - double seconds = parseValues(caster, SECONDS, level, 3.0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { int newTicks = ticks <= 0 ? 0 : Math.max(ticks, target.getFireTicks()); diff --git a/src/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java index da45260d..e446fdf6 100644 --- a/src/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagClearMechanic.java @@ -53,7 +53,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/FlagMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/FlagMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/FlagMechanic.java index 05743c5c..c3512e4a 100644 --- a/src/com/sucy/skill/dynamic/mechanic/FlagMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagMechanic.java @@ -54,7 +54,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { @@ -62,11 +62,11 @@ public boolean execute(LivingEntity caster, int level, List target } String key = settings.getString(KEY); - double seconds = parseValues(caster, SECONDS, level, 3.0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { - FlagManager.addFlag(target, key, ticks); + FlagManager.addFlag(caster, target, key, ticks); } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java index fec6d1ec..c99e45fa 100644 --- a/src/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/FlagToggleMechanic.java @@ -53,7 +53,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { @@ -69,7 +69,7 @@ public boolean execute(LivingEntity caster, int level, List target } else { - FlagManager.addFlag(target, key, -1); + FlagManager.addFlag(caster, target, key, -1); } } return targets.size() > 0; diff --git a/src/com/sucy/skill/dynamic/mechanic/FoodMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/FoodMechanic.java similarity index 72% rename from src/com/sucy/skill/dynamic/mechanic/FoodMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/FoodMechanic.java index 6611fbb2..00c7abf0 100644 --- a/src/com/sucy/skill/dynamic/mechanic/FoodMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/FoodMechanic.java @@ -1,7 +1,9 @@ package com.sucy.skill.dynamic.mechanic; +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.event.entity.FoodLevelChangeEvent; import java.util.List; @@ -28,12 +30,17 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { - double food = parseValues(caster, FOOD, level, 1.0); - double saturation = parseValues(caster, SATURATION, level, 1.0); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + double food = parseValues(caster, FOOD, level, 1.0, 0); + double saturation = parseValues(caster, SATURATION, level, 1.0, 0); for (LivingEntity target : targets) { if (target instanceof Player) { Player player = (Player) target; + FoodLevelChangeEvent e = new FoodLevelChangeEvent(player, Math.min(20, Math.max(0, (int) food + player.getFoodLevel()))); + Bukkit.getPluginManager().callEvent(e); + if (e.isCancelled()) { + return targets.size() > 0; + } player.setFoodLevel(Math.min(20, Math.max(0, (int) food + player.getFoodLevel()))); player.setSaturation(Math.min( player.getFoodLevel(), diff --git a/src/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java index 672c8bf2..18ff53c9 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ForgetTargetsMechanic.java @@ -50,7 +50,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String key = settings.getString(KEY, ""); DynamicSkill.getCastData(caster).remove(key); diff --git a/src/com/sucy/skill/dynamic/mechanic/HealMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/HealMechanic.java similarity index 92% rename from src/com/sucy/skill/dynamic/mechanic/HealMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/HealMechanic.java index 07966e1a..76a1fe9c 100644 --- a/src/com/sucy/skill/dynamic/mechanic/HealMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/HealMechanic.java @@ -55,9 +55,10 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean percent = settings.getString(TYPE, "health").toLowerCase().equals("percent"); - double value = parseValues(caster, VALUE, level, 1.0); + boolean ignoreCurse = settings.getBool("ignores-curse", false); + double value = parseValues(caster, VALUE, level, 1.0, 0); if (value < 0) { return false; } for (LivingEntity target : targets) { if (target.isDead()) { continue; } @@ -67,7 +68,7 @@ public boolean execute(LivingEntity caster, int level, List target amount = target.getMaxHealth() * value / 100; } - SkillHealEvent event = new SkillHealEvent(caster, target, amount); + SkillHealEvent event = new SkillHealEvent(caster, target, amount, ignoreCurse); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { VersionManager.heal(target, event.getAmount()); diff --git a/src/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java similarity index 89% rename from src/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java index cd39d965..26a6494c 100644 --- a/src/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/HealthSetMechanic.java @@ -18,8 +18,8 @@ public String getKey() { } @Override - public boolean execute(final LivingEntity caster, final int level, final List targets) { - final double health = Math.max(1, parseValues(caster, HEALTH, level, 1)); + public boolean execute(final LivingEntity caster, final int level, final List targets, double critChance) { + final double health = Math.max(1, parseValues(caster, HEALTH, level, 1, 0)); for (final LivingEntity target : targets) { target.setHealth(Math.min(health, target.getMaxHealth())); diff --git a/src/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java index 69ecfc40..b4544bef 100644 --- a/src/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/HeldItemMechanic.java @@ -51,9 +51,9 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { - int slot = (int) parseValues(caster, SLOT, level, 0); + int slot = (int) parseValues(caster, SLOT, level, 0, 0); boolean worked = false; for (LivingEntity target : targets) diff --git a/src/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java similarity index 94% rename from src/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java index 835209a0..1aa011a0 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ImmunityMechanic.java @@ -57,17 +57,17 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(TYPE)) { return false; } String key = settings.getString(TYPE); - double seconds = parseValues(caster, SECONDS, level, 3.0); - double multiplier = parseValues(caster, MULTIPLIER, level, 0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); + double multiplier = parseValues(caster, MULTIPLIER, level, 0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { - FlagManager.addFlag(target, "immune:" + key.toUpperCase().replace(" ", "_"), ticks); + FlagManager.addFlag(caster, target, "immune:" + key.toUpperCase().replace(" ", "_"), ticks); SkillAPI.setMeta(target, META_KEY, multiplier); } return targets.size() > 0; diff --git a/src/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java index 980f181b..edd3f4b6 100644 --- a/src/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/InterruptMechanic.java @@ -52,7 +52,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean worked = false; for (LivingEntity target : targets) diff --git a/src/com/sucy/skill/dynamic/mechanic/ItemMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ItemMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ItemMechanic.java index b919490b..819caee4 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ItemMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemMechanic.java @@ -63,7 +63,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String mat = settings.getString(MATERIAL, "arrow").toUpperCase().replace(" ", "_"); Material material; diff --git a/src/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java index c3142b07..41e39447 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemProjectileMechanic.java @@ -70,6 +70,7 @@ public class ItemProjectileMechanic extends MechanicComponent implements Project private static final String USE_EFFECT = "use-effect"; private static final String EFFECT_KEY = "effect-key"; + private double critChance; /** * Creates the list of indicators for the skill @@ -83,20 +84,20 @@ public class ItemProjectileMechanic extends MechanicComponent implements Project public void makeIndicators(List list, Player caster, List targets, int level) { targets.forEach(target -> { // Get common values - int amount = (int) parseValues(caster, AMOUNT, level, 1.0); - double speed = parseValues(caster, "velocity", level, 1); + int amount = (int) parseValues(caster, AMOUNT, level, 1.0, 0); + double speed = parseValues(caster, "velocity", level, 1, 0); String spread = settings.getString(SPREAD, "cone").toLowerCase(); // Apply the spread type if (spread.equals("rain")) { - double radius = parseValues(caster, RADIUS, level, 2.0); + double radius = parseValues(caster, RADIUS, level, 2.0, 0); if (indicatorType == IndicatorType.DIM_2) { IIndicator indicator = new CircleIndicator(radius); indicator.moveTo(target.getLocation().add(0, 0.1, 0)); list.add(indicator); } else { - double height = parseValues(caster, HEIGHT, level, 8.0); + double height = parseValues(caster, HEIGHT, level, 8.0, 0); IIndicator indicator = new CylinderIndicator(radius, height); indicator.moveTo(target.getLocation()); list.add(indicator); @@ -107,7 +108,7 @@ public void makeIndicators(List list, Player caster, List dirs = CustomProjectile.calcSpread(dir, angle, amount); Location loc = caster.getLocation().add(0, caster.getEyeHeight(), 0); for (Vector d : dirs) { @@ -135,7 +136,8 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + this.critChance = critChance; Material mat = Material.JACK_O_LANTERN; try { mat = Material.valueOf(settings.getString(ITEM).toUpperCase().replace(" ", "_")); @@ -146,8 +148,8 @@ public boolean execute(LivingEntity caster, int level, List target item.setDurability((short) settings.getInt(DATA, 0)); // Get other common values - double speed = parseValues(caster, SPEED, level, 3.0); - int amount = (int) parseValues(caster, AMOUNT, level, 1.0); + double speed = parseValues(caster, SPEED, level, 3.0, 0); + int amount = (int) parseValues(caster, AMOUNT, level, 1.0, 0); String spread = settings.getString(SPREAD, "cone").toLowerCase(); boolean ally = settings.getString(ALLY, "enemy").toLowerCase().equals("ally"); @@ -158,15 +160,15 @@ public boolean execute(LivingEntity caster, int level, List target // Apply the spread type ArrayList list; if (spread.equals("rain")) { - double radius = parseValues(caster, RADIUS, level, 2.0); - double height = parseValues(caster, HEIGHT, level, 8.0); + double radius = parseValues(caster, RADIUS, level, 2.0, 0); + double height = parseValues(caster, HEIGHT, level, 8.0, 0); list = ItemProjectile.rain(caster, loc, item, radius, height, speed, amount, this); } else { Vector dir = target.getLocation().getDirection(); - double right = parseValues(caster, RIGHT, level, 0); - double upward = parseValues(caster, UPWARD, level, 0); - double forward = parseValues(caster, FORWARD, level, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); + double upward = parseValues(caster, UPWARD, level, 0, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); Vector looking = dir.clone().setY(0).normalize(); Vector normal = looking.clone().crossProduct(UP); @@ -177,7 +179,7 @@ public boolean execute(LivingEntity caster, int level, List target dir.normalize(); } dir.multiply(speed); - double angle = parseValues(caster, ANGLE, level, 30.0); + double angle = parseValues(caster, ANGLE, level, 30.0, 0); list = ItemProjectile.spread( caster, dir, @@ -222,9 +224,9 @@ public void callback(CustomProjectile projectile, LivingEntity hit) { if (hit == null) { hit = new TempEntity(projectile.getLocation()); } - ArrayList targets = new ArrayList(); + ArrayList targets = new ArrayList<>(); targets.add(hit); - executeChildren(projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets); + executeChildren(projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets, critChance); projectile.setCallback(null); } } diff --git a/src/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java index 9fc1b2ed..1bd19f15 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ItemRemoveMechanic.java @@ -52,7 +52,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean players = false; for (LivingEntity target : targets) diff --git a/src/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java similarity index 80% rename from src/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java index e1064394..62547bd4 100644 --- a/src/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/LaunchMechanic.java @@ -27,8 +27,12 @@ package com.sucy.skill.dynamic.mechanic; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.log.Logger; + import java.util.List; /** @@ -58,14 +62,14 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } - double forward = parseValues(caster, FORWARD, level, 0); - double upward = parseValues(caster, UPWARD, level, 0); - double right = parseValues(caster, RIGHT, level, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); + double upward = parseValues(caster, UPWARD, level, 0, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); String relative = settings.getString(RELATIVE, "target").toLowerCase(); for (LivingEntity target : targets) { final Vector dir; @@ -81,7 +85,15 @@ public boolean execute(LivingEntity caster, int level, List target dir.multiply(forward); dir.add(nor.multiply(right)).setY(upward); - target.setVelocity(dir); + try { + target.setVelocity(dir); + } + catch (IllegalArgumentException e) { + Logger.bug("Illegal Argument Exception from player " + caster.getName()); + Player p = (Player) caster; + Logger.bug("Caster class is " + SkillAPI.getPlayerData(p).getClass("class").getData().getName()); + e.printStackTrace(); + } } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/LightningMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/LightningMechanic.java similarity index 93% rename from src/com/sucy/skill/dynamic/mechanic/LightningMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/LightningMechanic.java index 7d2dba13..cf0abd2f 100644 --- a/src/com/sucy/skill/dynamic/mechanic/LightningMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/LightningMechanic.java @@ -57,13 +57,13 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } boolean damage = settings.getBool(DAMAGE, true); - double forward = parseValues(caster, FORWARD, level, 0); - double right = parseValues(caster, RIGHT, level, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); for (LivingEntity target : targets) { Vector dir = target.getLocation().getDirection().setY(0).normalize(); Vector nor = dir.clone().crossProduct(up); diff --git a/src/com/sucy/skill/dynamic/mechanic/ManaMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ManaMechanic.java similarity index 96% rename from src/com/sucy/skill/dynamic/mechanic/ManaMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ManaMechanic.java index 8fa5047a..a36c2650 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ManaMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ManaMechanic.java @@ -57,9 +57,9 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean percent = settings.getString(TYPE, "mana").toLowerCase().equals("percent"); - double value = parseValues(caster, VALUE, level, 1.0); + double value = parseValues(caster, VALUE, level, 1.0, 0); boolean worked = false; for (LivingEntity target : targets) { diff --git a/src/com/sucy/skill/dynamic/mechanic/MechanicComponent.java b/src/main/java/com/sucy/skill/dynamic/mechanic/MechanicComponent.java similarity index 100% rename from src/com/sucy/skill/dynamic/mechanic/MechanicComponent.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/MechanicComponent.java diff --git a/src/com/sucy/skill/dynamic/mechanic/MessageMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/MessageMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/MessageMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/MessageMechanic.java index 2f209003..d1316e49 100644 --- a/src/com/sucy/skill/dynamic/mechanic/MessageMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/MessageMechanic.java @@ -54,7 +54,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(MESSAGE)) return false; diff --git a/src/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java similarity index 91% rename from src/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java index 05facba2..711bf59e 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleAnimationMechanic.java @@ -29,6 +29,7 @@ import com.sucy.skill.SkillAPI; import com.sucy.skill.api.Settings; import com.sucy.skill.api.util.ParticleHelper; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.bukkit.scheduler.BukkitRunnable; @@ -42,6 +43,7 @@ public class ParticleAnimationMechanic extends MechanicComponent { private static final String FORWARD = "forward"; + private static final String FORWARD_SCALE = "forward-scale"; private static final String UPWARD = "upward"; private static final String RIGHT = "right"; private static final String STEPS = "steps"; @@ -69,7 +71,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { @@ -77,8 +79,8 @@ public boolean execute(LivingEntity caster, int level, List target } final Settings copy = new Settings(settings); - copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1), 0); - copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0), 0); + copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1, 0), 0); + copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0, 0), 0); copy.set("level", level); new ParticleTask(caster, targets, level, copy); return targets.size() > 0; @@ -88,6 +90,7 @@ private class ParticleTask extends BukkitRunnable { private List targets; + private final LivingEntity caster; private double[] rots; private Vector offset; private Vector dir; @@ -115,10 +118,11 @@ private class ParticleTask extends BukkitRunnable ParticleTask(LivingEntity caster, List targets, int level, Settings settings) { + this.caster = caster; this.targets = targets; this.settings = settings; - this.forward = settings.getDouble(FORWARD, 0); + this.forward = settings.getDouble(FORWARD, 0) + (settings.getDouble(FORWARD_SCALE, 0) * level); this.upward = settings.getDouble(UPWARD, 0); this.right = settings.getDouble(RIGHT, 0); @@ -126,10 +130,10 @@ private class ParticleTask extends BukkitRunnable this.freq = (int) (settings.getDouble(FREQ, 1.0) * 20); this.angle = settings.getInt(ANGLE, 0); this.startAngle = settings.getInt(START, 0); - this.duration = steps * (int) (20 * parseValues(caster, DURATION, level, 3.0)); + this.duration = steps * (int) (20 * parseValues(caster, DURATION, level, 3.0, 0)); this.life = 0; - this.ht = parseValues(caster, H_TRANS, level, 0); - this.vt = parseValues(caster, V_TRANS, level, 0); + this.ht = parseValues(caster, H_TRANS, level, 0, 0); + this.vt = parseValues(caster, V_TRANS, level, 0, 0); this.hc = settings.getInt(H_CYCLES, 1); this.vc = settings.getInt(V_CYCLES, 1); this.hl = duration / hc; @@ -169,7 +173,7 @@ public void run() rotate(offset, rots[j], rots[j + 1]); loc.add(offset); - ParticleHelper.play(loc, settings); + ParticleHelper.play(caster, loc, settings); loc.subtract(offset); rotate(offset, rots[j++], -rots[j++]); } diff --git a/src/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java index f965bc2c..e23af711 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleEffectMechanic.java @@ -43,10 +43,10 @@ public String getKey() { } @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { String key = settings.getString(KEY, skill.getName()); - int duration = (int) (20 * parseValues(caster, DURATION, level, 5)); + int duration = (int) (20 * parseValues(caster, DURATION, level, 5, 0)); EffectPlayer player = new EffectPlayer(settings); for (LivingEntity target : targets) diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleLineMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleLineMechanic.java new file mode 100644 index 00000000..d059c595 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleLineMechanic.java @@ -0,0 +1,65 @@ +package com.sucy.skill.dynamic.mechanic; + +import com.sucy.skill.api.ParticleSettings; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.util.ParticleHelper; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.bukkit.util.Vector; + +import java.util.List; + +public class ParticleLineMechanic extends MechanicComponent { + + private static final String POINTS = "points"; + private static final String UPWARD = "upward"; + + @Override + public String getKey() { + return "particle line"; + } + + @Override + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + if (targets.size() == 0) { + return false; + } + + double points = settings.getDouble(POINTS, 20); + double upward = settings.getDouble(UPWARD, 0); + + Vector offset = new Vector(0, upward, 0); + + final Settings copy = new Settings(settings); + copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1, 0), 0); + copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0, 0), 0); + copy.set("level", level); + + LivingEntity target = targets.get(0); + + Location startLocation = caster.getEyeLocation(); + Location endLocation = target.getEyeLocation(); + + ParticleSettings particleSettings = new ParticleSettings(caster, settings); + + Vector line = endLocation.clone().toVector().subtract(startLocation.toVector()); + double length = line.length(); + double steps = length / points; + for (double i = steps; i < length; i += steps) { + line.multiply(i); + startLocation.add(line); + ParticleHelper.play(particleSettings, startLocation.clone().add(offset)); + startLocation.subtract(line); + line.normalize(); + } + + return targets.size() > 0; + } + + private void rotate(Vector vec, double cos, double sin) { + double x = vec.getX() * cos - vec.getZ() * sin; + vec.setZ(vec.getX() * sin + vec.getZ() * cos); + vec.setX(x); + } + +} diff --git a/src/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java similarity index 94% rename from src/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java index da2dade0..e1619368 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleMechanic.java @@ -60,7 +60,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { @@ -72,8 +72,8 @@ public boolean execute(LivingEntity caster, int level, List target double right = settings.getDouble(RIGHT, 0); final Settings copy = new Settings(settings); - copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1), 0); - copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0), 0); + copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1, 0), 0); + copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0, 0), 0); copy.set("level", level); for (LivingEntity target : targets) @@ -83,7 +83,7 @@ public boolean execute(LivingEntity caster, int level, List target Vector side = dir.clone().crossProduct(UP); loc.add(dir.multiply(forward)).add(0, upward, 0).add(side.multiply(right)); - ParticleHelper.play(loc, copy); + ParticleHelper.play(caster, loc, copy); } return targets.size() > 0; diff --git a/src/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java index 5015fcdb..05547526 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java @@ -68,6 +68,7 @@ public class ParticleProjectileMechanic extends MechanicComponent implements Pro private static final String USE_EFFECT = "use-effect"; private static final String EFFECT_KEY = "effect-key"; + private double critChance; /** * Creates the list of indicators for the skill @@ -81,20 +82,20 @@ public class ParticleProjectileMechanic extends MechanicComponent implements Pro public void makeIndicators(List list, Player caster, List targets, int level) { targets.forEach(target -> { // Get common values - int amount = (int) parseValues(caster, AMOUNT, level, 1.0); - double speed = parseValues(caster, "velocity", level, 1); + int amount = (int) parseValues(caster, AMOUNT, level, 1.0, 0); + double speed = parseValues(caster, "velocity", level, 1, 0); String spread = settings.getString(SPREAD, "cone").toLowerCase(); // Apply the spread type if (spread.equals("rain")) { - double radius = parseValues(caster, RADIUS, level, 2.0); + double radius = parseValues(caster, RADIUS, level, 2.0, 0); if (indicatorType == IndicatorType.DIM_2) { IIndicator indicator = new CircleIndicator(radius); indicator.moveTo(target.getLocation().add(0, 0.1, 0)); list.add(indicator); } else { - double height = parseValues(caster, HEIGHT, level, 8.0); + double height = parseValues(caster, HEIGHT, level, 8.0, 0); IIndicator indicator = new CylinderIndicator(radius, height); indicator.moveTo(target.getLocation()); list.add(indicator); @@ -105,7 +106,7 @@ public void makeIndicators(List list, Player caster, List dirs = CustomProjectile.calcSpread(dir, angle, amount); Location loc = caster.getLocation().add(0, caster.getEyeHeight(), 0); for (Vector d : dirs) { @@ -133,17 +134,18 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { // Get common values - int amount = (int) parseValues(caster, AMOUNT, level, 1.0); + this.critChance = critChance; + int amount = (int) parseValues(caster, AMOUNT, level, 1.0, 0); String spread = settings.getString(SPREAD, "cone").toLowerCase(); boolean ally = settings.getString(ALLY, "enemy").toLowerCase().equals("ally"); settings.set("level", level); final Settings copy = new Settings(settings); - copy.set(ParticleProjectile.SPEED, parseValues(caster, ParticleProjectile.SPEED, level, 1), 0); - copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1), 0); - copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0), 0); + copy.set(ParticleProjectile.SPEED, parseValues(caster, ParticleProjectile.SPEED, level, 1, 0), 0); + copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1, 0), 0); + copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0, 0), 0); // Fire from each target for (LivingEntity target : targets) { @@ -152,15 +154,15 @@ public boolean execute(LivingEntity caster, int level, List target // Apply the spread type ArrayList list; if (spread.equals("rain")) { - double radius = parseValues(caster, RADIUS, level, 2.0); - double height = parseValues(caster, HEIGHT, level, 8.0); + double radius = parseValues(caster, RADIUS, level, 2.0, 0); + double height = parseValues(caster, HEIGHT, level, 8.0, 0); list = ParticleProjectile.rain(caster, level, loc, copy, radius, height, amount, this); } else { Vector dir = target.getLocation().getDirection(); - double right = parseValues(caster, RIGHT, level, 0); - double upward = parseValues(caster, UPWARD, level, 0); - double forward = parseValues(caster, FORWARD, level, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); + double upward = parseValues(caster, UPWARD, level, 0, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); Vector looking = dir.clone().setY(0).normalize(); Vector normal = looking.clone().crossProduct(UP); @@ -170,7 +172,7 @@ public boolean execute(LivingEntity caster, int level, List target dir.setY(0); dir.normalize(); } - double angle = parseValues(caster, ANGLE, level, 30.0); + double angle = parseValues(caster, ANGLE, level, 30.0, 0); list = ParticleProjectile.spread( caster, level, @@ -218,6 +220,6 @@ public void callback(CustomProjectile projectile, LivingEntity hit) { } ArrayList targets = new ArrayList(); targets.add(hit); - executeChildren(projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets); + executeChildren(projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets, critChance); } } diff --git a/src/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java index 37437127..81ca9408 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PassiveMechanic.java @@ -44,6 +44,7 @@ public class PassiveMechanic extends MechanicComponent { private static final String PERIOD = "seconds"; private final Map tasks = new HashMap<>(); + private double critChance; /** * Executes the component @@ -55,11 +56,12 @@ public class PassiveMechanic extends MechanicComponent { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (tasks.containsKey(caster.getEntityId())) { return false; } if (targets.size() > 0) { - final int period = (int) (parseValues(caster, PERIOD, level, 1.0) * 20); + this.critChance = critChance; + final int period = (int) (parseValues(caster, PERIOD, level, 1.0, 0) * 20); final PassiveTask task = new PassiveTask(caster, level, targets, period); tasks.put(caster.getEntityId(), task); @@ -118,7 +120,7 @@ public void run() { } } level = skill.getActiveLevel(caster); - executeChildren(caster, level, targets); + executeChildren(caster, level, targets, critChance); if (skill.checkCancelled()) { cancel(); diff --git a/src/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java index 4d715e9c..fc403f28 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PermissionMechanic.java @@ -54,17 +54,17 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(PERM) || !PluginChecker.isVaultActive()) { return false; } String key = settings.getString(PERM); - double seconds = parseValues(caster, SECONDS, level, 3.0); + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { if (!target.hasPermission(key)) { - FlagManager.addFlag(target, "perm:" + key, ticks); + FlagManager.addFlag(caster, target, "perm:" + key, ticks); } } return targets.size() > 0; diff --git a/src/com/sucy/skill/dynamic/mechanic/PotionMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PotionMechanic.java similarity index 74% rename from src/com/sucy/skill/dynamic/mechanic/PotionMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PotionMechanic.java index b0ea7a03..ac450834 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PotionMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PotionMechanic.java @@ -56,25 +56,21 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } - try { - PotionEffectType potion = PotionEffectType.getByName(settings.getString(POTION, "Absorption") - .toUpperCase() - .replace(' ', '_')); - int tier = (int) parseValues(caster, TIER, level, 1) - 1; - double seconds = parseValues(caster, SECONDS, level, 3.0); - boolean ambient = !settings.getString(AMBIENT, "true").equals("false"); - int ticks = (int) (seconds * 20); - for (LivingEntity target : targets) { - target.addPotionEffect(new PotionEffect(potion, ticks, tier, ambient), true); - } - return targets.size() > 0; - } catch (Exception ex) { - return false; + PotionEffectType potion = PotionEffectType.getByName(settings.getString(POTION, "Absorption") + .toUpperCase() + .replace(' ', '_')); + int tier = (int) parseValues(caster, TIER, level, 1, 0) - 1; + double seconds = parseValues(caster, SECONDS, level, 3.0, 0); + boolean ambient = !settings.getString(AMBIENT, "true").equals("false"); + int ticks = (int) (seconds * 20); + for (LivingEntity target : targets) { + target.addPotionEffect(new PotionEffect(potion, ticks, tier, ambient)); } + return targets.size() > 0; } } diff --git a/src/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java similarity index 96% rename from src/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java index 70a98bf6..e9774072 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PotionProjectileMechanic.java @@ -57,6 +57,7 @@ public class PotionProjectileMechanic extends MechanicComponent private static final String POTION = "type"; private static final String ALLY = "group"; private static final String LINGER = "linger"; + private double critChance; @Override public String getKey() { @@ -73,9 +74,10 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { // Get common values + this.critChance = critChance; String potion = settings.getString(POTION, "slowness").toUpperCase().replace(" ", "_"); boolean linger = settings.getString(LINGER, "false").toLowerCase().equals("true") && VersionManager.isVersionAtLeast(VersionManager.V1_9_0); PotionType type; @@ -146,6 +148,6 @@ public void callback(Entity entity, Collection hit) LivingEntity locTarget = new TempEntity(loc); targets.add(locTarget); } - executeChildren(caster, level, targets); + executeChildren(caster, level, targets, critChance); } } diff --git a/src/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java similarity index 92% rename from src/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java index 0eab31d8..71d467e7 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ProjectileMechanic.java @@ -33,6 +33,7 @@ import com.sucy.skill.task.RemoveTask; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.entity.AbstractArrow.PickupStatus; import org.bukkit.entity.Arrow; import org.bukkit.entity.Egg; import org.bukkit.entity.Entity; @@ -69,6 +70,7 @@ public class ProjectileMechanic extends MechanicComponent private static final String RIGHT = "right"; private static final String UPWARD = "upward"; private static final String FORWARD = "forward"; + private double critChance; @Override public String getKey() { @@ -85,12 +87,13 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { // Get common values - int amount = (int) parseValues(caster, AMOUNT, level, 1.0); - double speed = parseValues(caster, SPEED, level, 2.0); - double range = parseValues(caster, RANGE, level, 999); + this.critChance = critChance; + int amount = (int) parseValues(caster, AMOUNT, level, 1.0, 0); + double speed = parseValues(caster, SPEED, level, 2.0, 0); + double range = parseValues(caster, RANGE, level, 999, 0); boolean flaming = settings.getString(FLAMING, "false").equalsIgnoreCase("true"); String spread = settings.getString(SPREAD, "cone").toLowerCase(); String projectile = settings.getString(PROJECTILE, "arrow").toLowerCase(); @@ -129,13 +132,16 @@ public boolean execute(LivingEntity caster, int level, List target // Apply the spread type if (spread.equals("rain")) { - double radius = parseValues(caster, RADIUS, level, 2.0); - double height = parseValues(caster, HEIGHT, level, 8.0); + double radius = parseValues(caster, RADIUS, level, 2.0, 0); + double height = parseValues(caster, HEIGHT, level, 8.0, 0); ArrayList locs = CustomProjectile.calcRain(target.getLocation(), radius, height, amount); for (Location loc : locs) { Projectile p = caster.launchProjectile(type); + if (type == Arrow.class) { + ((Arrow) p).setPickupStatus(PickupStatus.DISALLOWED); + } p.setVelocity(new Vector(0, speed, 0)); p.teleport(loc); SkillAPI.setMeta(p, LEVEL, level); @@ -151,10 +157,10 @@ public boolean execute(LivingEntity caster, int level, List target dir.setY(0); dir.normalize(); } - double angle = parseValues(caster, ANGLE, level, 30.0); - double right = parseValues(caster, RIGHT, level, 0); - double upward = parseValues(caster, UPWARD, level, 0); - double forward = parseValues(caster, FORWARD, level, 0); + double angle = parseValues(caster, ANGLE, level, 30.0, 0); + double right = parseValues(caster, RIGHT, level, 0, 0); + double upward = parseValues(caster, UPWARD, level, 0, 0); + double forward = parseValues(caster, FORWARD, level, 0, 0); Vector looking = target.getLocation().getDirection().setY(0).normalize(); Vector normal = looking.clone().crossProduct(UP); @@ -168,6 +174,9 @@ public boolean execute(LivingEntity caster, int level, List target { p.teleport(target.getLocation().add(looking).add(0, upward + 0.5, 0).add(p.getVelocity()).setDirection(d)); } + else { + ((Arrow) p).setPickupStatus(PickupStatus.DISALLOWED); + } p.setVelocity(d.multiply(speed)); SkillAPI.setMeta(p, MechanicListener.P_CALL, this); SkillAPI.setMeta(p, LEVEL, level); @@ -194,7 +203,7 @@ public void callback(Projectile projectile, LivingEntity hit) ArrayList targets = new ArrayList(); targets.add(hit); - executeChildren((LivingEntity) projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets); + executeChildren((LivingEntity) projectile.getShooter(), SkillAPI.getMetaInt(projectile, LEVEL), targets, critChance); SkillAPI.removeMeta(projectile, MechanicListener.P_CALL); projectile.remove(); } diff --git a/src/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java index 74b216f0..ba628e21 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PurgeMechanic.java @@ -64,7 +64,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { boolean worked = false; String status = settings.getString(STATUS, "None").toLowerCase(); diff --git a/src/com/sucy/skill/dynamic/mechanic/PushMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/PushMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/PushMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/PushMechanic.java index 133c2c9d..c1ad4d4d 100644 --- a/src/com/sucy/skill/dynamic/mechanic/PushMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/PushMechanic.java @@ -55,12 +55,12 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } - final double speed = parseValues(caster, SPEED, level, 3.0); + final double speed = parseValues(caster, SPEED, level, 3.0, 0); final String type = settings.getString("type", "scaled").toLowerCase(); final List sources = RememberTarget.remember(caster, settings.getString(SOURCE, "_none")); diff --git a/src/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java index 1437692a..266648e3 100644 --- a/src/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/RememberTargetsMechanic.java @@ -53,7 +53,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java similarity index 89% rename from src/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java index dba3b7cb..8e860380 100644 --- a/src/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/RepeatMechanic.java @@ -45,6 +45,7 @@ public class RepeatMechanic extends MechanicComponent { private static final String STOP_ON_FAIL = "stop-on-fail"; private final Map> tasks = new HashMap<>(); + private double critChance; /** * Executes the component @@ -56,9 +57,10 @@ public class RepeatMechanic extends MechanicComponent { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() > 0) { - final int count = (int) parseValues(caster, REPETITIONS, level, 3.0); + this.critChance = critChance; + final int count = (int) parseValues(caster, REPETITIONS, level, 3.0, 0); if (count <= 0) { return false; } final int delay = (int) (settings.getDouble(DELAY, 0.0) * 20); @@ -121,14 +123,23 @@ public void run() { for (int i = 0; i < targets.size(); i++) { if (targets.get(i).isDead() || !targets.get(i).isValid()) { targets.remove(i); } } + int level = 1; - if (!skill.isActive(caster) || targets.size() == 0) { - cancel(); - return; + if (!skill.isActive(caster)) { + if (skill.getMaxLevel() != 999) { + cancel(); + return; + } } - - final int level = skill.getActiveLevel(caster); - boolean success = executeChildren(caster, level, targets); + else { + level = skill.getActiveLevel(caster); + } + + if (targets.size() == 0) { + cancel(); + return; + } + boolean success = executeChildren(caster, level, targets, critChance); if (--count <= 0 || (!success && stopOnFail)) { cancel(); diff --git a/src/com/sucy/skill/dynamic/mechanic/SoundMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/SoundMechanic.java similarity index 76% rename from src/com/sucy/skill/dynamic/mechanic/SoundMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/SoundMechanic.java index ecaf0a9e..fee45fed 100644 --- a/src/com/sucy/skill/dynamic/mechanic/SoundMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/SoundMechanic.java @@ -1,21 +1,21 @@ /** * SkillAPI * com.sucy.skill.dynamic.mechanic.SoundMechanic - * + *

* The MIT License (MIT) - * + *

* Copyright (c) 2014 Steven Sucy - * + *

* Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software") to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + *

* The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,18 +29,18 @@ import com.sucy.skill.log.Logger; import org.bukkit.Sound; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import java.util.List; /** * Plays a particle effect */ -public class SoundMechanic extends MechanicComponent -{ - private static final String SOUND = "sound"; +public class SoundMechanic extends MechanicComponent { + private static final String SOUND = "sound"; private static final String SOUND2 = "newsound"; private static final String VOLUME = "volume"; - private static final String PITCH = "pitch"; + private static final String PITCH = "pitch"; @Override public String getKey() { @@ -57,31 +57,32 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) - { - if (targets.size() == 0) - { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + if (targets.size() == 0) { return false; } String type = settings.getString(SOUND, settings.getString(SOUND2, "")).toUpperCase().replace(" ", "_"); - try - { + boolean onlyCaster = settings.getBool("onlycaster", true); + + try { Sound sound = Sound.valueOf(type); - float volume = (float) parseValues(caster, VOLUME, level, 100.0) / 100; - float pitch = (float) parseValues(caster, PITCH, level, 0.0); + float volume = (float) parseValues(caster, VOLUME, level, 100.0, 0) / 100; + float pitch = (float) parseValues(caster, PITCH, level, 0.0, 0); volume = Math.max(0, volume); pitch = Math.min(2, Math.max(0.5f, pitch)); - for (LivingEntity target : targets) - { - target.getWorld().playSound(target.getLocation(), sound, volume, pitch); + if (onlyCaster) { + Player p = (Player) caster; + p.playSound(caster.getLocation(), sound, volume, pitch); + } else { + for (LivingEntity target : targets) { + target.getWorld().playSound(target.getLocation(), sound, volume, pitch); + } } return targets.size() > 0; - } - catch (Exception ex) - { + } catch (Exception ex) { Logger.invalid("Invalid sound type: " + type); return false; } diff --git a/src/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java similarity index 94% rename from src/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java index bf476df9..e782edbd 100644 --- a/src/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/SpeedMechanic.java @@ -56,16 +56,16 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { - float multiplier = (float) parseValues(caster, MULTIPLIER, level, 1.2); - double seconds = parseValues(caster, DURATION, level, 3.0); + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { + float multiplier = (float) parseValues(caster, MULTIPLIER, level, 1.2, 0); + double seconds = parseValues(caster, DURATION, level, 3.0, 0); int ticks = (int) (seconds * 20); boolean worked = false; for (LivingEntity target : targets) { if (!(target instanceof Player)) { continue; } AttributeListener.refreshSpeed((Player) target); - FlagManager.addFlag(target, MechanicListener.SPEED_KEY, ticks); + FlagManager.addFlag(caster, target, MechanicListener.SPEED_KEY, ticks); ((Player) target).setWalkSpeed(multiplier * ((Player) target).getWalkSpeed()); worked = true; } diff --git a/src/com/sucy/skill/dynamic/mechanic/StatusMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/StatusMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/StatusMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/StatusMechanic.java index c28a11c0..0d27d4cb 100644 --- a/src/com/sucy/skill/dynamic/mechanic/StatusMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/StatusMechanic.java @@ -53,16 +53,16 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY, "stun").toLowerCase(); - double seconds = parseValues(caster, DURATION, level, 3.0); + double seconds = parseValues(caster, DURATION, level, 3.0, 0); int ticks = (int) (seconds * 20); for (LivingEntity target : targets) { - FlagManager.addFlag(target, key, ticks); + FlagManager.addFlag(caster, target, key, ticks); } return targets.size() > 0; } diff --git a/src/com/sucy/skill/dynamic/mechanic/TauntMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/TauntMechanic.java similarity index 86% rename from src/com/sucy/skill/dynamic/mechanic/TauntMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/TauntMechanic.java index 79ab390b..85f1348b 100644 --- a/src/com/sucy/skill/dynamic/mechanic/TauntMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/TauntMechanic.java @@ -26,8 +26,11 @@ */ package com.sucy.skill.dynamic.mechanic; +import com.sucy.skill.api.event.PlayerTauntEvent; import com.sucy.skill.hook.MythicMobsHook; import com.sucy.skill.hook.PluginChecker; + +import org.bukkit.Bukkit; import org.bukkit.entity.Creature; import org.bukkit.entity.LivingEntity; @@ -55,16 +58,18 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { - double amount = parseValues(caster, AMOUNT, level, 1); + double amount = parseValues(caster, AMOUNT, level, 1, 0); boolean taunted = false; for (LivingEntity entity : targets) { if (entity instanceof Creature && entity != caster) { if (PluginChecker.isMythicMobsActive() && MythicMobsHook.isMonster(entity)) { - MythicMobsHook.taunt(entity, caster, amount); + PlayerTauntEvent e = new PlayerTauntEvent(caster, entity, amount); + Bukkit.getPluginManager().callEvent(e); + MythicMobsHook.taunt(entity, caster, e.getAmount()); } else { ((Creature) entity).setTarget(caster); diff --git a/src/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java index 47f4d113..714d4015 100644 --- a/src/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/TriggerMechanic.java @@ -32,6 +32,7 @@ public class TriggerMechanic extends MechanicComponent { private TriggerHandler triggerHandler; private boolean once; private boolean stackable; + private double critChance; @Override public void load(final DynamicSkill skill, final DataSection dataSection) { @@ -57,9 +58,10 @@ public String getKey() { @Override public boolean execute( - final LivingEntity caster, final int level, final List targets) { + final LivingEntity caster, final int level, final List targets, double critChance) { + this.critChance = critChance; - final int ticks = (int)(20 * parseValues(caster, DURATION, level, 5)); + final int ticks = (int)(20 * parseValues(caster, DURATION, level, 5, 0)); boolean worked = false; for (final LivingEntity target : targets) { @@ -115,7 +117,7 @@ private Receiver() { } @Override - public boolean execute(final LivingEntity target, final int level, final List targets) { + public boolean execute(final LivingEntity target, final int level, final List targets, double critChance) { if (!CASTER_MAP.containsKey(target.getEntityId())) return false; final List contexts; @@ -129,7 +131,7 @@ public boolean execute(final LivingEntity target, final int level, final List

  • targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY); - double amount = parseValues(caster, AMOUNT, level, 1) * targets.size(); + double amount = parseValues(caster, AMOUNT, level, 1, 0) * targets.size(); HashMap data = DynamicSkill.getCastData(caster); - if (!data.containsKey(key)) { data.put(key, amount); } else { data.put(key, amount + (Double) data.get(key)); } + if (!data.containsKey(key)) { + data.put(key, amount); + } else { + data.put(key, amount + (double) data.get(key)); + } return true; } } diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java index 6c6d77ed..4f64a74e 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueAttributeMechanic.java @@ -57,7 +57,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!settings.has(KEY) || !settings.has(ATTR) || !(targets.get(0) instanceof Player)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java similarity index 96% rename from src/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java index 7bea3b83..53885aee 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueCopyMechanic.java @@ -21,7 +21,7 @@ public String getKey() { @Override public boolean execute( - final LivingEntity caster, final int level, final List targets) { + final LivingEntity caster, final int level, final List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java index 42109e67..a8317e32 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueDistanceMechanic.java @@ -30,7 +30,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(final LivingEntity caster, final int level, final List targets) + public boolean execute(final LivingEntity caster, final int level, final List targets, double critChance) { if (!settings.has(KEY) || !(caster instanceof Player)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java index 4ada14b0..20288f30 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueHealthMechanic.java @@ -51,7 +51,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { final String key = settings.getString(KEY); final String type = settings.getString(TYPE, "current").toLowerCase(); final HashMap data = DynamicSkill.getCastData(caster); diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java index 90a6aec1..ae968dbf 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLocationMechanic.java @@ -54,7 +54,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!settings.has(KEY)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java index ffc82a99..428cddf2 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreMechanic.java @@ -57,11 +57,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY); - double multiplier = parseValues(caster, MULTIPLIER, level, 1); + double multiplier = parseValues(caster, MULTIPLIER, level, 1, 0); boolean offhand = settings.getString(HAND, "").equalsIgnoreCase("offhand"); String regex = settings.getString(REGEX, "Damage: {value}"); diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java index 2179eae0..f6211ff0 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueLoreSlotMechanic.java @@ -54,11 +54,11 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY) || !(caster instanceof Player)) { return false; } String key = settings.getString(KEY); - double multiplier = parseValues(caster, MULTIPLIER, level, 1); + double multiplier = parseValues(caster, MULTIPLIER, level, 1, 0); int slot = settings.getInt(SLOT); String regex = settings.getString(REGEX, "Damage: {value}"); diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java index b34ee25a..0de30906 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueManaMechanic.java @@ -55,7 +55,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!(targets.get(0) instanceof Player)) return false; final PlayerData player = SkillAPI.getPlayerData((Player)targets.get(0)); diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java similarity index 97% rename from src/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java index f9fec5db..5347cd4f 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueMultiplyMechanic.java @@ -54,13 +54,13 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY); - double multiplier = parseValues(caster, MULTIPLIER, level, 1); + double multiplier = parseValues(caster, MULTIPLIER, level, 1, 0); HashMap data = DynamicSkill.getCastData(caster); if (data.containsKey(key)) { data.put(key, multiplier * (Double) data.get(key)); } return true; diff --git a/src/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java similarity index 72% rename from src/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java index ce417aea..be850a5c 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValuePlaceholderMechanic.java @@ -34,7 +34,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!PluginChecker.isPlaceholderAPIActive()) { return false; @@ -48,17 +48,16 @@ public boolean execute(LivingEntity caster, int level, List target final String value = PlaceholderAPIHook.format(placeholder, (Player)targets.get(0)); - switch (type.charAt(0)) { - case 'S': // STRING - DynamicSkill.getCastData(caster).put(key, value); - break; - default: // NUMBER - try { - DynamicSkill.getCastData(caster).put(key, Double.parseDouble(value)); - } catch (final Exception ex) { - Logger.invalid(placeholder + " is not a valid numeric placeholder - PlaceholderAPI returned " + value); - return false; - } + // NUMBER + if (type.charAt(0) == 'S') { // STRING + DynamicSkill.getCastData(caster).put(key, value); + } else { + try { + DynamicSkill.getCastData(caster).put(key, Double.parseDouble(value)); + } catch (final Exception ex) { + Logger.invalid(placeholder + " is not a valid numeric placeholder - PlaceholderAPI returned " + value); + return false; + } } return true; } diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java similarity index 93% rename from src/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java index d575935b..5ddfbee1 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueRandomMechanic.java @@ -56,15 +56,15 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY); boolean triangular = settings.getString(TYPE).toUpperCase().equals("triangular"); - double min = parseValues(caster, MIN, level, 1); - double max = parseValues(caster, MAX, level, 1); + double min = parseValues(caster, MIN, level, 1, 0); + double max = parseValues(caster, MAX, level, 1, 0); HashMap data = DynamicSkill.getCastData(caster); double rand = triangular ? 0.5 * (Math.random() + Math.random()) : Math.random(); diff --git a/src/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java similarity index 95% rename from src/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java index 4f1c2152..f1ef28dd 100644 --- a/src/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ValueSetMechanic.java @@ -54,13 +54,13 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { return false; } String key = settings.getString(KEY); - double value = parseValues(caster, VALUE, level, 1); + double value = parseValues(caster, VALUE, level, 1, 0); HashMap data = DynamicSkill.getCastData(caster); data.put(key, value); return true; diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java index ff4bbdc9..20022740 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpLocMechanic.java @@ -60,7 +60,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java similarity index 94% rename from src/com/sucy/skill/dynamic/mechanic/WarpMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java index 173541ab..b88f575e 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java @@ -60,16 +60,16 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } // Get the world boolean throughWalls = settings.getString(WALL, "false").toLowerCase().equals("true"); - double forward = parseValues(caster, FORWARD, level, 0.0); - double upward = parseValues(caster, UPWARD, level, 0.0); - double right = parseValues(caster, RIGHT, level, 0.0); + double forward = parseValues(caster, FORWARD, level, 0.0, 0); + double upward = parseValues(caster, UPWARD, level, 0.0, 0); + double right = parseValues(caster, RIGHT, level, 0.0, 0); for (LivingEntity target : targets) { Vector dir = target.getLocation().getDirection(); diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java index b6173160..d7ab66c6 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java @@ -59,7 +59,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { return false; } @@ -67,7 +67,7 @@ public boolean execute(LivingEntity caster, int level, List target // Get the world boolean throughWalls = settings.getString(WALL, "false").toLowerCase().equals("true"); boolean horizontal = !settings.getString(HORIZONTAL, "true").toLowerCase().equals("false"); - double distance = parseValues(caster, DISTANCE, level, 3.0); + double distance = parseValues(caster, DISTANCE, level, 3.0, 0); for (LivingEntity target : targets) { Location loc; diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java index 5e8f0232..09134f48 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpSwapMechanic.java @@ -51,7 +51,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() > 0) { diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java index 2e7cffde..ea533058 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpTargetMechanic.java @@ -52,7 +52,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0) { diff --git a/src/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java similarity index 98% rename from src/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java index 7c593267..310fb146 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpValueMechanic.java @@ -55,7 +55,7 @@ public String getKey() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (targets.size() == 0 || !settings.has(KEY)) { diff --git a/src/com/sucy/skill/dynamic/mechanic/WolfMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WolfMechanic.java similarity index 94% rename from src/com/sucy/skill/dynamic/mechanic/WolfMechanic.java rename to src/main/java/com/sucy/skill/dynamic/mechanic/WolfMechanic.java index a6c30894..e3d17789 100644 --- a/src/com/sucy/skill/dynamic/mechanic/WolfMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WolfMechanic.java @@ -70,7 +70,7 @@ public class WolfMechanic extends MechanicComponent { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { if (!(caster instanceof Player)) { return false; } @@ -80,10 +80,10 @@ public boolean execute(LivingEntity caster, int level, List target final Player player = (Player) caster; String color = settings.getString(COLOR); - double health = parseValues(player, HEALTH, level, 10.0); + double health = parseValues(player, HEALTH, level, 10.0, 0); String name = TextFormatter.colorString(settings.getString(NAME, "").replace("{player}", player.getName())); - double damage = parseValues(player, DAMAGE, level, 3.0); - double amount = parseValues(player, AMOUNT, level, 1.0); + double damage = parseValues(player, DAMAGE, level, 3.0, 0); + double amount = parseValues(player, AMOUNT, level, 1.0, 0); boolean sitting = settings.getString(SITTING, "false").equalsIgnoreCase("true"); List skills = settings.getStringList(SKILLS); @@ -94,7 +94,7 @@ public boolean execute(LivingEntity caster, int level, List target } catch (Exception ex) { /* Invalid color */ } } - double seconds = parseValues(player, SECONDS, level, 10.0); + double seconds = parseValues(player, SECONDS, level, 10.0, 0); int ticks = (int) (seconds * 20); List wolves = new ArrayList<>(); for (LivingEntity target : targets) { @@ -137,7 +137,7 @@ public boolean execute(LivingEntity caster, int level, List target // Apply children to the wolves if (wolves.size() > 0) { - executeChildren(player, level, wolves); + executeChildren(player, level, wolves, critChance); return true; } return false; diff --git a/src/com/sucy/skill/dynamic/target/AreaTarget.java b/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java similarity index 98% rename from src/com/sucy/skill/dynamic/target/AreaTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java index c52b8d72..83decf47 100644 --- a/src/com/sucy/skill/dynamic/target/AreaTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java @@ -50,7 +50,7 @@ public class AreaTarget extends TargetComponent { List getTargets( final LivingEntity caster, final int level, final List targets) { - final double radius = parseValues(caster, RADIUS, level, 3.0); + final double radius = parseValues(caster, RADIUS, level, 3.0, 0); final boolean random = settings.getBool(RANDOM, false); return determineTargets(caster, level, targets, t -> shuffle(Nearby.getLivingNearby(t.getLocation(), radius), random)); } @@ -58,7 +58,7 @@ List getTargets( /** {@inheritDoc} */ @Override void makeIndicators(final List list, final Player caster, final LivingEntity target, final int level) { - makeCircleIndicator(list, target, parseValues(caster, RADIUS, level, 3.0)); + makeCircleIndicator(list, target, parseValues(caster, RADIUS, level, 3.0, 0)); } @Override diff --git a/src/com/sucy/skill/dynamic/target/ConeTarget.java b/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java similarity index 89% rename from src/com/sucy/skill/dynamic/target/ConeTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java index 36df9826..d1fcc23f 100644 --- a/src/com/sucy/skill/dynamic/target/ConeTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java @@ -44,16 +44,16 @@ public class ConeTarget extends TargetComponent { /** {@inheritDoc} */ @Override void makeIndicators(List list, Player caster, LivingEntity target, int level) { - double range = parseValues(caster, RANGE, level, 3.0); - double angle = parseValues(caster, ANGLE, level, 90.0); + double range = parseValues(caster, RANGE, level, 3.0, 0); + double angle = parseValues(caster, ANGLE, level, 90.0, 0); makeConeIndicator(list, target, range, angle); } /** {@inheritDoc} */ @Override List getTargets(LivingEntity caster, int level, List targets) { - double range = parseValues(caster, RANGE, level, 3.0); - double angle = parseValues(caster, ANGLE, level, 90.0); + double range = parseValues(caster, RANGE, level, 3.0, 0); + double angle = parseValues(caster, ANGLE, level, 90.0, 0); return determineTargets(caster, level, targets, t -> TargetHelper.getConeTargets(t, angle, range)); } diff --git a/src/com/sucy/skill/dynamic/target/LinearTarget.java b/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java similarity index 99% rename from src/com/sucy/skill/dynamic/target/LinearTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java index 142f7fe2..a0a1c1d4 100644 --- a/src/com/sucy/skill/dynamic/target/LinearTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java @@ -45,8 +45,8 @@ public class LinearTarget extends TargetComponent { @Override List getTargets( final LivingEntity caster, final int level, final List targets) { - final double tolerance = parseValues(caster, TOLERANCE, level, 4.0); - final double range = parseValues(caster, RANGE, level, 5.0); + final double tolerance = parseValues(caster, TOLERANCE, level, 4.0, 0); + final double range = parseValues(caster, RANGE, level, 5.0, 0); return determineTargets(caster, level, targets, t -> TargetHelper.getLivingTargets(t, range, tolerance)); } diff --git a/src/com/sucy/skill/dynamic/target/LocationTarget.java b/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java similarity index 99% rename from src/com/sucy/skill/dynamic/target/LocationTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java index bb3f9cab..a584afa7 100644 --- a/src/com/sucy/skill/dynamic/target/LocationTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java @@ -58,7 +58,7 @@ public void makeIndicators(List list, Player caster, LivingEntity ta @Override List getTargets( final LivingEntity caster, final int level, final List targets) { - final double range = parseValues(caster, RANGE, level, 5.0); + final double range = parseValues(caster, RANGE, level, 5.0, 0); final boolean groundOnly = !settings.getString(GROUND, "true").toLowerCase().equals("false"); return determineTargets(caster, level, targets, t -> getTargetLoc(caster, t, range, groundOnly)); } diff --git a/src/com/sucy/skill/dynamic/target/NearestTarget.java b/src/main/java/com/sucy/skill/dynamic/target/NearestTarget.java similarity index 98% rename from src/com/sucy/skill/dynamic/target/NearestTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/NearestTarget.java index 8cc602d6..3553023a 100644 --- a/src/com/sucy/skill/dynamic/target/NearestTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/NearestTarget.java @@ -48,7 +48,7 @@ public class NearestTarget extends TargetComponent { List getTargets( final LivingEntity caster, final int level, final List targets) { - final double radius = parseValues(caster, RADIUS, level, 3.0); + final double radius = parseValues(caster, RADIUS, level, 3.0, 0); final List result = new ArrayList<>(); for (LivingEntity target : targets) { final Comparator comparator = new DistanceComparator(target.getLocation()); @@ -63,7 +63,7 @@ List getTargets( /** {@inheritDoc} */ @Override void makeIndicators(final List list, final Player caster, final LivingEntity target, final int level) { - makeCircleIndicator(list, target, parseValues(caster, RADIUS, level, 3.0)); + makeCircleIndicator(list, target, parseValues(caster, RADIUS, level, 3.0, 0)); } @Override diff --git a/src/com/sucy/skill/dynamic/target/OffsetTarget.java b/src/main/java/com/sucy/skill/dynamic/target/OffsetTarget.java similarity index 99% rename from src/com/sucy/skill/dynamic/target/OffsetTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/OffsetTarget.java index 1ec94e5f..5d7b7eaa 100644 --- a/src/com/sucy/skill/dynamic/target/OffsetTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/OffsetTarget.java @@ -61,9 +61,9 @@ List getTargets( private TempEntity getTargetLoc(LivingEntity caster, int level, LivingEntity t) { final boolean horizontal = settings.getBool(HORIZONTAL, false); - final double forward = parseValues(caster, FORWARD, level, 0); - final double upward = parseValues(caster, UPWARD, level, 0); - final double right = parseValues(caster, RIGHT, level, 0); + final double forward = parseValues(caster, FORWARD, level, 0, 0); + final double upward = parseValues(caster, UPWARD, level, 0, 0); + final double right = parseValues(caster, RIGHT, level, 0, 0); final Vector dir = t.getLocation().getDirection().setY(0).normalize(); if (horizontal) { dir.setY(0).normalize(); } diff --git a/src/com/sucy/skill/dynamic/target/RememberTarget.java b/src/main/java/com/sucy/skill/dynamic/target/RememberTarget.java similarity index 100% rename from src/com/sucy/skill/dynamic/target/RememberTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/RememberTarget.java diff --git a/src/com/sucy/skill/dynamic/target/SelfTarget.java b/src/main/java/com/sucy/skill/dynamic/target/SelfTarget.java similarity index 100% rename from src/com/sucy/skill/dynamic/target/SelfTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/SelfTarget.java diff --git a/src/com/sucy/skill/dynamic/target/SingleTarget.java b/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java similarity index 94% rename from src/com/sucy/skill/dynamic/target/SingleTarget.java rename to src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java index 76d295a8..7b425ded 100644 --- a/src/com/sucy/skill/dynamic/target/SingleTarget.java +++ b/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java @@ -45,8 +45,8 @@ public class SingleTarget extends TargetComponent { /** {@inheritDoc} */ @Override public void makeIndicators(List list, Player caster, LivingEntity target, int level) { - double range = parseValues(caster, RANGE, level, 3.0); - double angle = parseValues(caster, TOLERANCE, level, 4.0); + double range = parseValues(caster, RANGE, level, 3.0, 0); + double angle = parseValues(caster, TOLERANCE, level, 4.0, 0); makeConeIndicator(list, target, range, angle); } @@ -55,8 +55,8 @@ public void makeIndicators(List list, Player caster, LivingEntity ta List getTargets( final LivingEntity caster, final int level, final List targets) { - double range = parseValues(caster, RANGE, level, 5.0); - double tolerance = parseValues(caster, TOLERANCE, level, 4.0); + double range = parseValues(caster, RANGE, level, 5.0, 0); + double tolerance = parseValues(caster, TOLERANCE, level, 4.0, 0); return determineTargets(caster, level, targets, t -> { final LivingEntity target = TargetHelper.getLivingTarget(t, range, tolerance); return target == null ? ImmutableList.of() : ImmutableList.of(target); diff --git a/src/com/sucy/skill/dynamic/target/TargetComponent.java b/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java similarity index 88% rename from src/com/sucy/skill/dynamic/target/TargetComponent.java rename to src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java index 1de78db1..97179c85 100644 --- a/src/com/sucy/skill/dynamic/target/TargetComponent.java +++ b/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java @@ -13,10 +13,12 @@ import com.sucy.skill.dynamic.EffectComponent; import com.sucy.skill.dynamic.TempEntity; import org.bukkit.Location; +import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.function.Function; @@ -51,9 +53,16 @@ public ComponentType getType() { * @return true if applied to something, false otherwise */ @Override - public boolean execute(LivingEntity caster, int level, List targets) { + public boolean execute(LivingEntity caster, int level, List targets, double critChance) { final List list = getTargets(caster, level, targets); - return (!list.isEmpty() && executeChildren(caster, level, list)); + Iterator iter = list.iterator(); + while (iter.hasNext()) { + LivingEntity ent = iter.next(); + if (!ent.isValid()) { + iter.remove(); + } + } + return (!list.isEmpty() && executeChildren(caster, level, list, critChance)); } @Override @@ -126,7 +135,7 @@ List determineTargets( final List from, final Function> conversion) { - final double max = parseValues(caster, MAX, level, 99); + final double max = parseValues(caster, MAX, level, 99, 0); final List list = new ArrayList<>(); from.forEach(target -> { @@ -134,16 +143,22 @@ List determineTargets( final List found = conversion.apply(target); for (LivingEntity entity : found) { if (isValidTarget(caster, target, entity)) { - list.add(entity); + list.add(entity); if (list.size() - count >= max) { break; } } + if (caster.getName().equals(entity.getName()) && self) { + list.add(entity); + if (list.size() - count >= max) { + break; + } + } } }); - if (self) { - list.add(caster); - } +// if (self) { +// list.add(caster); +// } return list; } diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/AccountChangeTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/AccountChangeTrigger.java new file mode 100644 index 00000000..a2b8d4cf --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/AccountChangeTrigger.java @@ -0,0 +1,47 @@ +package com.sucy.skill.dynamic.trigger; + +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.PlayerAccountChangeEvent; + +import org.bukkit.entity.LivingEntity; + +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class AccountChangeTrigger implements Trigger { + + @Override + public String getKey() { + return "ACCOUNT_CHANGE"; + } + + @Override + public Class getEvent() { + return PlayerAccountChangeEvent.class; + } + + /** {@inheritDoc} */ + @Override + public boolean shouldTrigger(final PlayerAccountChangeEvent event, final int level, final Settings settings) { + return true; + } + + /** {@inheritDoc} */ + @Override + public void setValues(final PlayerAccountChangeEvent event, final Map data) { } + + /** {@inheritDoc} */ + @Override + public LivingEntity getCaster(final PlayerAccountChangeEvent event) { + return event.getNewAccount().getPlayer(); + } + + /** {@inheritDoc} */ + @Override + public LivingEntity getTarget(final PlayerAccountChangeEvent event, final Settings settings) { + return event.getNewAccount().getPlayer(); + } +} diff --git a/src/com/sucy/skill/dynamic/trigger/BlockBreakTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/BlockBreakTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/BlockBreakTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/BlockBreakTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/BlockPlaceTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/BlockPlaceTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/BlockPlaceTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/BlockPlaceTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/ClickComboTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/ClickComboTrigger.java new file mode 100644 index 00000000..7fcce54d --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/ClickComboTrigger.java @@ -0,0 +1,71 @@ +package com.sucy.skill.dynamic.trigger; + +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.NeoClickComboEvent; +import com.sucy.skill.api.event.NeoClickComboEvent.ClickType; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +public class ClickComboTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player left clicks."; + } + + @Override + public Class getEvent() { + return NeoClickComboEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of( + EditorOption.dropdown("clicktype", "Click Type", "Which click event to trigger with", + ImmutableList.of("LR", "RL"))); + } + + @Override + public String getKey() { + return "CLICK_COMBO"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(NeoClickComboEvent e) { + return e.getPlayer(); + } + + @Override + public LivingEntity getTarget(NeoClickComboEvent e, Settings s) { + return e.getPlayer(); + } + + @Override + public void setValues(NeoClickComboEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(NeoClickComboEvent e, final int level, Settings s) { + if (e.getType().equals(ClickType.LR) && s.getString("clicktype").equals("LR")) return true; + if (e.getType().equals(ClickType.RL) && s.getString("clicktype").equals("RL")) return true; + return false; + } + +} diff --git a/src/com/sucy/skill/dynamic/trigger/CrouchTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/CrouchTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/CrouchTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/CrouchTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/DamageDeathTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/DamageDeathTrigger.java new file mode 100644 index 00000000..82961560 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/DamageDeathTrigger.java @@ -0,0 +1,73 @@ +package com.sucy.skill.dynamic.trigger; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import java.util.List; +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class DamageDeathTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers if some damage is about to kill the player."; + } + + @Override + public Class getEvent() { + return EntityDamageByEntityEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of(); + } + + @Override + public String getKey() { + return "DAMAGE_DEATH"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(EntityDamageByEntityEvent e) { + if (!(e.getEntity() instanceof LivingEntity)) return null; + return (LivingEntity) e.getEntity(); + } + + @Override + public LivingEntity getTarget(EntityDamageByEntityEvent e, Settings s) { + if (!(e.getEntity() instanceof LivingEntity)) return null; + return (LivingEntity) e.getEntity(); + } + + @Override + public void setValues(EntityDamageByEntityEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(EntityDamageByEntityEvent e, final int level, Settings s) { + if (e.getEntity() != null && e.getCause() != null && e.getEntity() instanceof LivingEntity) { + LivingEntity le = (LivingEntity) e.getEntity(); + return !e.isCancelled() && le.getHealth() <= e.getFinalDamage(); + } + return false; + } +} diff --git a/src/com/sucy/skill/dynamic/trigger/DeathTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/DeathTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/DeathTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/DeathTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/EnvironmentalTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/EnvironmentalTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/EnvironmentalTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/EnvironmentalTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/FlagSetTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/FlagSetTrigger.java new file mode 100644 index 00000000..d8ca41f9 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/FlagSetTrigger.java @@ -0,0 +1,67 @@ +package com.sucy.skill.dynamic.trigger; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.FlagApplyEvent; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +import org.bukkit.entity.LivingEntity; +import java.util.List; +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class FlagSetTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player has a specific flag applied."; + } + + @Override + public Class getEvent() { + return FlagApplyEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of( + EditorOption.list("flags", "Flags", "Which flags to trigger with", ImmutableList.of("stun", "root", "silence", "curse"))); + } + + @Override + public String getKey() { + return "FLAG_APPLY"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(FlagApplyEvent e) { + return e.getCaster(); + } + + @Override + public LivingEntity getTarget(FlagApplyEvent e, Settings s) { + return e.getEntity(); + } + + @Override + public void setValues(FlagApplyEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(FlagApplyEvent e, final int level, Settings s) { + final List types = s.getStringList("flags"); + return types.contains(e.getFlag()); + } +} diff --git a/src/com/sucy/skill/dynamic/trigger/KillTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/KillTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/KillTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/KillTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/LandTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/LandTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/LandTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/LandTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/LaunchTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/LaunchTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/LaunchTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/LaunchTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/LeftClickTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/LeftClickTrigger.java new file mode 100644 index 00000000..3f2ec1ad --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/LeftClickTrigger.java @@ -0,0 +1,79 @@ +package com.sucy.skill.dynamic.trigger; + +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +public class LeftClickTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player left clicks."; + } + + @Override + public Class getEvent() { + return PlayerInteractEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of(); + } + + @Override + public String getKey() { + return "LEFT_CLICK"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(PlayerInteractEvent e) { + return e.getPlayer(); + } + + @Override + public LivingEntity getTarget(PlayerInteractEvent e, Settings s) { + return e.getPlayer(); + } + + @Override + public void setValues(PlayerInteractEvent e, Map data) { + if (data.containsKey("cd-leftclickcooldown")) { + // Only change the attack cooldown data value if it's been at least 50 ms (To get through every trigger usually takes 4ms) + if ((long) data.get("cd-leftclickcooldown") + 50 < System.currentTimeMillis()) { + data.put("api-leftclickcooldown", (double) e.getPlayer().getAttackCooldown()); + } + } + else { + data.put("api-leftclickcooldown", (double) e.getPlayer().getAttackCooldown()); + } + data.put("cd-leftclickcooldown", System.currentTimeMillis()); + return; + + } + + @Override + public boolean shouldTrigger(PlayerInteractEvent e, final int level, Settings s) { + if (e.getHand() != null && e.getHand().equals(EquipmentSlot.HAND)) { + return e.getAction().equals(Action.LEFT_CLICK_AIR) || e.getAction().equals(Action.LEFT_CLICK_BLOCK); + } + return false; + } + +} diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/LoadTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/LoadTrigger.java new file mode 100644 index 00000000..ff1274a2 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/LoadTrigger.java @@ -0,0 +1,47 @@ +package com.sucy.skill.dynamic.trigger; + +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.PlayerLoadCompleteEvent; + +import org.bukkit.entity.LivingEntity; + +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class LoadTrigger implements Trigger { + + @Override + public String getKey() { + return "LOAD"; + } + + @Override + public Class getEvent() { + return PlayerLoadCompleteEvent.class; + } + + /** {@inheritDoc} */ + @Override + public boolean shouldTrigger(final PlayerLoadCompleteEvent event, final int level, final Settings settings) { + return true; + } + + /** {@inheritDoc} */ + @Override + public void setValues(final PlayerLoadCompleteEvent event, final Map data) { } + + /** {@inheritDoc} */ + @Override + public LivingEntity getCaster(final PlayerLoadCompleteEvent event) { + return event.getPlayer(); + } + + /** {@inheritDoc} */ + @Override + public LivingEntity getTarget(final PlayerLoadCompleteEvent event, final Settings settings) { + return event.getPlayer(); + } +} diff --git a/src/com/sucy/skill/dynamic/trigger/MoveTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/MoveTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/MoveTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/MoveTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java similarity index 60% rename from src/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java index b9970976..4a8414ab 100644 --- a/src/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java +++ b/src/main/java/com/sucy/skill/dynamic/trigger/PhysicalDealtTrigger.java @@ -1,38 +1,50 @@ -package com.sucy.skill.dynamic.trigger; - -import com.sucy.skill.api.Settings; -import com.sucy.skill.api.event.PhysicalDamageEvent; -import org.bukkit.entity.LivingEntity; - -import java.util.Map; - -/** - * SkillAPI © 2018 - * com.sucy.skill.dynamic.trigger.BlockBreakTrigger - */ -public class PhysicalDealtTrigger extends PhysicalTrigger { - - /** {@inheritDoc} */ - @Override - public String getKey() { - return "PHYSICAL_DAMAGE"; - } - - /** {@inheritDoc} */ - @Override - public LivingEntity getCaster(final PhysicalDamageEvent event) { - return event.getDamager(); - } - - /** {@inheritDoc} */ - @Override - public LivingEntity getTarget(final PhysicalDamageEvent event, final Settings settings) { - return isUsingTarget(settings) ? event.getTarget() : event.getDamager(); - } - - /** {@inheritDoc} */ - @Override - public void setValues(final PhysicalDamageEvent event, final Map data) { - data.put("api-dealt", event.getDamage()); - } -} +package com.sucy.skill.dynamic.trigger; + +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.PhysicalDamageEvent; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class PhysicalDealtTrigger extends PhysicalTrigger { + + /** {@inheritDoc} */ + @Override + public String getKey() { + return "PHYSICAL_DAMAGE"; + } + + /** {@inheritDoc} */ + @Override + public LivingEntity getCaster(final PhysicalDamageEvent event) { + return event.getDamager(); + } + + /** {@inheritDoc} */ + @Override + public LivingEntity getTarget(final PhysicalDamageEvent event, final Settings settings) { + return isUsingTarget(settings) ? event.getTarget() : event.getDamager(); + } + + /** {@inheritDoc} */ + @Override + public void setValues(final PhysicalDamageEvent event, final Map data) { + Player p = (Player) event.getDamager(); + data.put("api-dealt", event.getDamage()); + if (data.containsKey("cd-attackcooldown")) { + // Only change the attack cooldown data value if it's been at least 50 ms (To get through every trigger usually takes 4ms) + if ((long) data.get("cd-attackcooldown") + 50 < System.currentTimeMillis()) { + data.put("api-attackcooldown", (double) p.getAttackCooldown()); + } + } + else { + data.put("api-attackcooldown", (double) p.getAttackCooldown()); + } + data.put("cd-attackcooldown", System.currentTimeMillis()); + } +} diff --git a/src/com/sucy/skill/dynamic/trigger/PhysicalTakenTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/PhysicalTakenTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/PhysicalTakenTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/PhysicalTakenTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/PhysicalTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/PhysicalTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/PhysicalTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/PhysicalTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/PotionApplyTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/PotionApplyTrigger.java new file mode 100644 index 00000000..4c533a59 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/PotionApplyTrigger.java @@ -0,0 +1,74 @@ +package com.sucy.skill.dynamic.trigger; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityPotionEffectEvent; +import org.bukkit.event.entity.EntityPotionEffectEvent.Action; + +import java.util.List; +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class PotionApplyTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player has a specific flag applied."; + } + + @Override + public Class getEvent() { + return EntityPotionEffectEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of( + EditorOption.list("potions", "Potions", "Which potions to trigger with", + ImmutableList.of("SPEED", "SLOW", "BLINDNESS", "POISON"))); + } + + @Override + public String getKey() { + return "POTION_APPLY"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(EntityPotionEffectEvent e) { + return (LivingEntity) e.getEntity(); + } + + @Override + public LivingEntity getTarget(EntityPotionEffectEvent e, Settings s) { + return (LivingEntity) e.getEntity(); + } + + @Override + public void setValues(EntityPotionEffectEvent e, Map data) { + data.put("api-potion", (double) e.getNewEffect().getAmplifier()); + return; + } + + @Override + public boolean shouldTrigger(EntityPotionEffectEvent e, final int level, Settings s) { + if (!e.getAction().equals(Action.ADDED) && !e.getAction().equals(Action.CHANGED)) return false; + final List potions = s.getStringList("potions"); + for (String potion : potions) { + if (e.getNewEffect().getType().getName().startsWith(potion)) return true; + } + return false; + } +} diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/RightClickEntityTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/RightClickEntityTrigger.java new file mode 100644 index 00000000..3219540a --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/RightClickEntityTrigger.java @@ -0,0 +1,70 @@ +package com.sucy.skill.dynamic.trigger; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.EquipmentSlot; + +import java.util.List; +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class RightClickEntityTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player right clicks an entity."; + } + + @Override + public Class getEvent() { + return PlayerInteractEntityEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of(); + } + + @Override + public String getKey() { + return "RIGHT_CLICK_ENTITY"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(PlayerInteractEntityEvent e) { + return e.getPlayer(); + } + + @Override + public LivingEntity getTarget(PlayerInteractEntityEvent e, Settings s) { + return (LivingEntity) e.getRightClicked(); + } + + @Override + public void setValues(PlayerInteractEntityEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(PlayerInteractEntityEvent e, final int level, Settings s) { + if (e.getHand() != null && e.getHand().equals(EquipmentSlot.HAND)) + return !(e.getRightClicked() instanceof Player) && e.getRightClicked() instanceof LivingEntity; + return false; + } +} diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/RightClickTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/RightClickTrigger.java new file mode 100644 index 00000000..9071057a --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/RightClickTrigger.java @@ -0,0 +1,67 @@ +package com.sucy.skill.dynamic.trigger; + +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; + +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +public class RightClickTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player right clicks."; + } + + @Override + public Class getEvent() { + return PlayerInteractEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of(); + } + + @Override + public String getKey() { + return "RIGHT_CLICK"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(PlayerInteractEvent e) { + return e.getPlayer(); + } + + @Override + public LivingEntity getTarget(PlayerInteractEvent e, Settings s) { + return e.getPlayer(); + } + + @Override + public void setValues(PlayerInteractEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(PlayerInteractEvent e, final int level, Settings s) { + if (e.getHand() != null && e.getHand().equals(EquipmentSlot.HAND)) + return e.getAction().equals(Action.RIGHT_CLICK_AIR) || e.getAction().equals(Action.RIGHT_CLICK_BLOCK); + return false; + } + +} diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/ShootBowTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/ShootBowTrigger.java new file mode 100644 index 00000000..620b2b29 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/ShootBowTrigger.java @@ -0,0 +1,47 @@ +package com.sucy.skill.dynamic.trigger; + +import com.sucy.skill.api.Settings; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityShootBowEvent; + +import java.util.Map; + +/** + * SkillAPI © 2018 + * com.sucy.skill.dynamic.trigger.BlockBreakTrigger + */ +public class ShootBowTrigger implements Trigger { + + @Override + public String getKey() { + return "SHOOTBOW"; + } + + @Override + public Class getEvent() { + return EntityShootBowEvent.class; + } + + /** {@inheritDoc} */ + @Override + public boolean shouldTrigger(final EntityShootBowEvent event, final int level, final Settings settings) { + return true; + } + + /** {@inheritDoc} */ + @Override + public void setValues(final EntityShootBowEvent event, final Map data) { } + + /** {@inheritDoc} */ + @Override + public LivingEntity getCaster(final EntityShootBowEvent event) { + return event.getEntity(); + } + + /** {@inheritDoc} */ + @Override + public LivingEntity getTarget(final EntityShootBowEvent event, final Settings settings) { + return event.getEntity(); + } +} diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/SkillCastTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/SkillCastTrigger.java new file mode 100644 index 00000000..cdcaac8c --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/SkillCastTrigger.java @@ -0,0 +1,67 @@ +package com.sucy.skill.dynamic.trigger; + +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.LivingEntity; +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.PlayerSkillCastSuccessEvent; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +public class SkillCastTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player successfully casts a skill."; + } + + @Override + public Class getEvent() { + return PlayerSkillCastSuccessEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of( + EditorOption.text( + "skill_name", + "Skill Name", + "Skill name", + "")); + } + + @Override + public String getKey() { + return "CAST_SKILL"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(PlayerSkillCastSuccessEvent e) { + return e.getPlayer(); + } + + @Override + public LivingEntity getTarget(PlayerSkillCastSuccessEvent e, Settings s) { + return e.getPlayer(); + } + + @Override + public void setValues(PlayerSkillCastSuccessEvent arg0, Map arg1) { + return; + + } + + @Override + public boolean shouldTrigger(PlayerSkillCastSuccessEvent e, final int level, Settings s) { + return !e.isCancelled(); + } + +} diff --git a/src/com/sucy/skill/dynamic/trigger/SkillDealtTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/SkillDealtTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/SkillDealtTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/SkillDealtTrigger.java diff --git a/src/main/java/com/sucy/skill/dynamic/trigger/SkillHealTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/SkillHealTrigger.java new file mode 100644 index 00000000..d4989417 --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/trigger/SkillHealTrigger.java @@ -0,0 +1,76 @@ +package com.sucy.skill.dynamic.trigger; + +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.LivingEntity; +import com.google.common.collect.ImmutableList; +import com.sucy.skill.api.Settings; +import com.sucy.skill.api.event.SkillHealEvent; +import com.sucy.skill.dynamic.ComponentType; +import com.sucy.skill.dynamic.custom.CustomTrigger; +import com.sucy.skill.dynamic.custom.EditorOption; + +public class SkillHealTrigger implements CustomTrigger { + + @Override + public String getDescription() { + return "Triggers when the player heals something."; + } + + @Override + public Class getEvent() { + return SkillHealEvent.class; + } + + @Override + public List getOptions() { + return ImmutableList.of( + EditorOption.number( + "heal-min", + "Min Healing", + "The minimum healing that needs to be given", + 0, + 0), + EditorOption.number( + "dmg-max", + "Max Healing", + "The maximum healing that can be given", + 999999, + 0)); + } + + @Override + public String getKey() { + return "SKILL_HEAL"; + } + + @Override + public ComponentType getType() { + return ComponentType.TRIGGER; + } + + @Override + public LivingEntity getCaster(SkillHealEvent e) { + return e.getHealer(); + } + + @Override + public LivingEntity getTarget(SkillHealEvent e, Settings s) { + return e.getTarget(); + } + + @Override + public void setValues(SkillHealEvent e, Map data) { + data.put("api-healed", e.getAmount()); + + } + + @Override + public boolean shouldTrigger(SkillHealEvent e, final int level, Settings settings) { + final double min = settings.getDouble("heal-min", 0); + final double max = settings.getDouble("heal-max", 999999); + return !e.isCancelled() && min <= e.getAmount() && max >= e.getAmount(); + } + +} diff --git a/src/com/sucy/skill/dynamic/trigger/SkillTakenTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/SkillTakenTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/SkillTakenTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/SkillTakenTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/SkillTrigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/SkillTrigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/SkillTrigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/SkillTrigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/Trigger.java b/src/main/java/com/sucy/skill/dynamic/trigger/Trigger.java similarity index 100% rename from src/com/sucy/skill/dynamic/trigger/Trigger.java rename to src/main/java/com/sucy/skill/dynamic/trigger/Trigger.java diff --git a/src/com/sucy/skill/dynamic/trigger/TriggerComponent.java b/src/main/java/com/sucy/skill/dynamic/trigger/TriggerComponent.java similarity index 72% rename from src/com/sucy/skill/dynamic/trigger/TriggerComponent.java rename to src/main/java/com/sucy/skill/dynamic/trigger/TriggerComponent.java index d8123e78..2f175e49 100644 --- a/src/com/sucy/skill/dynamic/trigger/TriggerComponent.java +++ b/src/main/java/com/sucy/skill/dynamic/trigger/TriggerComponent.java @@ -3,24 +3,27 @@ import com.sucy.skill.dynamic.ComponentType; import com.sucy.skill.dynamic.EffectComponent; import com.sucy.skill.util.Lists; + +import org.bukkit.Sound; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import java.util.List; +import java.util.Random; /** * SkillAPI © 2018 * com.sucy.skill.dynamic.trigger.TriggerComponent */ public class TriggerComponent extends EffectComponent { - private boolean running = false; public boolean isRunning() { return running; } - public boolean trigger(final LivingEntity caster, final LivingEntity target, final int level) { - return execute(caster, level, Lists.asList(target)); + public boolean trigger(final LivingEntity caster, final LivingEntity target, final int level, double critChance) { + return execute(caster, level, Lists.asList(target), critChance); } @Override @@ -34,10 +37,10 @@ public ComponentType getType() { } @Override - public boolean execute(final LivingEntity caster, final int level, final List targets) { + public boolean execute(final LivingEntity caster, final int level, final List targets, double critChance) { try { running = true; - return executeChildren(caster, level, targets); + return executeChildren(caster, level, targets, critChance); } finally { running = false; } diff --git a/src/com/sucy/skill/gui/handlers/AttributeHandler.java b/src/main/java/com/sucy/skill/gui/handlers/AttributeHandler.java similarity index 100% rename from src/com/sucy/skill/gui/handlers/AttributeHandler.java rename to src/main/java/com/sucy/skill/gui/handlers/AttributeHandler.java diff --git a/src/com/sucy/skill/gui/handlers/DetailsHandler.java b/src/main/java/com/sucy/skill/gui/handlers/DetailsHandler.java similarity index 100% rename from src/com/sucy/skill/gui/handlers/DetailsHandler.java rename to src/main/java/com/sucy/skill/gui/handlers/DetailsHandler.java diff --git a/src/com/sucy/skill/gui/handlers/ProfessHandler.java b/src/main/java/com/sucy/skill/gui/handlers/ProfessHandler.java similarity index 100% rename from src/com/sucy/skill/gui/handlers/ProfessHandler.java rename to src/main/java/com/sucy/skill/gui/handlers/ProfessHandler.java diff --git a/src/com/sucy/skill/gui/handlers/SkillHandler.java b/src/main/java/com/sucy/skill/gui/handlers/SkillHandler.java similarity index 84% rename from src/com/sucy/skill/gui/handlers/SkillHandler.java rename to src/main/java/com/sucy/skill/gui/handlers/SkillHandler.java index 9249836d..324b8e18 100644 --- a/src/com/sucy/skill/gui/handlers/SkillHandler.java +++ b/src/main/java/com/sucy/skill/gui/handlers/SkillHandler.java @@ -1,58 +1,65 @@ -/** - * SkillAPI - * com.sucy.skill.gui.handlers.SkillHandler - *

    - * The MIT License (MIT) - *

    - * Copyright (c) 2016 Steven Sucy - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.gui.handlers; - -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.skills.Skill; -import com.sucy.skill.gui.tool.GUIHolder; - -import java.util.HashMap; - -public class SkillHandler extends GUIHolder { - private HashMap start = new HashMap(); - - @Override - public void onSetup() { - for (String key : data.keySet()) { start.put(key, player.getSkillLevel(key)); } - } - - @Override - public void onClick(Skill type, int slot, boolean left, boolean shift) { - if (left) { - if (player.upgradeSkill(type)) { setPage(page); } - } else if ((SkillAPI.getSettings() - .isAllowDowngrade() || player.getSkillLevel(type.getKey()) > start.get(type.getKey())) - && player.downgradeSkill(type)) { setPage(page); } - } - - @Override - public void onHotBar(Skill type, int from, int to) { - if (player.getSkillBar().isSetup() && type.canCast() && player.hasSkill(type.getName())) { - player.getSkillBar().assign(player.getSkill(type.getName()), to); - } - } -} +/** + * SkillAPI + * com.sucy.skill.gui.handlers.SkillHandler + *

    + * The MIT License (MIT) + *

    + * Copyright (c) 2016 Steven Sucy + *

    + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

    + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.gui.handlers; + +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.gui.tool.GUIHolder; + +import java.util.HashMap; + +import org.bukkit.Bukkit; + +public class SkillHandler extends GUIHolder { + private HashMap start = new HashMap(); + + @Override + public void onSetup() { + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Skill Map 1"); + for (String key : data.keySet()) { start.put(key, player.getSkillLevel(key)); } + if (SkillAPI.debug) Bukkit.getLogger().info("[SkillAPI Debug] Skill Map 2"); + } + + @Override + public void onClick(Skill type, int slot, boolean left, boolean shift) { + if (left) { + if (type.getName().equalsIgnoreCase("Attributes")) { + player.openAttributeMenu(); + } + else if (player.upgradeSkill(type, true)) { setPage(page); } + } else if ((SkillAPI.getSettings() + .isAllowDowngrade() || player.getSkillLevel(type.getKey()) > start.get(type.getKey())) + && player.downgradeSkill(type)) { setPage(page); } + } + + @Override + public void onHotBar(Skill type, int from, int to) { + if (player.getSkillBar().isSetup() && type.canCast() && player.hasSkill(type.getName())) { + player.getSkillBar().assign(player.getSkill(type.getName()), to); + } + } +} diff --git a/src/com/sucy/skill/gui/map/Menu.java b/src/main/java/com/sucy/skill/gui/map/Menu.java similarity index 100% rename from src/com/sucy/skill/gui/map/Menu.java rename to src/main/java/com/sucy/skill/gui/map/Menu.java diff --git a/src/com/sucy/skill/gui/map/SkillDetailMenu.java b/src/main/java/com/sucy/skill/gui/map/SkillDetailMenu.java similarity index 95% rename from src/com/sucy/skill/gui/map/SkillDetailMenu.java rename to src/main/java/com/sucy/skill/gui/map/SkillDetailMenu.java index bc891e24..6c4414dd 100644 --- a/src/com/sucy/skill/gui/map/SkillDetailMenu.java +++ b/src/main/java/com/sucy/skill/gui/map/SkillDetailMenu.java @@ -1,236 +1,236 @@ -/** - * SkillAPI - * com.sucy.skill.gui.map.SkillDetailMenu - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.gui.map; - -import com.rit.sucy.gui.*; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.player.PlayerSkill; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.List; - -public class SkillDetailMenu extends MapMenu -{ - private SkillAPI api; - - public SkillDetailMenu(SkillAPI api) - { - this.api = api; - } - - private int getButton(Player player) - { - return getSelection(player) & 0xff; - } - - private int getPage(Player player) - { - return (getSelection(player) >> 8) & 0xff; - } - - private int getPages(Player player) - { - return getSelection(player) >> 16; - } - - private void setButton(Player player, int button) - { - setSelection(player, button, getPage(player), getPages(player)); - } - - private void setPage(Player player, int page) - { - setSelection(player, getButton(player), page, getPages(player)); - } - - private void setPages(Player player, int pages) - { - setSelection(player, getButton(player), getPage(player), pages); - } - - private void setSelection(Player player, int button, int page, int pages) - { - setSelection(player, button | (page << 8) | (pages << 16)); - } - - @Override - public void onLeft(Player player) - { - int button = getButton(player); - - button = Math.max(0, button - 1); - boolean down = SkillAPI.getSettings().isAllowDowngrade(); - if (button == 2 && !down) button--; - - setButton(player, button); - } - - @Override - public void onRight(Player player) - { - int button = getButton(player); - int page = getPage(player); - - button = Math.min(3, button + 1); - boolean down = SkillAPI.getSettings().isAllowDowngrade(); - if (button == 2 && !down) button++; - - setButton(player, button); - } - - @Override - public void onUp(Player player) - { - SkillAPI.getPlayerData(player).upgradeSkill(SkillListMenu.getSkill(player).getData()); - } - - @Override - public void onDown(Player player) - { - SkillAPI.getPlayerData(player).downgradeSkill(SkillListMenu.getSkill(player).getData()); - } - - @Override - public void onSelect(Player player) - { - int button = getButton(player); - int page = getPage(player); - - // Back button - if (button == 0) - { - MapMenuManager.sendBack(player); - } - - // Upgrade button - else if (button == 1) - { - SkillAPI.getPlayerData(player).upgradeSkill(SkillListMenu.getSkill(player).getData()); - } - - // Downgrade button - else if (button == 2) - { - SkillAPI.getPlayerData(player).downgradeSkill(SkillListMenu.getSkill(player).getData()); - } - - // More info button - else - { - page = (page + 1) % getPages(player); - setPage(player, page); - setup(player); - } - } - - private static final String BACKGROUND = "background"; - private static final String DETAIL = "detail"; - private static final String BACK_ON = "back1"; - private static final String UP_ON = "up1"; - private static final String DOWN_ON = "down1"; - private static final String MORE_ON = "more1"; - private static final String BACK_OFF = "back0"; - private static final String UP_OFF = "up0"; - private static final String DOWN_OFF = "down0"; - private static final String MORE_OFF = "more0"; - - @Override - public void setup(Player player) - { - MapScheme scheme = MapScheme.get(api, SkillAPI.getPlayerData(player).getScheme()); - MapScene scene = getScene(player); - int page = getPage(player); - - scene.add(BACKGROUND, new MapObject(scheme.getImage(Menu.BACKGROUND), 0, 0)); - - // Get text to draw - PlayerSkill skill = SkillListMenu.getSkill(player); - ItemStack icon = skill.getData().getIndicator(skill, true); - List lore = icon.getItemMeta().getLore(); - lore.add(0, icon.getItemMeta().getDisplayName()); - - // Find page details - MapFont font = scheme.getFont(Menu.DETAIL); - int linesPerPage = 90 / (font.getFont().getSize() + 3); - int pages = (lore.size() + linesPerPage - 1) / linesPerPage; - - // Add the text - int y = font.getFont().getSize() + 5; - int start = linesPerPage * page; - for (int i = start; i < start + linesPerPage && i < lore.size(); i++) - { - String line = lore.get(i); - scene.add(DETAIL + i, new MapObject(new MapString(font, scheme.getColor(Menu.FONT), line), 7, y)); - y += font.getFont().getSize() + 3; - } - - // Get position for upgrade arrow - boolean down = SkillAPI.getSettings().isAllowDowngrade(); - int x; - if (down) x = 42; - else x = 56; - - // Add buttons - - scene.add(BACK_ON, new MapObject(scheme.getImage(Menu.BACK_1), 6, 95)); - scene.add(BACK_OFF, new MapObject(scheme.getImage(Menu.BACK_0), 6, 95)); - - scene.add(UP_ON, new MapObject(scheme.getImage(Menu.UP_1), x, 95)); - scene.add(UP_OFF, new MapObject(scheme.getImage(Menu.UP_0), x, 95)); - - scene.add(DOWN_ON, new MapObject(scheme.getImage(Menu.DOWN_1), 68, 95)); - scene.add(DOWN_OFF, new MapObject(scheme.getImage(Menu.DOWN_0), 68, 95)); - - scene.add(MORE_ON, new MapObject(scheme.getImage(Menu.MORE_1), 90, 95)); - scene.add(MORE_OFF, new MapObject(scheme.getImage(Menu.MORE_0), 90, 95)); - - setPages(player, pages); - } - - @Override - public void render(MapBuffer mapBuffer, Player player) - { - int button = getButton(player); - MapScene scene = getScene(player); - - // Draw buttons - scene.get(BACK_ON).setVisible(button == 0); - scene.get(BACK_OFF).setVisible(button != 0); - - scene.get(UP_ON).setVisible(button == 1); - scene.get(UP_OFF).setVisible(button != 1); - - scene.get(DOWN_ON).setVisible(button == 2); - scene.get(DOWN_OFF).setVisible(button != 2); - - scene.get(MORE_ON).setVisible(button == 3); - scene.get(MORE_OFF).setVisible(button != 3); - - scene.apply(mapBuffer); - } -} +/** + * SkillAPI + * com.sucy.skill.gui.map.SkillDetailMenu + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.gui.map; + +import com.rit.sucy.gui.*; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.player.PlayerSkill; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class SkillDetailMenu extends MapMenu +{ + private SkillAPI api; + + public SkillDetailMenu(SkillAPI api) + { + this.api = api; + } + + private int getButton(Player player) + { + return getSelection(player) & 0xff; + } + + private int getPage(Player player) + { + return (getSelection(player) >> 8) & 0xff; + } + + private int getPages(Player player) + { + return getSelection(player) >> 16; + } + + private void setButton(Player player, int button) + { + setSelection(player, button, getPage(player), getPages(player)); + } + + private void setPage(Player player, int page) + { + setSelection(player, getButton(player), page, getPages(player)); + } + + private void setPages(Player player, int pages) + { + setSelection(player, getButton(player), getPage(player), pages); + } + + private void setSelection(Player player, int button, int page, int pages) + { + setSelection(player, button | (page << 8) | (pages << 16)); + } + + @Override + public void onLeft(Player player) + { + int button = getButton(player); + + button = Math.max(0, button - 1); + boolean down = SkillAPI.getSettings().isAllowDowngrade(); + if (button == 2 && !down) button--; + + setButton(player, button); + } + + @Override + public void onRight(Player player) + { + int button = getButton(player); + int page = getPage(player); + + button = Math.min(3, button + 1); + boolean down = SkillAPI.getSettings().isAllowDowngrade(); + if (button == 2 && !down) button++; + + setButton(player, button); + } + + @Override + public void onUp(Player player) + { + SkillAPI.getPlayerData(player).upgradeSkill(SkillListMenu.getSkill(player).getData(), true); + } + + @Override + public void onDown(Player player) + { + SkillAPI.getPlayerData(player).downgradeSkill(SkillListMenu.getSkill(player).getData()); + } + + @Override + public void onSelect(Player player) + { + int button = getButton(player); + int page = getPage(player); + + // Back button + if (button == 0) + { + MapMenuManager.sendBack(player); + } + + // Upgrade button + else if (button == 1) + { + SkillAPI.getPlayerData(player).upgradeSkill(SkillListMenu.getSkill(player).getData(), true); + } + + // Downgrade button + else if (button == 2) + { + SkillAPI.getPlayerData(player).downgradeSkill(SkillListMenu.getSkill(player).getData()); + } + + // More info button + else + { + page = (page + 1) % getPages(player); + setPage(player, page); + setup(player); + } + } + + private static final String BACKGROUND = "background"; + private static final String DETAIL = "detail"; + private static final String BACK_ON = "back1"; + private static final String UP_ON = "up1"; + private static final String DOWN_ON = "down1"; + private static final String MORE_ON = "more1"; + private static final String BACK_OFF = "back0"; + private static final String UP_OFF = "up0"; + private static final String DOWN_OFF = "down0"; + private static final String MORE_OFF = "more0"; + + @Override + public void setup(Player player) + { + MapScheme scheme = MapScheme.get(api, SkillAPI.getPlayerData(player).getScheme()); + MapScene scene = getScene(player); + int page = getPage(player); + + scene.add(BACKGROUND, new MapObject(scheme.getImage(Menu.BACKGROUND), 0, 0)); + + // Get text to draw + PlayerSkill skill = SkillListMenu.getSkill(player); + ItemStack icon = skill.getData().getIndicator(skill, true); + List lore = icon.getItemMeta().getLore(); + lore.add(0, icon.getItemMeta().getDisplayName()); + + // Find page details + MapFont font = scheme.getFont(Menu.DETAIL); + int linesPerPage = 90 / (font.getFont().getSize() + 3); + int pages = (lore.size() + linesPerPage - 1) / linesPerPage; + + // Add the text + int y = font.getFont().getSize() + 5; + int start = linesPerPage * page; + for (int i = start; i < start + linesPerPage && i < lore.size(); i++) + { + String line = lore.get(i); + scene.add(DETAIL + i, new MapObject(new MapString(font, scheme.getColor(Menu.FONT), line), 7, y)); + y += font.getFont().getSize() + 3; + } + + // Get position for upgrade arrow + boolean down = SkillAPI.getSettings().isAllowDowngrade(); + int x; + if (down) x = 42; + else x = 56; + + // Add buttons + + scene.add(BACK_ON, new MapObject(scheme.getImage(Menu.BACK_1), 6, 95)); + scene.add(BACK_OFF, new MapObject(scheme.getImage(Menu.BACK_0), 6, 95)); + + scene.add(UP_ON, new MapObject(scheme.getImage(Menu.UP_1), x, 95)); + scene.add(UP_OFF, new MapObject(scheme.getImage(Menu.UP_0), x, 95)); + + scene.add(DOWN_ON, new MapObject(scheme.getImage(Menu.DOWN_1), 68, 95)); + scene.add(DOWN_OFF, new MapObject(scheme.getImage(Menu.DOWN_0), 68, 95)); + + scene.add(MORE_ON, new MapObject(scheme.getImage(Menu.MORE_1), 90, 95)); + scene.add(MORE_OFF, new MapObject(scheme.getImage(Menu.MORE_0), 90, 95)); + + setPages(player, pages); + } + + @Override + public void render(MapBuffer mapBuffer, Player player) + { + int button = getButton(player); + MapScene scene = getScene(player); + + // Draw buttons + scene.get(BACK_ON).setVisible(button == 0); + scene.get(BACK_OFF).setVisible(button != 0); + + scene.get(UP_ON).setVisible(button == 1); + scene.get(UP_OFF).setVisible(button != 1); + + scene.get(DOWN_ON).setVisible(button == 2); + scene.get(DOWN_OFF).setVisible(button != 2); + + scene.get(MORE_ON).setVisible(button == 3); + scene.get(MORE_OFF).setVisible(button != 3); + + scene.apply(mapBuffer); + } +} diff --git a/src/com/sucy/skill/gui/map/SkillListMenu.java b/src/main/java/com/sucy/skill/gui/map/SkillListMenu.java similarity index 100% rename from src/com/sucy/skill/gui/map/SkillListMenu.java rename to src/main/java/com/sucy/skill/gui/map/SkillListMenu.java diff --git a/src/com/sucy/skill/gui/tool/GUIData.java b/src/main/java/com/sucy/skill/gui/tool/GUIData.java similarity index 97% rename from src/com/sucy/skill/gui/tool/GUIData.java rename to src/main/java/com/sucy/skill/gui/tool/GUIData.java index 87cf37b3..9ac24727 100644 --- a/src/com/sucy/skill/gui/tool/GUIData.java +++ b/src/main/java/com/sucy/skill/gui/tool/GUIData.java @@ -27,6 +27,7 @@ package com.sucy.skill.gui.tool; import com.rit.sucy.config.parse.DataSection; +import com.sucy.skill.SkillAPI; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.tree.basic.InventoryTree; import org.bukkit.Bukkit; @@ -78,7 +79,7 @@ public class GUIData public void show(GUIHolder handler, PlayerData player, String title, HashMap data) { - Inventory inv = Bukkit.getServer().createInventory(handler, rows * 9, title); + Inventory inv = Bukkit.createInventory(handler, rows * 9, title); ItemStack[] contents = pageMap.get(0).instance(player, data); if (pages > 1) GUITool.addPageButtons(contents); diff --git a/src/com/sucy/skill/gui/tool/GUIHolder.java b/src/main/java/com/sucy/skill/gui/tool/GUIHolder.java similarity index 99% rename from src/com/sucy/skill/gui/tool/GUIHolder.java rename to src/main/java/com/sucy/skill/gui/tool/GUIHolder.java index 3606d292..f476377c 100644 --- a/src/com/sucy/skill/gui/tool/GUIHolder.java +++ b/src/main/java/com/sucy/skill/gui/tool/GUIHolder.java @@ -86,7 +86,6 @@ public void handleDrag(InventoryDragEvent event) event.setCancelled(true); } - @SuppressWarnings("unchecked") public void handleClick(InventoryClickEvent event) { event.setCancelled(true); diff --git a/src/com/sucy/skill/gui/tool/GUIPage.java b/src/main/java/com/sucy/skill/gui/tool/GUIPage.java similarity index 100% rename from src/com/sucy/skill/gui/tool/GUIPage.java rename to src/main/java/com/sucy/skill/gui/tool/GUIPage.java diff --git a/src/com/sucy/skill/gui/tool/GUITool.java b/src/main/java/com/sucy/skill/gui/tool/GUITool.java similarity index 100% rename from src/com/sucy/skill/gui/tool/GUITool.java rename to src/main/java/com/sucy/skill/gui/tool/GUITool.java diff --git a/src/com/sucy/skill/gui/tool/GUIType.java b/src/main/java/com/sucy/skill/gui/tool/GUIType.java similarity index 100% rename from src/com/sucy/skill/gui/tool/GUIType.java rename to src/main/java/com/sucy/skill/gui/tool/GUIType.java diff --git a/src/com/sucy/skill/gui/tool/IconHolder.java b/src/main/java/com/sucy/skill/gui/tool/IconHolder.java similarity index 100% rename from src/com/sucy/skill/gui/tool/IconHolder.java rename to src/main/java/com/sucy/skill/gui/tool/IconHolder.java diff --git a/src/com/sucy/skill/gui/tool/InventoryData.java b/src/main/java/com/sucy/skill/gui/tool/InventoryData.java similarity index 100% rename from src/com/sucy/skill/gui/tool/InventoryData.java rename to src/main/java/com/sucy/skill/gui/tool/InventoryData.java diff --git a/src/com/sucy/skill/gui/tool/ToolMenu.java b/src/main/java/com/sucy/skill/gui/tool/ToolMenu.java similarity index 100% rename from src/com/sucy/skill/gui/tool/ToolMenu.java rename to src/main/java/com/sucy/skill/gui/tool/ToolMenu.java diff --git a/src/com/sucy/skill/hook/BungeeHook.java b/src/main/java/com/sucy/skill/hook/BungeeHook.java similarity index 83% rename from src/com/sucy/skill/hook/BungeeHook.java rename to src/main/java/com/sucy/skill/hook/BungeeHook.java index 761cf753..8cf7b487 100644 --- a/src/com/sucy/skill/hook/BungeeHook.java +++ b/src/main/java/com/sucy/skill/hook/BungeeHook.java @@ -38,8 +38,7 @@ * Handles getting the server kick event over to the * quit event functions to save player data */ -public class BungeeHook implements Listener -{ +public class BungeeHook implements Listener { /** * Initializes the hook into Bungee * @@ -49,15 +48,4 @@ public static void init(SkillAPI api) { api.getServer().getPluginManager().registerEvents(new BungeeHook(), api); } - - @EventHandler - public void onKick(ServerKickEvent event) - { - MainListener.unload(VersionManager.getPlayer(event.getPlayer().getName())); - } - - @EventHandler - public void serverConnect(ServerConnectEvent event) { - MainListener.unload(VersionManager.getPlayer(event.getPlayer().getName())); - } } diff --git a/src/com/sucy/skill/hook/CitizensHook.java b/src/main/java/com/sucy/skill/hook/CitizensHook.java similarity index 76% rename from src/com/sucy/skill/hook/CitizensHook.java rename to src/main/java/com/sucy/skill/hook/CitizensHook.java index f99691d5..e9647fcd 100644 --- a/src/com/sucy/skill/hook/CitizensHook.java +++ b/src/main/java/com/sucy/skill/hook/CitizensHook.java @@ -7,6 +7,6 @@ */ public class CitizensHook { public static boolean isNPC(Entity entity) { - return entity.getClass().getName().equals("PlayerNPC"); + return entity.getClass().getName().contains("PlayerNPC"); } } diff --git a/src/com/sucy/skill/hook/DisguiseHook.java b/src/main/java/com/sucy/skill/hook/DisguiseHook.java similarity index 100% rename from src/com/sucy/skill/hook/DisguiseHook.java rename to src/main/java/com/sucy/skill/hook/DisguiseHook.java diff --git a/src/com/sucy/skill/hook/MythicMobsHook.java b/src/main/java/com/sucy/skill/hook/MythicMobsHook.java similarity index 60% rename from src/com/sucy/skill/hook/MythicMobsHook.java rename to src/main/java/com/sucy/skill/hook/MythicMobsHook.java index 87a6dccf..090ea25f 100644 --- a/src/com/sucy/skill/hook/MythicMobsHook.java +++ b/src/main/java/com/sucy/skill/hook/MythicMobsHook.java @@ -1,7 +1,7 @@ package com.sucy.skill.hook; -import io.lumine.xikage.mythicmobs.MythicMobs; import org.bukkit.entity.LivingEntity; +import io.lumine.mythic.bukkit.MythicBukkit; /** * SkillAPI © 2017 @@ -11,14 +11,14 @@ public class MythicMobsHook { public static void taunt(final LivingEntity target, final LivingEntity source, final double amount) { if (amount > 0) { - MythicMobs.inst().getAPIHelper().addThreat(target, source, amount); + MythicBukkit.inst().getAPIHelper().addThreat(target, source, amount); } else if (amount < 0) { - MythicMobs.inst().getAPIHelper().reduceThreat(target, source, -amount); + MythicBukkit.inst().getAPIHelper().reduceThreat(target, source, -amount); } } public static boolean isMonster(final LivingEntity target) { - return MythicMobs.inst().getAPIHelper().isMythicMob(target); + return MythicBukkit.inst().getAPIHelper().isMythicMob(target); } } diff --git a/src/com/sucy/skill/hook/NoCheatHook.java b/src/main/java/com/sucy/skill/hook/NoCheatHook.java similarity index 100% rename from src/com/sucy/skill/hook/NoCheatHook.java rename to src/main/java/com/sucy/skill/hook/NoCheatHook.java diff --git a/src/main/java/com/sucy/skill/hook/PlaceholderAPIHook.java b/src/main/java/com/sucy/skill/hook/PlaceholderAPIHook.java new file mode 100644 index 00000000..275a80cc --- /dev/null +++ b/src/main/java/com/sucy/skill/hook/PlaceholderAPIHook.java @@ -0,0 +1,176 @@ +package com.sucy.skill.hook; + +import com.google.common.collect.ImmutableMap; +import com.rit.sucy.mobs.MobManager; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.player.PlayerClass; +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.dynamic.DynamicSkill; +import me.clip.placeholderapi.PlaceholderAPI; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Map; +import java.util.function.BiFunction; + +/** + * SkillAPI © 2018 + * com.sucy.skill.hook.PlaceholderAPIHook + */ +public class PlaceholderAPIHook { + + public static String format(final String message, final Player player) { + return PlaceholderAPI.setPlaceholders(player, message); + } + + public static void registerPlaceholder(SkillAPI skillAPI) { + new SkillAPIPlaceholders(skillAPI).register(); + } + + public static class SkillAPIPlaceholders extends PlaceholderExpansion { + SkillAPI skillAPI; + + public SkillAPIPlaceholders(SkillAPI skillAPI) { + this.skillAPI = skillAPI; + } + + @NotNull + public String getIdentifier() { + return "sapi"; + } + + @Override + public boolean persist(){ + return true; + } + + @Override + public boolean canRegister(){ + return true; + } + + @NotNull + public String getAuthor() { + return "Eniripsa96"; + } + + @NotNull + public String getVersion() { + return "1.0"; + } + + private final Map> PLACEHOLDERS = getMap(); + + @Override + public String onPlaceholderRequest(Player player, String id) { + if (!skillAPI.isLoaded(player)) return "Loading..."; + String key, param; + int paramIndex = id.indexOf(':') + 1; + + if (paramIndex > 0) { + param = id.substring(paramIndex); + key = id.substring(0, paramIndex); + } else { + key = id; + param = null; + } + + BiFunction placeholder = PLACEHOLDERS.get(key); + return (placeholder == null) ? "" : placeholder.apply(SkillAPI.getPlayerData(player), param); + } + + + private String getExp(PlayerClass playerClass) { + return Integer.toString((int) ((playerClass == null) ? 0.0D : playerClass.getExp())); + } + + + private String getTotalExp(PlayerClass playerClass) { + return Integer.toString((int) ((playerClass == null) ? 0.0D : playerClass.getTotalExp())); + } + + + private String getRequiredExp(PlayerClass playerClass) { + return Integer.toString((playerClass == null) ? SkillAPI.getSettings().getRequiredExp(1) : playerClass.getRequiredExp()); + } + + + private String getRemainingExp(PlayerClass playerClass) { + return Integer.toString((int) ((playerClass == null) ? SkillAPI.getSettings().getRequiredExp(1) : (playerClass.getRequiredExp() - playerClass.getExp()))); + } + + + private String getLevel(PlayerClass playerClass) { + return Integer.toString((playerClass == null) ? 0 : playerClass.getLevel()); + } + + + private String getSkillPoints(PlayerClass playerClass) { + return Integer.toString((playerClass == null) ? 0 : playerClass.getPoints()); + } + + + private String getPrefix(PlayerClass playerClass) { + return (playerClass == null) ? "" : playerClass.getData().getPrefix(); + } + + + private String getManaName(PlayerClass playerClass) { + return (playerClass == null) ? "" : playerClass.getData().getManaName(); + } + + + private String format(Object value) { + if (value instanceof Player) + return ((Player) value).getName(); + if (value instanceof LivingEntity) { + if (((LivingEntity) value).isCustomNameVisible()) { + return ((LivingEntity) value).getCustomName(); + } + return MobManager.getName((LivingEntity) value); + } + + if (value instanceof Collection) { + return ((Collection) value).stream() + .map(this::format) + .reduce((a, b) -> a + ", " + b) + .toString(); + } + return value.toString(); + } + + private Map> getMap() { + ImmutableMap.Builder> builder = ImmutableMap.builder(); + builder.put("attrib_points", (p, u) -> Integer.toString(p.getAttributePoints())) + .put("attrib_spent:", (p, attribute) -> Integer.toString(p.getInvestedAttribute(attribute))) + .put("attrib_total:", (p, attribute) -> Integer.toString(p.getAttribute(attribute))) + .put("combo", (p, u) -> p.getComboData().getCurrentComboString()) + .put("exp", (p, u) -> getExp(p.getMainClass())) + .put("exp:", (p, group) -> getExp(p.getClass(group))) + .put("exp_total", (p, u) -> getTotalExp(p.getMainClass())) + .put("exp_total:", (p, group) -> getTotalExp(p.getClass(group))) + .put("exp_left", (p, u) -> getRemainingExp(p.getMainClass())) + .put("exp_left:", (p, group) -> getRemainingExp(p.getClass(group))) + .put("exp_req", (p, u) -> getRequiredExp(p.getMainClass())) + .put("exp_req:", (p, group) -> getRequiredExp(p.getClass(group))) + .put("level", (p, u) -> getLevel(p.getMainClass())) + .put("level:", (p, group) -> getLevel(p.getClass(group))) + .put("mana", (p, u) -> Integer.toString((int) p.getMana())) + .put("mana_max", (p, u) -> Integer.toString((int) p.getMaxMana())) + .put("mana_name", (p, u) -> getManaName(p.getMainClass())) + .put("mana_name:", (p, group) -> getManaName(p.getClass(group))) + .put("prefix", (p, u) -> getPrefix(p.getMainClass())) + .put("prefix:", (p, className) -> getPrefix(p.getClass(className))) + .put("skill_level:", (p, skill) -> Integer.toString(p.getSkill(skill).getLevel())) + .put("skill_points", (p, u) -> getSkillPoints(p.getMainClass())) + .put("skill_points:", (p, group) -> getSkillPoints(p.getClass(group))) + .put("value:", (p, key) -> format(DynamicSkill.getCastData(p.getPlayer()))).build(); + return builder.build(); + } + + } + +} diff --git a/src/com/sucy/skill/hook/PluginChecker.java b/src/main/java/com/sucy/skill/hook/PluginChecker.java similarity index 100% rename from src/com/sucy/skill/hook/PluginChecker.java rename to src/main/java/com/sucy/skill/hook/PluginChecker.java diff --git a/src/com/sucy/skill/hook/RPGInventoryHook.java b/src/main/java/com/sucy/skill/hook/RPGInventoryHook.java similarity index 100% rename from src/com/sucy/skill/hook/RPGInventoryHook.java rename to src/main/java/com/sucy/skill/hook/RPGInventoryHook.java diff --git a/src/com/sucy/skill/hook/VaultHook.java b/src/main/java/com/sucy/skill/hook/VaultHook.java similarity index 100% rename from src/com/sucy/skill/hook/VaultHook.java rename to src/main/java/com/sucy/skill/hook/VaultHook.java diff --git a/src/com/sucy/skill/hook/WorldGuardHook.java b/src/main/java/com/sucy/skill/hook/WorldGuardHook.java similarity index 90% rename from src/com/sucy/skill/hook/WorldGuardHook.java rename to src/main/java/com/sucy/skill/hook/WorldGuardHook.java index a6e368f4..a16971dd 100644 --- a/src/com/sucy/skill/hook/WorldGuardHook.java +++ b/src/main/java/com/sucy/skill/hook/WorldGuardHook.java @@ -1,8 +1,8 @@ package com.sucy.skill.hook; import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.managers.RegionManager; @@ -46,8 +46,8 @@ public static List getRegionIds(final Location loc) { } } - private static Vector asVector(final Location location) { - return new Vector(location.getX(), location.getY(), location.getZ()); + private static BlockVector3 asVector(final Location location) { + return BlockVector3.at(location.getX(), location.getY(), location.getZ()); } private static Method getRegionMethod() throws Exception { diff --git a/src/com/sucy/skill/language/ErrorNodes.java b/src/main/java/com/sucy/skill/language/ErrorNodes.java similarity index 100% rename from src/com/sucy/skill/language/ErrorNodes.java rename to src/main/java/com/sucy/skill/language/ErrorNodes.java diff --git a/src/com/sucy/skill/language/GUINodes.java b/src/main/java/com/sucy/skill/language/GUINodes.java similarity index 100% rename from src/com/sucy/skill/language/GUINodes.java rename to src/main/java/com/sucy/skill/language/GUINodes.java diff --git a/src/com/sucy/skill/language/NotificationNodes.java b/src/main/java/com/sucy/skill/language/NotificationNodes.java similarity index 100% rename from src/com/sucy/skill/language/NotificationNodes.java rename to src/main/java/com/sucy/skill/language/NotificationNodes.java diff --git a/src/com/sucy/skill/language/RPGFilter.java b/src/main/java/com/sucy/skill/language/RPGFilter.java similarity index 97% rename from src/com/sucy/skill/language/RPGFilter.java rename to src/main/java/com/sucy/skill/language/RPGFilter.java index c8d380eb..938ef939 100644 --- a/src/com/sucy/skill/language/RPGFilter.java +++ b/src/main/java/com/sucy/skill/language/RPGFilter.java @@ -43,6 +43,7 @@ public class RPGFilter public static final CustomFilter COOLDOWN = new CustomFilter("{cooldown}", ""); public static final CustomFilter SKILL = new CustomFilter("{skill}", ""); public static final CustomFilter MANA = new CustomFilter("{mana}", ""); + public static final CustomFilter MANANAME = new CustomFilter("{mananame}", ""); public static final CustomFilter COST = new CustomFilter("{cost}", ""); public static final CustomFilter MISSING = new CustomFilter("{missing}", ""); public static final CustomFilter DURATION = new CustomFilter("{duration}", ""); diff --git a/src/com/sucy/skill/language/SkillNodes.java b/src/main/java/com/sucy/skill/language/SkillNodes.java similarity index 100% rename from src/com/sucy/skill/language/SkillNodes.java rename to src/main/java/com/sucy/skill/language/SkillNodes.java diff --git a/src/com/sucy/skill/listener/AddonListener.java b/src/main/java/com/sucy/skill/listener/AddonListener.java similarity index 100% rename from src/com/sucy/skill/listener/AddonListener.java rename to src/main/java/com/sucy/skill/listener/AddonListener.java diff --git a/src/com/sucy/skill/listener/AttributeListener.java b/src/main/java/com/sucy/skill/listener/AttributeListener.java similarity index 93% rename from src/com/sucy/skill/listener/AttributeListener.java rename to src/main/java/com/sucy/skill/listener/AttributeListener.java index 82d3a4fa..dff6cab2 100644 --- a/src/com/sucy/skill/listener/AttributeListener.java +++ b/src/main/java/com/sucy/skill/listener/AttributeListener.java @@ -31,6 +31,7 @@ import com.sucy.skill.api.enums.ExpSource; import com.sucy.skill.api.enums.ManaSource; import com.sucy.skill.api.event.*; +import com.sucy.skill.api.player.PlayerClass; import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.hook.CitizensHook; import com.sucy.skill.log.LogType; @@ -179,11 +180,15 @@ public void onInvest(PlayerUpAttributeEvent event) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onManaRegen(PlayerManaGainEvent event) { - // Bonus to regen from attributes - if (event.getSource() == ManaSource.REGEN) - { - double newAmount = event.getPlayerData().scaleStat(AttributeManager.MANA_REGEN, event.getAmount()); + if (event.getAmount() > 0) { + double newAmount = event.getPlayerData().scaleStat(AttributeManager.MANA_GAIN, event.getAmount()); Logger.log(LogType.MANA, 3, "Attributes scaled mana gain to " + newAmount); + + if (event.getSource() == ManaSource.REGEN) + { + newAmount = event.getPlayerData().scaleStat(AttributeManager.MANA_REGEN, newAmount); + Logger.log(LogType.MANA, 3, "Attributes scaled mana regen to " + newAmount); + } event.setAmount(newAmount); } } @@ -347,8 +352,20 @@ public static void updatePlayer(PlayerData data) double change = updateStat(data, AttributeManager.HEALTH, player.getMaxHealth(), 0, Double.MAX_VALUE); data.addMaxHealth(change); - change = updateStat(data, AttributeManager.MANA, data.getMaxMana(), 0, Double.MAX_VALUE); - data.addMaxMana(change); + PlayerClass pc = data.getMainClass(); + // Class uses mana + if (pc != null && pc.getData().getManaName().endsWith("MP")) { + change = updateStat(data, AttributeManager.MANA, data.getMaxMana(), 0, Double.MAX_VALUE); + data.addMaxMana(change); + } + // Class does not use mana, remove any bonus mana it has + else { + String key = player.getName() + ":" + AttributeManager.MANA; + if (BONUSES.containsKey(key)) { + double amt = -BONUSES.remove(key); + data.addMaxMana(amt); + } + } change = updateStat(data, AttributeManager.MOVE_SPEED, player.getWalkSpeed(), -2, 1); player.setWalkSpeed(player.getWalkSpeed() + (float) change); @@ -407,7 +424,7 @@ private static double updateStat(PlayerData data, String key, double value, doub String mapKey = player.getName() + ":" + key; double current = BONUSES.containsKey(mapKey) ? BONUSES.remove(mapKey) : 0; double updated = Math.max(min, Math.min(max, data.scaleStat(key, value - current) - value + current)); - BONUSES.put(mapKey, updated); + BONUSES.put(mapKey, updated >= 0 ? updated : 0); return updated - current; } return 0; diff --git a/src/com/sucy/skill/listener/BarListener.java b/src/main/java/com/sucy/skill/listener/BarListener.java similarity index 92% rename from src/com/sucy/skill/listener/BarListener.java rename to src/main/java/com/sucy/skill/listener/BarListener.java index 3e353f91..47f68b8e 100644 --- a/src/com/sucy/skill/listener/BarListener.java +++ b/src/main/java/com/sucy/skill/listener/BarListener.java @@ -27,6 +27,7 @@ package com.sucy.skill.listener; import com.rit.sucy.gui.MapData; +import org.bukkit.Bukkit; import com.rit.sucy.gui.MapMenu; import com.rit.sucy.gui.MapMenuManager; import com.rit.sucy.version.VersionManager; @@ -57,6 +58,9 @@ import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import java.util.HashSet; import java.util.UUID; @@ -68,13 +72,14 @@ public class BarListener extends SkillAPIListener { private final HashSet ignored = new HashSet(); + private final Plugin sapi = Bukkit.getPluginManager().getPlugin("SkillAPI"); @Override public void init() { MainListener.registerJoin(this::onJoin); MainListener.registerClear(this::handleClear); - for (Player player : VersionManager.getOnlinePlayers()) + for (Player player : Bukkit.getOnlinePlayers()) { if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { PlayerData data = SkillAPI.getPlayerData(player); @@ -107,12 +112,20 @@ private void cleanup(Player player) { */ public void onJoin(final Player player) { - if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { - final PlayerData data = SkillAPI.getPlayerData(player); - if (data.hasClass()) { - data.getSkillBar().setup(player); - } - } + SkillAPI skillAPI = (SkillAPI) sapi; + if(!skillAPI.isSkillBarsEnabled()) + return; + BukkitRunnable enableBar = new BukkitRunnable() { + public void run() { + if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { + final PlayerData data = SkillAPI.getPlayerData(player); + if (data.hasClass()) { + data.getSkillBar().setup(player); + } + } + } + }; + enableBar.runTaskLater(sapi, 100L); } /** @@ -327,8 +340,6 @@ public void onChangeWorld(PlayerChangedWorldEvent event) boolean enabled = SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld()); if (data.hasClass() && data.getSkillBar().isSetup() && enabled) ignored.add(event.getPlayer().getUniqueId()); - if (enabled) - data.getSkillBar().setup(event.getPlayer()); else data.getSkillBar().clear(event.getPlayer()); } @@ -388,12 +399,12 @@ public void onChangeMode(PlayerGameModeChangeEvent event) if (event.getNewGameMode() == GameMode.CREATIVE && data.hasClass()) data.getSkillBar().clear(event.getPlayer()); - // Setup on leaving creative mode - else if (event.getPlayer().getGameMode() == GameMode.CREATIVE && data.hasClass()) - { - final Player player = event.getPlayer(); - SkillAPI.schedule(() -> SkillAPI.getPlayerData(player).getSkillBar().setup(player), 0); - } + // Setup on leaving creative mode (Removed by Neoblade298) +// else if (event.getPlayer().getGameMode() == GameMode.CREATIVE && data.hasClass()) +// { +// final Player player = event.getPlayer(); +// SkillAPI.schedule(() -> SkillAPI.getPlayerData(player).getSkillBar().setup(player), 0); +// } } private void handleClear(final Player player) { diff --git a/src/com/sucy/skill/listener/BindListener.java b/src/main/java/com/sucy/skill/listener/BindListener.java similarity index 94% rename from src/com/sucy/skill/listener/BindListener.java rename to src/main/java/com/sucy/skill/listener/BindListener.java index 728e6b57..ade1339f 100644 --- a/src/com/sucy/skill/listener/BindListener.java +++ b/src/main/java/com/sucy/skill/listener/BindListener.java @@ -1,73 +1,73 @@ -/** - * SkillAPI - * com.sucy.skill.listener.BindListener - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.listener; - -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.event.KeyPressEvent; -import com.sucy.skill.api.player.PlayerData; -import com.sucy.skill.api.player.PlayerSkill; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; - -/** - * A listener that handles casting skills through binds. This shouldn't be - * use by other plugins as it is handled by the API. - */ -public class BindListener extends SkillAPIListener { - /** - * Handles interact events to check when a player right clicks with - * a bound item to cast a skill. - * - * @param event event details - */ - @EventHandler(priority = EventPriority.HIGHEST) - public void onInteract(KeyPressEvent event) { - Player player = event.getPlayer(); - if (!SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { - return; - } - - PlayerData data = SkillAPI.getPlayerData(player); - Material heldItem = player.getItemInHand().getType(); - - // Must be right clicking with an item - if (event.getKey() != KeyPressEvent.Key.RIGHT || heldItem == null) { - return; - } - - // Must have a valid item - final PlayerSkill skill = data.getBoundSkill(heldItem); - if (skill == null || !SkillAPI.isSkillRegistered(skill.getData().getName())) { - return; - } - - // Cast the skill - data.cast(skill); - } -} +/** + * SkillAPI + * com.sucy.skill.listener.BindListener + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.listener; + +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.event.KeyPressEvent; +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.api.player.PlayerSkill; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; + +/** + * A listener that handles casting skills through binds. This shouldn't be + * use by other plugins as it is handled by the API. + */ +public class BindListener extends SkillAPIListener { + /** + * Handles interact events to check when a player right clicks with + * a bound item to cast a skill. + * + * @param event event details + */ + @EventHandler(priority = EventPriority.HIGHEST) + public void onInteract(KeyPressEvent event) { + Player player = event.getPlayer(); + if (!SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { + return; + } + + PlayerData data = SkillAPI.getPlayerData(player); + Material heldItem = player.getInventory().getItemInMainHand().getType(); + + // Must be right clicking with an item + if (event.getKey() != KeyPressEvent.Key.RIGHT || heldItem == null) { + return; + } + + // Must have a valid item + final PlayerSkill skill = data.getBoundSkill(heldItem); + if (skill == null || !SkillAPI.isSkillRegistered(skill.getData().getName())) { + return; + } + + // Cast the skill + data.cast(skill); + } +} diff --git a/src/com/sucy/skill/listener/BuffListener.java b/src/main/java/com/sucy/skill/listener/BuffListener.java similarity index 79% rename from src/com/sucy/skill/listener/BuffListener.java rename to src/main/java/com/sucy/skill/listener/BuffListener.java index c406f7b3..e46d5a41 100644 --- a/src/com/sucy/skill/listener/BuffListener.java +++ b/src/main/java/com/sucy/skill/listener/BuffListener.java @@ -1,10 +1,14 @@ package com.sucy.skill.listener; +import com.sucy.skill.SkillAPI; import com.sucy.skill.api.event.PhysicalDamageEvent; import com.sucy.skill.api.event.SkillDamageEvent; import com.sucy.skill.api.event.SkillHealEvent; import com.sucy.skill.api.util.BuffManager; import com.sucy.skill.api.util.BuffType; +import com.sucy.skill.manager.AttributeManager; + +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -20,10 +24,12 @@ public class BuffListener extends SkillAPIListener { public void onPhysical(final PhysicalDamageEvent event) { final double withDamageBuffs = BuffManager.apply( event.getDamager(), + event.getTarget(), BuffType.DAMAGE, event.getDamage()); final double withDefenseBuffs = BuffManager.apply( event.getTarget(), + event.getDamager(), BuffType.DEFENSE, withDamageBuffs); @@ -38,10 +44,12 @@ public void onSkill(final SkillDamageEvent event) { if (event.getClassification().equalsIgnoreCase(PHYSICAL)) { final double withDamageBuffs = BuffManager.apply( event.getDamager(), + event.getTarget(), BuffType.DAMAGE, event.getDamage()); final double withDefenseBuffs = BuffManager.apply( event.getTarget(), + event.getDamager(), BuffType.DEFENSE, withDamageBuffs); @@ -52,11 +60,13 @@ public void onSkill(final SkillDamageEvent event) { } else { final double withDamageBuffs = BuffManager.apply( event.getDamager(), + event.getTarget(), BuffType.SKILL_DAMAGE, event.getClassification(), event.getDamage()); final double withDefenseBuffs = BuffManager.apply( event.getTarget(), + event.getDamager(), BuffType.SKILL_DEFENSE, event.getClassification(), withDamageBuffs); @@ -70,13 +80,18 @@ public void onSkill(final SkillDamageEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onHeal(final SkillHealEvent event) { - final double withBuff = BuffManager.apply( + double withBuff = BuffManager.apply( + event.getHealer(), event.getTarget(), BuffType.HEALING, event.getAmount()); + double withAttr = withBuff; + if (event.getTarget() instanceof Player) { + withAttr = SkillAPI.getPlayerData((Player) event.getTarget()).scaleStat(AttributeManager.HEALING_RECEIVED, withAttr); + } - event.setAmount(withBuff); - if (withBuff <= 0) { + event.setAmount(withAttr); + if (withAttr <= 0) { event.setCancelled(true); } } diff --git a/src/com/sucy/skill/listener/CastCombatListener.java b/src/main/java/com/sucy/skill/listener/CastCombatListener.java similarity index 100% rename from src/com/sucy/skill/listener/CastCombatListener.java rename to src/main/java/com/sucy/skill/listener/CastCombatListener.java diff --git a/src/com/sucy/skill/listener/CastItemListener.java b/src/main/java/com/sucy/skill/listener/CastItemListener.java similarity index 100% rename from src/com/sucy/skill/listener/CastItemListener.java rename to src/main/java/com/sucy/skill/listener/CastItemListener.java diff --git a/src/com/sucy/skill/listener/CastListener.java b/src/main/java/com/sucy/skill/listener/CastListener.java similarity index 100% rename from src/com/sucy/skill/listener/CastListener.java rename to src/main/java/com/sucy/skill/listener/CastListener.java diff --git a/src/com/sucy/skill/listener/CastOffhandListener.java b/src/main/java/com/sucy/skill/listener/CastOffhandListener.java similarity index 100% rename from src/com/sucy/skill/listener/CastOffhandListener.java rename to src/main/java/com/sucy/skill/listener/CastOffhandListener.java diff --git a/src/com/sucy/skill/listener/ClickListener.java b/src/main/java/com/sucy/skill/listener/ClickListener.java similarity index 90% rename from src/com/sucy/skill/listener/ClickListener.java rename to src/main/java/com/sucy/skill/listener/ClickListener.java index d704560d..3bd847f8 100644 --- a/src/com/sucy/skill/listener/ClickListener.java +++ b/src/main/java/com/sucy/skill/listener/ClickListener.java @@ -1,64 +1,58 @@ -/** - * SkillAPI - * com.sucy.skill.listener.ClickListener - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.listener; - -import com.sucy.skill.api.event.KeyPressEvent; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; - -/** - * Handles transferring click actions by the player to - * combos that cast skills. - */ -public class ClickListener extends SkillAPIListener { - - /** - * Registers clicks as they happen - * - * @param event event details - */ - @EventHandler - public void onClick(PlayerInteractEvent event) { - // Left clicks - if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) { - Bukkit.getServer().getPluginManager().callEvent(new KeyPressEvent(event.getPlayer(), KeyPressEvent.Key.LEFT)); - } - - // Right clicks - else if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR) { - Bukkit.getServer().getPluginManager().callEvent(new KeyPressEvent(event.getPlayer(), KeyPressEvent.Key.RIGHT)); - } - } - - @EventHandler - public void onDrop(final PlayerDropItemEvent event) { - Bukkit.getServer().getPluginManager().callEvent(new KeyPressEvent(event.getPlayer(), KeyPressEvent.Key.Q)); - } -} +/** + * SkillAPI + * com.sucy.skill.listener.ClickListener + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.listener; + +import com.sucy.skill.api.event.KeyPressEvent; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +/** + * Handles transferring click actions by the player to + * combos that cast skills. + */ +public class ClickListener extends SkillAPIListener { + + /** + * Registers clicks as they happen + * + * @param event event details + */ + @EventHandler + public void onClick(PlayerInteractEvent event) { + // Left clicks + if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) { + Bukkit.getServer().getPluginManager().callEvent(new KeyPressEvent(event.getPlayer(), KeyPressEvent.Key.LEFT)); + } + + // Right clicks + else if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR) { + Bukkit.getServer().getPluginManager().callEvent(new KeyPressEvent(event.getPlayer(), KeyPressEvent.Key.RIGHT)); + } + } +} diff --git a/src/com/sucy/skill/listener/ComboListener.java b/src/main/java/com/sucy/skill/listener/ComboListener.java similarity index 100% rename from src/com/sucy/skill/listener/ComboListener.java rename to src/main/java/com/sucy/skill/listener/ComboListener.java diff --git a/src/com/sucy/skill/listener/DeathListener.java b/src/main/java/com/sucy/skill/listener/DeathListener.java similarity index 100% rename from src/com/sucy/skill/listener/DeathListener.java rename to src/main/java/com/sucy/skill/listener/DeathListener.java diff --git a/src/com/sucy/skill/listener/ExperienceListener.java b/src/main/java/com/sucy/skill/listener/ExperienceListener.java similarity index 100% rename from src/com/sucy/skill/listener/ExperienceListener.java rename to src/main/java/com/sucy/skill/listener/ExperienceListener.java diff --git a/src/com/sucy/skill/listener/ItemListener.java b/src/main/java/com/sucy/skill/listener/ItemListener.java similarity index 86% rename from src/com/sucy/skill/listener/ItemListener.java rename to src/main/java/com/sucy/skill/listener/ItemListener.java index 9665f154..7c284748 100644 --- a/src/com/sucy/skill/listener/ItemListener.java +++ b/src/main/java/com/sucy/skill/listener/ItemListener.java @@ -1,266 +1,288 @@ -/** - * SkillAPI - * com.sucy.skill.listener.ItemListener - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Steven Sucy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software") to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.sucy.skill.listener; - -import com.google.common.collect.ImmutableSet; -import com.rit.sucy.config.FilterType; -import com.rit.sucy.version.VersionManager; -import com.sucy.skill.SkillAPI; -import com.sucy.skill.api.event.PlayerClassChangeEvent; -import com.sucy.skill.data.PlayerEquips; -import com.sucy.skill.language.ErrorNodes; -import org.bukkit.Material; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemBreakEvent; -import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.Set; - -/** - * Listener that handles weapon item lore requirements - */ -public class ItemListener extends SkillAPIListener -{ - @Override - public void init() { - MainListener.registerJoin(this::onJoin); - } - - /** - * Removes weapon bonuses when dropped - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onDrop(PlayerDropItemEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.getPlayerData(event.getPlayer()).getEquips().clearWeapon(); - } - - /** - * Updates player equips when an item breaks - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBreak(PlayerItemBreakEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.schedule(new UpdateTask(event.getPlayer(), false), 1); - } - - /** - * Updates equipment data on join - */ - public void onJoin(final Player player) - { - if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - SkillAPI.getPlayerData(player).getEquips().update(player); - } - - @EventHandler - public void onProfess(PlayerClassChangeEvent event) { - final Player player = event.getPlayerData().getPlayer(); - if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) - event.getPlayerData().getEquips().update(player); - } - - /** - * Updates weapon on pickup - * Clear attribute buff data on quit - * - * @param event event details - */ - @EventHandler - public void onPickup(PlayerPickupItemEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.schedule(new UpdateTask(event.getPlayer(), false), 1); - } - - /** - * Update equips on world change into an active world - * - * @param event event details - */ - @EventHandler(priority = EventPriority.MONITOR) - public void onWorld(PlayerChangedWorldEvent event) - { - if (!SkillAPI.getSettings().isWorldEnabled(event.getFrom()) - && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.getPlayerData(event.getPlayer()).getEquips().update(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onHeld(PlayerItemHeldEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.schedule(new UpdateTask(event.getPlayer(), true), 1); - } - - @EventHandler - public void onClose(InventoryCloseEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) - SkillAPI.schedule(new UpdateTask((Player) event.getPlayer(), false), 1); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onInteract(PlayerInteractEvent event) - { - if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld()) - && (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) - && event.getPlayer().getItemInHand() != null - && ARMOR_TYPES.contains(event.getPlayer().getItemInHand().getType())) - { - SkillAPI.schedule(new UpdateTask(event.getPlayer(), false), 1); - } - } - - /** - * Cancels left clicks on disabled items - * - * @param event event details - */ - @EventHandler(priority = EventPriority.LOWEST) - public void onAttack(EntityDamageByEntityEvent event) - { - if (!SkillAPI.getSettings().isWorldEnabled(event.getEntity().getWorld())) - return; - - if (event.getDamager() instanceof Player) - { - Player player = (Player) event.getDamager(); - if (!SkillAPI.getPlayerData(player).getEquips().canHit()) - { - SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, player, FilterType.COLOR); - event.setCancelled(true); - } - } - if (event.getEntity() instanceof Player && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) - { - Player player = (Player) event.getEntity(); - final boolean blocking = event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0; - if (blocking && !SkillAPI.getPlayerData(player).getEquips().canBlock()) - { - SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); - event.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, 0); - } - } - } - - /** - * Cancels firing a bow with a disabled weapon - * - * @param event event details - */ - @EventHandler(priority = EventPriority.LOWEST) - public void onShoot(EntityShootBowEvent event) - { - if (event.getEntity() instanceof Player) - { - final PlayerEquips equips = SkillAPI.getPlayerData((Player) event.getEntity()).getEquips(); - if (isMainhand(event.getBow(), event.getEntity())) - { - if (!equips.canHit()) { - SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); - event.setCancelled(true); - } - } - else if (!equips.canBlock()) { - SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); - event.setCancelled(true); - } - } - } - - private boolean isMainhand(final ItemStack bow, final LivingEntity entity) { - return !VersionManager.isVersionAtLeast(VersionManager.V1_9_0) - || bow == entity.getEquipment().getItemInMainHand(); - } - - public static final Set ARMOR_TYPES = getArmorMaterials(); - - private static Set getArmorMaterials() { - final Set armorSuffixes = ImmutableSet.of("BOOTS", "LEGGINGS", "CHESTPLATE", "HELMET"); - final ImmutableSet.Builder builder = ImmutableSet.builder(); - for (Material material : Material.values()) { - final int index = material.name().lastIndexOf('_') + 1; - final String suffix = material.name().substring(index); - if (armorSuffixes.contains(suffix)) { - builder.add(material); - } - } - return builder.build(); - } - - /** - * Handles updating equipped armor - */ - private class UpdateTask extends BukkitRunnable - { - private Player player; - - private boolean weaponOnly; - - /** - * @param player player reference - */ - UpdateTask(Player player, boolean weaponOnly) - { - this.player = player; - this.weaponOnly = weaponOnly; - } - - /** - * Applies the update - */ - @Override - public void run() - { - if (weaponOnly) - SkillAPI.getPlayerData(player).getEquips().updateWeapon(player.getInventory()); - else - SkillAPI.getPlayerData(player).getEquips().update(player); - } - } -} +/** + * SkillAPI + * com.sucy.skill.listener.ItemListener + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.listener; + +import com.google.common.collect.ImmutableSet; +import com.rit.sucy.config.FilterType; +import com.rit.sucy.version.VersionManager; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.event.PlayerClassChangeEvent; +import com.sucy.skill.data.PlayerEquips; +import com.sucy.skill.language.ErrorNodes; +import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemBreakEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Set; + +/** + * Listener that handles weapon item lore requirements + */ +public class ItemListener extends SkillAPIListener +{ + private static SkillAPI singleton; + + public ItemListener(SkillAPI api) { + singleton = api; + } + + @Override + public void init() { + MainListener.registerJoin(this::onJoin); + } + + /** + * Removes weapon bonuses when dropped + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDrop(PlayerDropItemEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.getPlayerData(event.getPlayer()).getEquips().clearWeapon(); + } + + /** + * Updates player equips when an item breaks + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBreak(PlayerItemBreakEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.schedule(new UpdateTask(event.getPlayer(), false, false), 1); + } + + /** + * Updates equipment data on join + */ + public void onJoin(final Player player) + { + if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) + SkillAPI.getPlayerData(player).getEquips().update(player); + } + + @EventHandler + public void onProfess(PlayerClassChangeEvent event) { + final Player player = event.getPlayerData().getPlayer(); + if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) + event.getPlayerData().getEquips().update(player); + } + + /** + * Updates weapon on pickup + * Clear attribute buff data on quit + * + * @param event event details + */ + @EventHandler + public void onPickup(PlayerPickupItemEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.schedule(new UpdateTask(event.getPlayer(), false, false), 1); + } + + /** + * Update equips on world change into an active world + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR) + public void onWorld(PlayerChangedWorldEvent event) + { + if (!SkillAPI.getSettings().isWorldEnabled(event.getFrom()) + && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.getPlayerData(event.getPlayer()).getEquips().update(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onHeld(PlayerItemHeldEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.schedule(new UpdateTask(event.getPlayer(), true, false), 1); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onOffhandSwap(PlayerSwapHandItemsEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.schedule(new UpdateTask(event.getPlayer(), true, true), 1); + } + + @EventHandler + public void onClose(InventoryCloseEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + SkillAPI.schedule(new UpdateTask((Player) event.getPlayer(), false, false), 1); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInteract(PlayerInteractEvent event) + { + if (SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld()) + && (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) + && event.getPlayer().getItemInHand() != null + && ARMOR_TYPES.contains(event.getPlayer().getItemInHand().getType())) + { + SkillAPI.schedule(new UpdateTask(event.getPlayer(), false, false), 1); + } + } + + /** + * Cancels left clicks on disabled items + * + * @param event event details + */ + @EventHandler(priority = EventPriority.LOWEST) + public void onAttack(EntityDamageByEntityEvent event) + { + if (!SkillAPI.getSettings().isWorldEnabled(event.getEntity().getWorld())) + return; + + if (event.getDamager() instanceof Player) + { + Player player = (Player) event.getDamager(); + if (!SkillAPI.getPlayerData(player).getEquips().canHit()) + { + SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, player, FilterType.COLOR); + event.setCancelled(true); + } + } + if (event.getEntity() instanceof Player && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) + { + Player player = (Player) event.getEntity(); + final boolean blocking = event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0; + if (blocking && !SkillAPI.getPlayerData(player).getEquips().canBlock()) + { + SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); + event.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, 0); + } + } + } + + /** + * Cancels firing a bow with a disabled weapon + * + * @param event event details + */ + @EventHandler(priority = EventPriority.LOWEST) + public void onShoot(EntityShootBowEvent event) + { + if (event.getEntity() instanceof Player) + { + final PlayerEquips equips = SkillAPI.getPlayerData((Player) event.getEntity()).getEquips(); + if (isMainhand(event.getBow(), event.getEntity())) + { + if (!equips.canHit()) { + SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); + event.setCancelled(true); + } + } + else if (!equips.canBlock()) { + SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); + event.setCancelled(true); + } + } + } + + private boolean isMainhand(final ItemStack bow, final LivingEntity entity) { + return !VersionManager.isVersionAtLeast(VersionManager.V1_9_0) + || bow == entity.getEquipment().getItemInMainHand(); + } + + public static final Set ARMOR_TYPES = getArmorMaterials(); + + private static Set getArmorMaterials() { + final Set armorSuffixes = ImmutableSet.of("BOOTS", "LEGGINGS", "CHESTPLATE", "HELMET"); + final ImmutableSet.Builder builder = ImmutableSet.builder(); + for (Material material : Material.values()) { + final int index = material.name().lastIndexOf('_') + 1; + final String suffix = material.name().substring(index); + if (armorSuffixes.contains(suffix)) { + builder.add(material); + } + } + return builder.build(); + } + + /** + * Handles updating equipped armor + */ + private class UpdateTask extends BukkitRunnable + { + private Player player; + + private boolean weaponOnly; + private boolean offhandSwap; + + /** + * @param player player reference + */ + UpdateTask(Player player, boolean weaponOnly, boolean offhandSwap) + { + this.player = player; + this.weaponOnly = weaponOnly; + this.offhandSwap = offhandSwap; + } + + /** + * Applies the update + */ + @Override + public void run() + { + String id = player.getUniqueId().toString(); + if (singleton.players.containsKey(id)) { + if (offhandSwap) SkillAPI.getPlayerData(player).getEquips().swapOffhand(); + else { + if (weaponOnly) + SkillAPI.getPlayerData(player).getEquips().updateWeapon(player.getInventory()); + else + SkillAPI.getPlayerData(player).getEquips().update(player); + } + } + } + } +} diff --git a/src/com/sucy/skill/listener/KillListener.java b/src/main/java/com/sucy/skill/listener/KillListener.java similarity index 98% rename from src/com/sucy/skill/listener/KillListener.java rename to src/main/java/com/sucy/skill/listener/KillListener.java index 0f68fb37..f7898e3f 100644 --- a/src/com/sucy/skill/listener/KillListener.java +++ b/src/main/java/com/sucy/skill/listener/KillListener.java @@ -63,7 +63,7 @@ public KillListener() { try { - Class living = Reflection.getNMSClass("EntityLiving"); + Class living = Reflection.getNMSClass("net.minecraft.world.entity.EntityLiving"); handle = Reflection.getCraftClass("entity.CraftEntity").getDeclaredMethod("getHandle"); killer = living.getDeclaredField("killer"); damageTime = living.getDeclaredField("lastDamageByPlayerTime"); diff --git a/src/com/sucy/skill/listener/LingeringPotionListener.java b/src/main/java/com/sucy/skill/listener/LingeringPotionListener.java similarity index 100% rename from src/com/sucy/skill/listener/LingeringPotionListener.java rename to src/main/java/com/sucy/skill/listener/LingeringPotionListener.java diff --git a/src/com/sucy/skill/listener/ListenerUtil.java b/src/main/java/com/sucy/skill/listener/ListenerUtil.java similarity index 100% rename from src/com/sucy/skill/listener/ListenerUtil.java rename to src/main/java/com/sucy/skill/listener/ListenerUtil.java diff --git a/src/main/java/com/sucy/skill/listener/MainListener.java b/src/main/java/com/sucy/skill/listener/MainListener.java new file mode 100644 index 00000000..9f40068e --- /dev/null +++ b/src/main/java/com/sucy/skill/listener/MainListener.java @@ -0,0 +1,557 @@ +/** + * SkillAPI + * com.sucy.skill.listener.MainListener + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.listener; + +import com.rit.sucy.version.VersionManager; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.enums.ExpSource; +import com.sucy.skill.api.event.PhysicalDamageEvent; +import com.sucy.skill.api.event.PlayerAttributeLoadEvent; +import com.sucy.skill.api.event.PlayerAttributeUnloadEvent; +import com.sucy.skill.api.event.PlayerClassChangeEvent; +import com.sucy.skill.api.event.PlayerLevelUpEvent; +import com.sucy.skill.api.event.PlayerLoadCompleteEvent; +import com.sucy.skill.api.event.PlayerPreLoadCompleteEvent; +import com.sucy.skill.api.player.PlayerAccounts; +import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.api.util.BuffManager; +import com.sucy.skill.api.util.Combat; +import com.sucy.skill.api.util.FlagManager; +import com.sucy.skill.data.Permissions; +import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.dynamic.mechanic.ImmunityMechanic; +import com.sucy.skill.hook.CitizensHook; +import com.sucy.skill.log.Logger; +import com.sucy.skill.manager.ClassBoardManager; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.entity.*; +import org.bukkit.event.inventory.FurnaceExtractEvent; +import org.bukkit.event.player.*; +import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.*; +import java.util.function.Consumer; + +/** + * The main listener for SkillAPI that handles general mechanics such as + * loading/clearing data, controlling experience gains, and enabling/disabling + * passive abilities. + */ +public class MainListener extends SkillAPIListener { + private static final List> JOIN_HANDLERS = new ArrayList<>(); + private static final List> CLEAR_HANDLERS = new ArrayList<>(); + private static SkillAPI singleton; + + public static final Map loadingTask = new HashMap<>(); // Holds the preload and load tasks + public static final HashSet preloadingPlayers = new HashSet(); + public static final HashSet loadingPlayers = new HashSet(); + + public MainListener(SkillAPI skillAPI) { + singleton = skillAPI; + } + + public static void registerJoin(final Consumer joinHandler) { + JOIN_HANDLERS.add(joinHandler); + } + + public static void registerClear(final Consumer joinHandler) { + CLEAR_HANDLERS.add(joinHandler); + } + + @Override + public void cleanup() { + JOIN_HANDLERS.clear(); + } + + /** + * Loads player data asynchronously when a player tries to log in + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onLogin(AsyncPlayerPreLoginEvent event) { + OfflinePlayer player = Bukkit.getOfflinePlayer(event.getUniqueId()); + loadingPlayers.add(event.getUniqueId()); + preloadingPlayers.add(event.getUniqueId()); + + int delay = SkillAPI.getSettings().getSqlDelay(); + + if (SkillAPI.getSettings().isUseSql() && delay > 0) { + SkillAPI.initFakeData(player); + final BukkitTask task = new BukkitRunnable() { + int count = 0; + public void run() { + count++; + if (count > 1) { + Logger.bug("[SkillAPI] Preload task for " + player.getName() + " is on attempt " + count); + if (count > 4) { + Logger.bug("[SkillAPI] Cancelling preload task for " + player.getName() + ", count = " + count); + loadingTask.remove(event.getUniqueId()); + preloadingPlayers.remove(event.getUniqueId()); + this.cancel(); + } + } + + PlayerAccounts data = SkillAPI.loadPlayerDataSQL(player); + if (data != null && data.getActiveData() != null) { + Logger.log("[SkillAPI] Successfully preloaded " + event.getUniqueId() + " after " + count + " attempts"); + loadingTask.remove(event.getUniqueId()); + preloadingPlayers.remove(event.getUniqueId()); + this.cancel(); + new BukkitRunnable() { + public void run() { + Bukkit.getPluginManager().callEvent(new PlayerPreLoadCompleteEvent(event.getUniqueId())); + } + }.runTask(singleton); + } + } + }.runTaskTimerAsynchronously(singleton, delay, 20L); + loadingTask.put(player.getUniqueId(), task); + } + } + + /** + * Starts passives and applies class data when a player logs in. + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onJoin(final PlayerJoinEvent event) { + final Player player = event.getPlayer(); + if (player.hasMetadata("NPC")) + return; + + loadPlayer(player); + } + + @EventHandler + public void onPreLoadComplete(PlayerPreLoadCompleteEvent e) { + Player p = Bukkit.getPlayer(e.getUniqueId()); + + // Preload complete before player logged on + if (p == null) return; + + loadPlayer(p); + } + + private void loadPlayer(Player p) { + UUID uuid = p.getUniqueId(); + + if (loadingTask.containsKey(uuid)) return; + + BukkitTask load = new BukkitRunnable() { + int count = 1; + + @SuppressWarnings("unused") + public void run() { + if (p == null) { + loadingTask.remove(uuid); + loadingPlayers.remove(uuid); + this.cancel(); + } + if (count > 5) { + loadingTask.remove(uuid); + loadingPlayers.remove(uuid); + Logger.bug("[SkillAPI] Load task for " + p.getName() + " failed"); + this.cancel(); + } + try { + init(p); + loadingTask.remove(uuid); + loadingPlayers.remove(uuid); + SkillAPI.getPlayerData(p).getEquips().update(p); + Logger.log("[SkillAPI] Successfully loaded " + p.getName() + " on attempt " + count); + Bukkit.getPluginManager().callEvent(new PlayerLoadCompleteEvent(p)); + Bukkit.getPluginManager().callEvent(new PlayerAttributeLoadEvent(p)); + this.cancel(); + } + catch (Exception e) { + count++; + } + } + }.runTask(singleton); + loadingTask.put(uuid, load); + } + + private void init(final Player player) { + final PlayerData data = SkillAPI.getPlayerData(player); + OfflinePlayer op = Bukkit.getOfflinePlayer(player.getUniqueId()); + SkillAPI.getPlayerAccountData(player).setPlayer(op); + data.setPlayer(op); + data.init(player); + data.autoLevel(); + // data.updateScoreboard(); + JOIN_HANDLERS.forEach(handler -> handler.accept(player)); + } + + /** + * Saves player data when they log out and stops passives + * + * @param event event details + */ + @EventHandler(priority = EventPriority.LOWEST) // Lowest = We called it first before MPDB + public void onQuit(PlayerQuitEvent event) { + unload(event.getPlayer()); + } + + /** + * Unloads a player's data from the server + * + * @param player player to unload + */ + public static void unload(Player player) { + if (player.hasMetadata("NPC")) + return; + + boolean skipSaving = false; + UUID uuid = player.getUniqueId(); + if (loadingTask.containsKey(uuid)) { + loadingTask.remove(player.getUniqueId()).cancel(); + skipSaving = true; + } + loadingPlayers.remove(uuid); + + PlayerData data = SkillAPI.getPlayerData(player); + if (SkillAPI.getSettings().isWorldEnabled(player.getWorld())) { + data.record(player); + data.stopPassives(player); + // We remove the SkillBar + data.getSkillBar().clear(player); + } + + FlagManager.clearFlags(player); + BuffManager.clearData(player); + Combat.clearData(player); + DynamicSkill.clearCastData(player); + + player.setDisplayName(player.getName()); + if (VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { + player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(20); + } + else { + player.setMaxHealth(20); + } + player.setWalkSpeed(0.2f); + SkillAPI.unloadPlayerData(player, skipSaving); + } + + /** + * Stops passives an applies death penalties when a player dies. + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR) + public void onDeath(PlayerDeathEvent event) { + FlagManager.clearFlags(event.getEntity()); + BuffManager.clearData(event.getEntity()); + DynamicSkill.clearCastData(event.getEntity()); + + if (event.getEntity().hasMetadata("NPC")) + return; + + PlayerData data = SkillAPI.getPlayerData(event.getEntity()); + if (data.hasClass() && SkillAPI.getSettings().isWorldEnabled(event.getEntity().getWorld())) { + data.stopPassives(event.getEntity()); + if (!SkillAPI.getSettings().shouldIgnoreExpLoss(event.getEntity().getWorld())) { + data.loseExp(); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDeath(final EntityDeathEvent event) { + DynamicSkill.clearCastData(event.getEntity()); + FlagManager.clearFlags(event.getEntity()); + BuffManager.clearData(event.getEntity()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onUnload(final ChunkUnloadEvent event) { + for (final Entity entity : event.getChunk().getEntities()) { + if (entity instanceof LivingEntity && !(entity instanceof Player)) { + final LivingEntity livingEntity = (LivingEntity) entity; + DynamicSkill.clearCastData(livingEntity); + FlagManager.clearFlags(livingEntity); + BuffManager.clearData(livingEntity); + } + } + } + + /** + * Handles experience when a block is broken + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBreak(BlockBreakEvent event) { + if (event.getPlayer().hasMetadata("NPC")) + return; + + Player player = event.getPlayer(); + if (SkillAPI.getSettings().isUseOrbs() && player != null + && SkillAPI.getSettings().isWorldEnabled(player.getWorld())) + SkillAPI.getPlayerData(player).giveExp(event.getExpToDrop(), ExpSource.BLOCK_BREAK); + } + + /** + * Handles experience when ore is smelted in a furnace + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onSmelt(FurnaceExtractEvent event) { + Player player = event.getPlayer(); + if (SkillAPI.getSettings().isUseOrbs() && player != null + && SkillAPI.getSettings().isWorldEnabled(player.getWorld())) + SkillAPI.getPlayerData(player).giveExp(event.getExpToDrop(), ExpSource.SMELT); + } + + /** + * Handles experience when a Bottle o' Enchanting breaks + * + * @param event event details + */ + @EventHandler + public void onExpBottleBreak(ExpBottleEvent event) { + if (!(event.getEntity().getShooter() instanceof Player) + || !SkillAPI.getSettings().isWorldEnabled(((Player) event.getEntity().getShooter()).getWorld())) + return; + + Player player = (Player) event.getEntity().getShooter(); + if (CitizensHook.isNPC(player)) + return; + + if (SkillAPI.getSettings().isUseOrbs()) + SkillAPI.getPlayerData(player).giveExp(event.getExperience(), ExpSource.EXP_BOTTLE); + } + + /** + * Prevents experience orbs from modifying the level bar when it is used for + * displaying class level. + * + * @param event event details + */ + @EventHandler(priority = EventPriority.HIGHEST) + public void onExpChange(PlayerExpChangeEvent event) { + // Prevent it from changing the level bar when that is being used to display + // class level + if (!SkillAPI.getSettings().getLevelBar().equalsIgnoreCase("none") + && event.getPlayer().hasPermission(Permissions.EXP) + && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) { + event.setAmount(0); + } + } + + /** + * Handles updating level displays for players + * + * @param event event details + */ + @EventHandler + public void onLevelUp(final PlayerLevelUpEvent event) { + if (SkillAPI.getSettings().isShowClassLevel()) { + // ClassBoardManager.updateLevel(event.getPlayerData()); + } + } + + /** + * Starts passive abilities again after respawning + * + * @param event event details + */ + @EventHandler + public void onRespawn(PlayerRespawnEvent event) { + if (event.getPlayer().hasMetadata("NPC")) + return; + + PlayerData data = SkillAPI.getPlayerData(event.getPlayer()); + if (data.hasClass() && SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) { + data.startPassives(event.getPlayer()); + // data.updateScoreboard(); + } + } + + /** + * Damage type immunities + * + * @param event event details + */ + @EventHandler(ignoreCancelled = true) + public void onDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof LivingEntity + && FlagManager.hasFlag((LivingEntity) event.getEntity(), "immune:" + event.getCause().name())) { + double multiplier = SkillAPI.getMetaDouble(event.getEntity(), ImmunityMechanic.META_KEY); + if (multiplier <= 0) + event.setCancelled(true); + else + event.setDamage(event.getDamage() * multiplier); + } + } + + /** + * Cancels food damaging the player when the bar is being used for GUI features + * instead of normal hunger. + * + * @param event event details + */ + @EventHandler + public void onStarve(EntityDamageEvent event) { + if (event.getCause() == EntityDamageEvent.DamageCause.STARVATION + && !SkillAPI.getSettings().getFoodBar().equalsIgnoreCase("none")) { + event.setCancelled(true); + } + } + + /** + * Cancels saturation heal + * + * @param event event details + */ + @EventHandler + public void onSaturationHeal(EntityRegainHealthEvent event) { + String foodBar = SkillAPI.getSettings().getFoodBar().toLowerCase(); + if ((foodBar.equals("mana") || foodBar.equals("exp")) + && event.getRegainReason() == EntityRegainHealthEvent.RegainReason.SATIATED) { + event.setCancelled(true); + } + } + + /** + * Launches physical damage events to differentiate skill damage from physical + * damage + * + * @param event event details + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPhysicalDamage(EntityDamageByEntityEvent event) { + if (Skill.isSkillDamage() || event.getCause() == EntityDamageEvent.DamageCause.CUSTOM + || event.getCause() == EntityDamageEvent.DamageCause.THORNS + || !(event.getEntity() instanceof LivingEntity) || event.getDamage() <= 0) { + return; + } + + PhysicalDamageEvent e = new PhysicalDamageEvent(ListenerUtil.getDamager(event), + (LivingEntity) event.getEntity(), event.getDamage(), event.getDamager() instanceof Projectile); + Bukkit.getPluginManager().callEvent(e); + event.setDamage(e.getDamage()); + event.setCancelled(e.isCancelled()); + } + + /** + * Handles marking players as in combat + * + * @param event event details + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onCombat(EntityDamageByEntityEvent event) { + if (event.getCause() == EntityDamageEvent.DamageCause.CUSTOM || !(event.getEntity() instanceof LivingEntity)) + return; + + if (event.getEntity() instanceof Player) { + Combat.applyCombat((Player) event.getEntity()); + } + + LivingEntity damager = ListenerUtil.getDamager(event); + if (damager instanceof Player) { + Combat.applyCombat((Player) damager); + } + } + + /** + * Applies or removes SkillAPI features from a player upon switching worlds + * + * @param event event details + */ + @EventHandler + public void onWorldChange(PlayerChangedWorldEvent event) { + if (event.getPlayer().hasMetadata("NPC")) + return; + + boolean oldEnabled = SkillAPI.getSettings().isWorldEnabled(event.getFrom()); + boolean newEnabled = SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld()); + if (oldEnabled && !newEnabled) { + PlayerData data = SkillAPI.getPlayerData(event.getPlayer()); + data.clearBonuses(); + data.stopPassives(event.getPlayer()); + event.getPlayer().setMaxHealth(SkillAPI.getSettings().getDefaultHealth()); + event.getPlayer().setHealth(SkillAPI.getSettings().getDefaultHealth()); + if (!SkillAPI.getSettings().getLevelBar().equalsIgnoreCase("none")) { + event.getPlayer().setLevel(0); + event.getPlayer().setExp(0); + } + if (!SkillAPI.getSettings().getFoodBar().equalsIgnoreCase("none")) { + event.getPlayer().setFoodLevel(20); + } + } + else if (!oldEnabled && newEnabled) { + init(event.getPlayer()); + Bukkit.getPluginManager().callEvent(new PlayerAttributeLoadEvent(event.getPlayer())); + } + } + + @EventHandler(ignoreCancelled = true) + public void onCommand(final PlayerCommandPreprocessEvent event) { + if (!SkillAPI.getSettings().isWorldEnabled(event.getPlayer().getWorld())) + return; + + if (event.getMessage().equals("/clear")) { + handleClear(event.getPlayer()); + } + else if (event.getMessage().startsWith("/clear ")) { + handleClear(Bukkit.getPlayer(event.getMessage().substring(7))); + } + } + + @EventHandler + public void onCommand(final ServerCommandEvent event) { + if (event.getCommand().startsWith("clear ")) { + handleClear(Bukkit.getPlayer(event.getCommand().substring(6))); + } + } + + private void handleClear(final Player player) { + if (player != null) { + SkillAPI.schedule(() -> { + final PlayerData data = SkillAPI.getPlayerData(player); + data.getEquips().update(player); + + CLEAR_HANDLERS.forEach(handler -> handler.accept(player)); + }, 1); + } + } +} \ No newline at end of file diff --git a/src/com/sucy/skill/listener/MechanicListener.java b/src/main/java/com/sucy/skill/listener/MechanicListener.java similarity index 100% rename from src/com/sucy/skill/listener/MechanicListener.java rename to src/main/java/com/sucy/skill/listener/MechanicListener.java diff --git a/src/main/java/com/sucy/skill/listener/NeoComboListener.java b/src/main/java/com/sucy/skill/listener/NeoComboListener.java new file mode 100644 index 00000000..1ae8d542 --- /dev/null +++ b/src/main/java/com/sucy/skill/listener/NeoComboListener.java @@ -0,0 +1,130 @@ +/** + * SkillAPI + * com.sucy.skill.listener.KillListener + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.listener; + +import com.sucy.skill.api.classes.Click; +import com.sucy.skill.api.event.KeyPressEvent.Key; +import com.sucy.skill.api.event.NeoClickComboEvent; +import com.sucy.skill.api.event.NeoClickComboEvent.ClickType; +import com.sucy.skill.api.event.PhysicalDamageEvent; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityInteractEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; + +import java.util.HashMap; +import java.util.UUID; + +/** + * Tracks who kills what entities and awards experience accordingly + */ +public class NeoComboListener extends SkillAPIListener +{ + private HashMap lastClick; + + public NeoComboListener() + { + lastClick = new HashMap(); + } + + @EventHandler + public void onHitEntity(PhysicalDamageEvent e) { + // Left clicks + if (e.getDamager() instanceof Player && !e.isProjectile()) { + Player p = (Player) e.getDamager(); + UUID uuid = p.getUniqueId(); + Key key = Key.LEFT; + if (lastClick.containsKey(uuid)) { + Click prev = lastClick.get(uuid); + if (prev.getTime() + 500 > System.currentTimeMillis()) { + if (prev.getKey().equals(Key.RIGHT)) { + Bukkit.getPluginManager().callEvent(new NeoClickComboEvent(p, ClickType.RL)); + } + } + } + lastClick.put(uuid, new Click(System.currentTimeMillis(), key)); + } + } + + @EventHandler(ignoreCancelled=false) + public void onClick(PlayerInteractEvent e) { + // Left clicks + Key key = null; + if (e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.LEFT_CLICK_BLOCK) { + key = Key.LEFT; + } + + // Right clicks + else if (e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.RIGHT_CLICK_AIR) { + key = Key.RIGHT; + } + + if (key != null) { + UUID uuid = e.getPlayer().getUniqueId(); + if (lastClick.containsKey(uuid)) { + Click prev = lastClick.get(uuid); + if (prev.getTime() + 500 > System.currentTimeMillis()) { + if (prev.getKey().equals(Key.RIGHT) && key.equals(Key.LEFT)) { + Bukkit.getPluginManager().callEvent(new NeoClickComboEvent(e.getPlayer(), ClickType.RL)); + } + else if (prev.getKey().equals(Key.LEFT) && key.equals(Key.RIGHT)) { + Bukkit.getPluginManager().callEvent(new NeoClickComboEvent(e.getPlayer(), ClickType.LR)); + } + } + } + lastClick.put(uuid, new Click(System.currentTimeMillis(), key)); + } + } + + @EventHandler + public void onLeave(PlayerQuitEvent e) { + lastClick.remove(e.getPlayer().getUniqueId()); + } + + @EventHandler + public void onLeave(PlayerKickEvent e) { + lastClick.remove(e.getPlayer().getUniqueId()); + } + + @EventHandler + public void onHotbarSwap(PlayerItemHeldEvent e) { + lastClick.remove(e.getPlayer().getUniqueId()); + } + + @EventHandler + public void onOffhandSwap(PlayerSwapHandItemsEvent e) { + lastClick.remove(e.getPlayer().getUniqueId()); + } +} diff --git a/src/com/sucy/skill/listener/PacketListener.java b/src/main/java/com/sucy/skill/listener/PacketListener.java similarity index 100% rename from src/com/sucy/skill/listener/PacketListener.java rename to src/main/java/com/sucy/skill/listener/PacketListener.java diff --git a/src/com/sucy/skill/listener/SkillAPIListener.java b/src/main/java/com/sucy/skill/listener/SkillAPIListener.java similarity index 100% rename from src/com/sucy/skill/listener/SkillAPIListener.java rename to src/main/java/com/sucy/skill/listener/SkillAPIListener.java diff --git a/src/com/sucy/skill/listener/StatusListener.java b/src/main/java/com/sucy/skill/listener/StatusListener.java similarity index 98% rename from src/com/sucy/skill/listener/StatusListener.java rename to src/main/java/com/sucy/skill/listener/StatusListener.java index b558b68e..191f4bd2 100644 --- a/src/com/sucy/skill/listener/StatusListener.java +++ b/src/main/java/com/sucy/skill/listener/StatusListener.java @@ -111,7 +111,7 @@ public void onMove(PlayerMoveEvent event) { if (((event.getPlayer()).isOnGround() || event.getTo().getY() > event.getFrom().getY()) && check(event, event.getPlayer(), event.getPlayer(), StatusFlag.STUN, StatusFlag.ROOT, StatusFlag.CHANNELING)) { - event.getPlayer().setVelocity(ZERO); + event.setCancelled(true); } } @@ -178,8 +178,7 @@ public void onPhysicalDamage(PhysicalDamageEvent event) { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onDamaged(EntityDamageEvent event) { - if (event.getCause() == EntityDamageEvent.DamageCause.CUSTOM - || !(event.getEntity() instanceof LivingEntity)) + if (!(event.getEntity() instanceof LivingEntity)) return; checkAbsorbAndInvincible((LivingEntity) event.getEntity(), event, event.getDamage()); diff --git a/src/com/sucy/skill/listener/ToolListener.java b/src/main/java/com/sucy/skill/listener/ToolListener.java similarity index 100% rename from src/com/sucy/skill/listener/ToolListener.java rename to src/main/java/com/sucy/skill/listener/ToolListener.java diff --git a/src/com/sucy/skill/log/LogType.java b/src/main/java/com/sucy/skill/log/LogType.java similarity index 100% rename from src/com/sucy/skill/log/LogType.java rename to src/main/java/com/sucy/skill/log/LogType.java diff --git a/src/com/sucy/skill/log/Logger.java b/src/main/java/com/sucy/skill/log/Logger.java similarity index 100% rename from src/com/sucy/skill/log/Logger.java rename to src/main/java/com/sucy/skill/log/Logger.java diff --git a/src/com/sucy/skill/manager/AttributeManager.java b/src/main/java/com/sucy/skill/manager/AttributeManager.java similarity index 97% rename from src/com/sucy/skill/manager/AttributeManager.java rename to src/main/java/com/sucy/skill/manager/AttributeManager.java index a7eec502..b3506043 100644 --- a/src/com/sucy/skill/manager/AttributeManager.java +++ b/src/main/java/com/sucy/skill/manager/AttributeManager.java @@ -55,8 +55,10 @@ public class AttributeManager { // Keys for supported stat modifiers public static final String HEALTH = "health"; + public static final String HEALTH_REGEN = "health-regen"; public static final String MANA = "mana"; public static final String MANA_REGEN = "mana-regen"; + public static final String MANA_GAIN = "mana-gain"; public static final String PHYSICAL_DAMAGE = "physical-damage"; public static final String MELEE_DAMAGE = "melee-damage"; public static final String PROJECTILE_DAMAGE = "projectile-damage"; @@ -73,6 +75,7 @@ public class AttributeManager { public static final String EXPERIENCE = "exp"; public static final String HUNGER = "hunger"; public static final String HUNGER_HEAL = "hunger-heal"; + public static final String HEALING_RECEIVED = "healing-received"; public static final String COOLDOWN = "cooldown"; public static final String KNOCKBACK_RESIST = "knockback-resist"; @@ -321,21 +324,23 @@ public int getMax() { * * @param component component to modify for * @param key key of the value to modify - * @param value base value + * @param base base value * @param amount amount of attribute points * * @return modified value */ - public double modify(EffectComponent component, String key, double value, int amount) { + public double modify(EffectComponent component, String key, double base, int amount) { key = component.getKey() + "-" + key.toLowerCase(); final Map map = dynamicModifiers.get(component.getType()); if (map.containsKey(key)) { AttributeValue[] list = map.get(key); for (AttributeValue attribValue : list) { - if (attribValue.passes(component)) { return attribValue.apply(value, amount); } + if (attribValue.passes(component)) { + return attribValue.apply(base, amount) - base; + } } } - return value; + return 0; } /** diff --git a/src/com/sucy/skill/manager/ClassBoardManager.java b/src/main/java/com/sucy/skill/manager/ClassBoardManager.java similarity index 99% rename from src/com/sucy/skill/manager/ClassBoardManager.java rename to src/main/java/com/sucy/skill/manager/ClassBoardManager.java index 00972af7..c7ebf0bf 100644 --- a/src/com/sucy/skill/manager/ClassBoardManager.java +++ b/src/main/java/com/sucy/skill/manager/ClassBoardManager.java @@ -52,6 +52,7 @@ public class ClassBoardManager * * @deprecated use clearPrefix(VersionPlayer) instead */ + @Deprecated public static void clear(String player) { clear(new VersionPlayer(player)); diff --git a/src/com/sucy/skill/manager/CmdManager.java b/src/main/java/com/sucy/skill/manager/CmdManager.java similarity index 91% rename from src/com/sucy/skill/manager/CmdManager.java rename to src/main/java/com/sucy/skill/manager/CmdManager.java index f06039f9..545c5500 100644 --- a/src/com/sucy/skill/manager/CmdManager.java +++ b/src/main/java/com/sucy/skill/manager/CmdManager.java @@ -26,6 +26,10 @@ */ package com.sucy.skill.manager; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.Command; + import com.rit.sucy.commands.CommandManager; import com.rit.sucy.commands.ConfigurableCommand; import com.rit.sucy.commands.SenderType; @@ -36,7 +40,7 @@ /** * Sets up commands for the plugin */ -public class CmdManager +public class CmdManager implements CommandExecutor { public static ConfigurableCommand PROFESS_COMMAND; @@ -53,6 +57,17 @@ public CmdManager(SkillAPI api) this.api = api; this.initialize(); } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + ConfigurableCommand cmd = CommandManager.getCommand(command.getName()); + if (cmd != null) + { + cmd.execute(sender, args); + return true; + } + return true; + } /** * Initializes commands with MCCore's CommandManager @@ -61,6 +76,7 @@ public void initialize() { ConfigurableCommand root = new ConfigurableCommand(api, "class", SenderType.ANYONE); root.addSubCommands( + new ConfigurableCommand(api, "togglebar", SenderType.ANYONE, new CmdToggleBar(), "Toggle the SkillBar", "", Permissions.FORCE), new ConfigurableCommand(api, "bind", SenderType.PLAYER_ONLY, new CmdBind(), "Binds a skill", "", Permissions.BASIC), new ConfigurableCommand(api, "cast", SenderType.PLAYER_ONLY, new CmdCast(), "Casts a skill", "", Permissions.BASIC), new ConfigurableCommand(api, "changeclass", SenderType.ANYONE, new CmdChangeClass(), "Swaps classes", " ", Permissions.FORCE), @@ -79,7 +95,8 @@ public void initialize() new ConfigurableCommand(api, "reset", SenderType.PLAYER_ONLY, new CmdReset(), "Resets account data", "", Permissions.BASIC), new ConfigurableCommand(api, "skill", SenderType.PLAYER_ONLY, new CmdSkill(), "Shows player skills", "", Permissions.BASIC), new ConfigurableCommand(api, "unbind", SenderType.PLAYER_ONLY, new CmdUnbind(), "Unbinds held item", "", Permissions.BASIC), - new ConfigurableCommand(api, "world", SenderType.PLAYER_ONLY, new CmdWorld(), "Moves to world", "", Permissions.WORLD) + new ConfigurableCommand(api, "world", SenderType.PLAYER_ONLY, new CmdWorld(), "Moves to world", "", Permissions.WORLD), + new ConfigurableCommand(api, "debug", SenderType.ANYONE, new CmdDebug(), "Toggles debug", "", Permissions.RELOAD) ); root.addSubCommands( new ConfigurableCommand(api, "forceaccount", SenderType.CONSOLE_ONLY, new CmdForceAccount(), "Changes player's account", " ", Permissions.FORCE), diff --git a/src/com/sucy/skill/manager/ComboManager.java b/src/main/java/com/sucy/skill/manager/ComboManager.java similarity index 100% rename from src/com/sucy/skill/manager/ComboManager.java rename to src/main/java/com/sucy/skill/manager/ComboManager.java diff --git a/src/com/sucy/skill/manager/RegistrationManager.java b/src/main/java/com/sucy/skill/manager/RegistrationManager.java similarity index 91% rename from src/com/sucy/skill/manager/RegistrationManager.java rename to src/main/java/com/sucy/skill/manager/RegistrationManager.java index aef71534..732b1eee 100644 --- a/src/com/sucy/skill/manager/RegistrationManager.java +++ b/src/main/java/com/sucy/skill/manager/RegistrationManager.java @@ -178,30 +178,7 @@ public void initialize() { if (skillRoot.exists()) { File[] files = skillRoot.listFiles(); if (files != null) { - for (File file : files) { - if (!file.getName().endsWith(".yml")) { continue; } - String name = file.getName().replace(".yml", ""); - try { - CommentedConfig sConfig = new CommentedConfig(api, SKILL_DIR + name); - DynamicSkill skill = new DynamicSkill(name); - skill.load(sConfig.getConfig().getSection(name)); - if (!SkillAPI.isSkillRegistered(skill.getName())) { - api.addDynamicSkill(skill); - skill.registerEvents(api); - sConfig.clear(); - skill.save(sConfig.getConfig().createSection(name)); - skill.save(skillConfig.getConfig().createSection(name)); - sConfig.save(); - Logger.log(LogType.REGISTRATION, 2, "Loaded the dynamic skill: " + name); - } else if (SkillAPI.getSkill(name) instanceof DynamicSkill) { - Logger.log(LogType.REGISTRATION, 3, name + " is already loaded, skipping it"); - } else { - Logger.invalid("Duplicate skill detected: " + name); - } - } catch (Exception ex) { - Logger.invalid("Failed to load skill: " + name + " - " + ex.getMessage()); - } - } + loadSkillsRecursive(files, ""); } } @@ -298,6 +275,35 @@ public void initialize() { Logger.log(LogType.REGISTRATION, 0, " - " + SkillAPI.getSkills().size() + " skills"); Logger.log(LogType.REGISTRATION, 0, " - " + SkillAPI.getClasses().size() + " classes"); } + + public void loadSkillsRecursive(File[] files, String addedPath) { + for (File file : files) { + if (file.isDirectory()) { loadSkillsRecursive(file.listFiles(), addedPath + file.getName() + File.separator); } + if (!file.getName().endsWith(".yml")) { continue; } + String name = file.getName().replace(".yml", ""); + try { + CommentedConfig sConfig = new CommentedConfig(api, SKILL_DIR + addedPath + name); + DynamicSkill skill = new DynamicSkill(name); + skill.load(sConfig.getConfig().getSection(name)); + if (!SkillAPI.isSkillRegistered(skill.getName())) { + api.addDynamicSkill(skill); + skill.registerEvents(api); + sConfig.clear(); + skill.save(sConfig.getConfig().createSection(name)); + skill.save(skillConfig.getConfig().createSection(name)); + sConfig.save(); + Logger.log(LogType.REGISTRATION, 2, "Loaded the dynamic skill: " + name); + } else if (SkillAPI.getSkill(name) instanceof DynamicSkill) { + Logger.log(LogType.REGISTRATION, 3, name + " is already loaded, skipping it"); + } else { + Logger.invalid("Duplicate skill detected: " + name); + } + } catch (Exception ex) { + Logger.invalid("Failed to load skill: " + name + " - " + ex.getMessage()); + ex.printStackTrace(); + } + } + } /** *

    Validates a skill, making sure it is being registered during the diff --git a/src/main/java/com/sucy/skill/manager/ResourceManager.java b/src/main/java/com/sucy/skill/manager/ResourceManager.java new file mode 100644 index 00000000..8a44b754 --- /dev/null +++ b/src/main/java/com/sucy/skill/manager/ResourceManager.java @@ -0,0 +1,84 @@ +/* + SkillAPI + com.sucy.skill.manager.ResourceManager + + The MIT License (MIT) + + Copyright (c) 2014 Steven Sucy + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software") to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.sucy.skill.manager; + +import com.sucy.skill.log.Logger; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Manages embedded resources within the .jar + */ +public class ResourceManager { + public static final String + QUESTS_FOLDER = "plugins" + File.separator + "Quests" + File.separator + "modules", + PLACEHOLDERS_FOLDER = "plugins" + File.separator + "PlaceholderAPI" + File.separator + "expansions"; + + /** + * Copies a resource embedded in the jar into the given folder + * + * @param name name of the file + * @param folder folder to put the file in + */ + public static void copyResource(String name, String folder) { + try { + // Prepare to copy the file + InputStream stream = ResourceManager.class.getResourceAsStream("/" + name); + OutputStream resStreamOut; + int readBytes; + byte[] buffer = new byte[4096]; + File dir = new File(folder); + dir.mkdirs(); + resStreamOut = new FileOutputStream(new File(dir, name)); + + // Copy to the file + while ((readBytes = stream.read(buffer)) > 0) { + resStreamOut.write(buffer, 0, readBytes); + } + + // Close the streams + stream.close(); + resStreamOut.close(); + } catch (Exception ex) { + Logger.bug("Failed to copy resource: " + name); + } + } + + /** + *

    Places the SkillAPI module for Quests into the proper directory

    + */ + public static void copyQuestsModule() { + copyResource("legacy/SkillAPIModule.jar", QUESTS_FOLDER); + } + + public static void copyPlaceholdersModule() { + copyResource("legacy/SkillAPIPlaceholders.jar", PLACEHOLDERS_FOLDER); + } +} diff --git a/src/com/sucy/skill/manager/TitleManager.java b/src/main/java/com/sucy/skill/manager/TitleManager.java similarity index 100% rename from src/com/sucy/skill/manager/TitleManager.java rename to src/main/java/com/sucy/skill/manager/TitleManager.java diff --git a/src/com/sucy/skill/packet/PacketHandler.java b/src/main/java/com/sucy/skill/packet/PacketHandler.java similarity index 100% rename from src/com/sucy/skill/packet/PacketHandler.java rename to src/main/java/com/sucy/skill/packet/PacketHandler.java diff --git a/src/com/sucy/skill/packet/PacketInjector.java b/src/main/java/com/sucy/skill/packet/PacketInjector.java similarity index 100% rename from src/com/sucy/skill/packet/PacketInjector.java rename to src/main/java/com/sucy/skill/packet/PacketInjector.java diff --git a/src/com/sucy/skill/task/CooldownTask.java b/src/main/java/com/sucy/skill/task/CooldownTask.java similarity index 89% rename from src/com/sucy/skill/task/CooldownTask.java rename to src/main/java/com/sucy/skill/task/CooldownTask.java index 48ebcb2c..dd01fcb6 100644 --- a/src/com/sucy/skill/task/CooldownTask.java +++ b/src/main/java/com/sucy/skill/task/CooldownTask.java @@ -27,9 +27,13 @@ package com.sucy.skill.task; import com.rit.sucy.version.VersionManager; +import org.bukkit.Bukkit; import com.sucy.skill.SkillAPI; import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.listener.MainListener; import com.sucy.skill.thread.RepeatThreadTask; + +import org.bukkit.Bukkit; import org.bukkit.entity.Player; /** @@ -45,6 +49,7 @@ public class CooldownTask extends RepeatThreadTask public CooldownTask() { super(20, 20); + } /** @@ -53,8 +58,9 @@ public CooldownTask() @Override public void run() { - for (Player player : VersionManager.getOnlinePlayers()) + for (Player player : Bukkit.getOnlinePlayers()) { + if (MainListener.loadingPlayers.contains(player.getUniqueId())) continue; PlayerData data = SkillAPI.getPlayerData(player); if (data.hasClass()) { diff --git a/src/com/sucy/skill/task/EffectTask.java b/src/main/java/com/sucy/skill/task/EffectTask.java similarity index 100% rename from src/com/sucy/skill/task/EffectTask.java rename to src/main/java/com/sucy/skill/task/EffectTask.java diff --git a/src/com/sucy/skill/task/GUITask.java b/src/main/java/com/sucy/skill/task/GUITask.java similarity index 95% rename from src/com/sucy/skill/task/GUITask.java rename to src/main/java/com/sucy/skill/task/GUITask.java index e8c22754..2fc62308 100644 --- a/src/com/sucy/skill/task/GUITask.java +++ b/src/main/java/com/sucy/skill/task/GUITask.java @@ -33,9 +33,12 @@ import com.sucy.skill.api.player.PlayerData; import com.sucy.skill.api.util.ActionBar; import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.listener.MainListener; import com.sucy.skill.log.LogType; import com.sucy.skill.log.Logger; import com.sucy.skill.thread.RepeatThreadTask; + +import org.bukkit.Bukkit; import org.bukkit.entity.Player; /** @@ -64,7 +67,7 @@ public class GUITask extends RepeatThreadTask public GUITask(SkillAPI api) { super(5, 5); - + String levelBar = SkillAPI.getSettings().getLevelBar().toLowerCase(); levelMana = levelBar.equals("mana"); levelLevel = levelBar.equals("level"); @@ -93,11 +96,11 @@ public GUITask(SkillAPI api) @Override public void run() { - Logger.log(LogType.GUI, 1, "Updating GUI (" + VersionManager.getOnlinePlayers().length + " players)..."); - for (Player player : VersionManager.getOnlinePlayers()) + Logger.log(LogType.GUI, 1, "Updating GUI (" + Bukkit.getOnlinePlayers().size() + " players)..."); + for (Player player : Bukkit.getOnlinePlayers()) { if (!SkillAPI.getSettings().isWorldEnabled(player.getWorld())) continue; - + if (MainListener.loadingPlayers.contains(player.getUniqueId())) continue; PlayerData data = SkillAPI.getPlayerData(player); // Health scale diff --git a/src/com/sucy/skill/task/PreviewTask.java b/src/main/java/com/sucy/skill/task/PreviewTask.java similarity index 100% rename from src/com/sucy/skill/task/PreviewTask.java rename to src/main/java/com/sucy/skill/task/PreviewTask.java diff --git a/src/com/sucy/skill/task/ManaTask.java b/src/main/java/com/sucy/skill/task/RegenTask.java similarity index 82% rename from src/com/sucy/skill/task/ManaTask.java rename to src/main/java/com/sucy/skill/task/RegenTask.java index b89a5dee..1c9375f8 100644 --- a/src/com/sucy/skill/task/ManaTask.java +++ b/src/main/java/com/sucy/skill/task/RegenTask.java @@ -29,24 +29,26 @@ import com.rit.sucy.version.VersionManager; import com.sucy.skill.SkillAPI; import com.sucy.skill.api.player.PlayerData; +import com.sucy.skill.listener.MainListener; import com.sucy.skill.log.LogType; import com.sucy.skill.log.Logger; import com.sucy.skill.thread.RepeatThreadTask; import org.bukkit.entity.Player; +import org.bukkit.Bukkit; /** *

    Restores mana to all players over time.

    *

    This task is run by the API and you should not * use this task yourself.

    */ -public class ManaTask extends RepeatThreadTask +public class RegenTask extends RepeatThreadTask { /** * Starts a new task for regenerating mana over time. The task is * started automatically so don't initialize this class unless wanting to * start a new task. */ - public ManaTask() + public RegenTask() { super( SkillAPI.getSettings().getGainFreq(), @@ -59,12 +61,15 @@ public ManaTask() */ public void run() { - Player[] players = VersionManager.getOnlinePlayers(); - Logger.log(LogType.MANA, 1, "Applying mana regen for " + players.length + " players"); - for (Player player : players) + Logger.log(LogType.MANA, 1, "Applying mana regen for " + Bukkit.getOnlinePlayers().size() + " players"); + for (Player player : Bukkit.getOnlinePlayers()) { + if (MainListener.loadingPlayers.contains(player.getUniqueId())) continue; PlayerData data = SkillAPI.getPlayerData(player); - data.regenMana(); - } + if(data != null) { + data.regenMana(); + data.regenHealth(player); + } + } } } diff --git a/src/com/sucy/skill/task/RemoveTask.java b/src/main/java/com/sucy/skill/task/RemoveTask.java similarity index 100% rename from src/com/sucy/skill/task/RemoveTask.java rename to src/main/java/com/sucy/skill/task/RemoveTask.java diff --git a/src/com/sucy/skill/task/SaveTask.java b/src/main/java/com/sucy/skill/task/SaveTask.java similarity index 100% rename from src/com/sucy/skill/task/SaveTask.java rename to src/main/java/com/sucy/skill/task/SaveTask.java diff --git a/src/com/sucy/skill/task/ScoreboardTask.java b/src/main/java/com/sucy/skill/task/ScoreboardTask.java similarity index 100% rename from src/com/sucy/skill/task/ScoreboardTask.java rename to src/main/java/com/sucy/skill/task/ScoreboardTask.java diff --git a/src/com/sucy/skill/thread/IThreadTask.java b/src/main/java/com/sucy/skill/thread/IThreadTask.java similarity index 100% rename from src/com/sucy/skill/thread/IThreadTask.java rename to src/main/java/com/sucy/skill/thread/IThreadTask.java diff --git a/src/com/sucy/skill/thread/MainThread.java b/src/main/java/com/sucy/skill/thread/MainThread.java similarity index 100% rename from src/com/sucy/skill/thread/MainThread.java rename to src/main/java/com/sucy/skill/thread/MainThread.java diff --git a/src/com/sucy/skill/thread/RepeatThreadTask.java b/src/main/java/com/sucy/skill/thread/RepeatThreadTask.java similarity index 100% rename from src/com/sucy/skill/thread/RepeatThreadTask.java rename to src/main/java/com/sucy/skill/thread/RepeatThreadTask.java diff --git a/src/com/sucy/skill/thread/TaskList.java b/src/main/java/com/sucy/skill/thread/TaskList.java similarity index 100% rename from src/com/sucy/skill/thread/TaskList.java rename to src/main/java/com/sucy/skill/thread/TaskList.java diff --git a/src/com/sucy/skill/thread/ThreadTask.java b/src/main/java/com/sucy/skill/thread/ThreadTask.java similarity index 100% rename from src/com/sucy/skill/thread/ThreadTask.java rename to src/main/java/com/sucy/skill/thread/ThreadTask.java diff --git a/src/com/sucy/skill/tree/SkillTree.java b/src/main/java/com/sucy/skill/tree/SkillTree.java similarity index 100% rename from src/com/sucy/skill/tree/SkillTree.java rename to src/main/java/com/sucy/skill/tree/SkillTree.java diff --git a/src/com/sucy/skill/tree/basic/BasicHorizontalTree.java b/src/main/java/com/sucy/skill/tree/basic/BasicHorizontalTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/BasicHorizontalTree.java rename to src/main/java/com/sucy/skill/tree/basic/BasicHorizontalTree.java diff --git a/src/com/sucy/skill/tree/basic/BasicVerticalTree.java b/src/main/java/com/sucy/skill/tree/basic/BasicVerticalTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/BasicVerticalTree.java rename to src/main/java/com/sucy/skill/tree/basic/BasicVerticalTree.java diff --git a/src/com/sucy/skill/tree/basic/FloodTree.java b/src/main/java/com/sucy/skill/tree/basic/FloodTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/FloodTree.java rename to src/main/java/com/sucy/skill/tree/basic/FloodTree.java diff --git a/src/com/sucy/skill/tree/basic/InventoryTree.java b/src/main/java/com/sucy/skill/tree/basic/InventoryTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/InventoryTree.java rename to src/main/java/com/sucy/skill/tree/basic/InventoryTree.java diff --git a/src/com/sucy/skill/tree/basic/LevelHorizontalTree.java b/src/main/java/com/sucy/skill/tree/basic/LevelHorizontalTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/LevelHorizontalTree.java rename to src/main/java/com/sucy/skill/tree/basic/LevelHorizontalTree.java diff --git a/src/com/sucy/skill/tree/basic/LevelTree.java b/src/main/java/com/sucy/skill/tree/basic/LevelTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/LevelTree.java rename to src/main/java/com/sucy/skill/tree/basic/LevelTree.java diff --git a/src/com/sucy/skill/tree/basic/LevelVerticalTree.java b/src/main/java/com/sucy/skill/tree/basic/LevelVerticalTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/LevelVerticalTree.java rename to src/main/java/com/sucy/skill/tree/basic/LevelVerticalTree.java diff --git a/src/com/sucy/skill/tree/basic/RequirementTree.java b/src/main/java/com/sucy/skill/tree/basic/RequirementTree.java similarity index 100% rename from src/com/sucy/skill/tree/basic/RequirementTree.java rename to src/main/java/com/sucy/skill/tree/basic/RequirementTree.java diff --git a/src/com/sucy/skill/util/Lists.java b/src/main/java/com/sucy/skill/util/Lists.java similarity index 100% rename from src/com/sucy/skill/util/Lists.java rename to src/main/java/com/sucy/skill/util/Lists.java diff --git a/configs/attributes.yml b/src/main/resources/attributes.yml similarity index 100% rename from configs/attributes.yml rename to src/main/resources/attributes.yml diff --git a/configs/config.yml b/src/main/resources/config.yml similarity index 100% rename from configs/config.yml rename to src/main/resources/config.yml diff --git a/configs/effects.yml b/src/main/resources/effects.yml similarity index 100% rename from configs/effects.yml rename to src/main/resources/effects.yml diff --git a/configs/exp.yml b/src/main/resources/exp.yml similarity index 100% rename from configs/exp.yml rename to src/main/resources/exp.yml diff --git a/configs/internal/mobSizes.yml b/src/main/resources/internal/mobSizes.yml similarity index 100% rename from configs/internal/mobSizes.yml rename to src/main/resources/internal/mobSizes.yml diff --git a/configs/language.yml b/src/main/resources/language.yml similarity index 100% rename from configs/language.yml rename to src/main/resources/language.yml diff --git a/configs/plugin.yml b/src/main/resources/plugin.yml similarity index 94% rename from configs/plugin.yml rename to src/main/resources/plugin.yml index 8f5783c5..e60499e8 100644 --- a/configs/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,11 +1,14 @@ name: SkillAPI main: com.sucy.skill.SkillAPI -version: 1.89 +version: 1.90 author: Eniripsa96 depend: [MCCore] -softdepend: [Vault] +softdepend: [Vault, MythicMobs] loadbefore: [Quests] api-version: 1.13 +commands: + class: + description: Class command permissions: skillapi.basic: diff --git a/configs/tool.yml b/src/main/resources/tool.yml similarity index 100% rename from configs/tool.yml rename to src/main/resources/tool.yml diff --git a/configs/worldGuard.yml b/src/main/resources/worldGuard.yml similarity index 100% rename from configs/worldGuard.yml rename to src/main/resources/worldGuard.yml