From e379c866bd8715bed9dba797462c6da38d0c03a2 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Tue, 26 Mar 2024 21:25:00 +0100 Subject: [PATCH 01/18] switch to gradle remove unused PlotsquaredManager, ConfigManager, GriefPreventionManager and CommandManager --- .gitignore | 104 +++ README.md | 2 +- build.gradle.kts | 72 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 +++++++ gradlew.bat | 92 +++ settings.gradle.kts | 8 + src/com/rifledluffy/chairs/ChairManager.java | 629 ------------------ src/com/rifledluffy/chairs/ConfigManager.java | 87 --- .../rifledluffy/chairs/MessageManager.java | 107 --- src/com/rifledluffy/chairs/RFChairs.java | 131 ---- src/com/rifledluffy/chairs/TargetInfo.java | 61 -- src/com/rifledluffy/chairs/chairs/Chair.java | 111 ---- .../command/commands/CommandManager.java | 101 --- .../chairs/command/commands/HelpCommand.java | 62 -- .../chairs/command/commands/MuteCommand.java | 69 -- .../command/commands/ReloadCommand.java | 65 -- .../chairs/command/commands/ResetCommand.java | 56 -- .../command/commands/ToggleCommand.java | 69 -- .../chairs/config/ConfigManager.java | 117 ---- .../chairs/events/ChairCheckEvent.java | 48 -- .../chairs/events/ChairLeaveEvent.java | 48 -- .../chairs/events/ChairReplaceEvent.java | 43 -- .../chairs/events/ChairSitEvent.java | 37 -- .../chairs/events/ChairTossEvent.java | 57 -- .../managers/GriefPreventionManager.java | 27 - .../chairs/managers/PlotSquaredManager.java | 29 - .../chairs/managers/WorldGuardManager.java | 83 --- .../chairs/messages/MessageEvent.java | 75 --- .../chairs/messages/MessageType.java | 7 - .../rifledluffy/chairs/messages/Messages.java | 92 --- src/com/rifledluffy/chairs/utility/Util.java | 316 --------- .../com/rifledluffy/chairs/ChairManager.java | 599 +++++++++++++++++ .../rifledluffy/chairs/MessageManager.java | 107 +++ .../java/com/rifledluffy/chairs/RFChairs.java | 130 ++++ .../com/rifledluffy/chairs/TargetInfo.java | 60 ++ .../chairs/chairs/BlockFilter.java | 37 +- .../com/rifledluffy/chairs/chairs/Chair.java | 109 +++ .../chairs/command/CommandManager.java | 60 +- .../chairs/command/commands/HelpCommand.java | 61 ++ .../chairs/command/commands/InfoCommand.java | 32 +- .../chairs/command/commands/MuteCommand.java | 66 ++ .../command/commands/ReloadCommand.java | 64 ++ .../chairs/command/commands/ResetCommand.java | 55 ++ .../chairs/command/commands/SubCommand.java | 7 +- .../command/commands/ToggleCommand.java | 66 ++ .../chairs/config/ConfigManager.java | 108 +++ .../chairs/events/ChairCheckEvent.java | 46 ++ .../chairs/events/ChairLeaveEvent.java | 46 ++ .../chairs/events/ChairReplaceEvent.java | 41 ++ .../chairs/events/ChairSitEvent.java | 35 + .../chairs/events/ChairTossEvent.java | 55 ++ .../chairs/managers/WorldGuardManager.java | 84 +++ .../chairs/messages/MessageConstruct.java | 3 +- .../chairs/messages/MessageEvent.java | 73 ++ .../chairs/messages/MessageType.java | 7 + .../rifledluffy/chairs/messages/Messages.java | 92 +++ .../chairs/metrics/MetricsLite.java | 156 ++--- .../com/rifledluffy/chairs/utility/Util.java | 318 +++++++++ config.yml => src/main/resources/config.yml | 4 +- src/main/resources/messages.properties | 53 ++ src/main/resources/messages_en.properties | 53 ++ plugin.yml => src/main/resources/plugin.yml | 12 +- src/messages.yml | 53 -- 65 files changed, 3013 insertions(+), 2740 deletions(-) create mode 100644 .gitignore create mode 100644 build.gradle.kts create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts delete mode 100644 src/com/rifledluffy/chairs/ChairManager.java delete mode 100644 src/com/rifledluffy/chairs/ConfigManager.java delete mode 100644 src/com/rifledluffy/chairs/MessageManager.java delete mode 100644 src/com/rifledluffy/chairs/RFChairs.java delete mode 100644 src/com/rifledluffy/chairs/TargetInfo.java delete mode 100644 src/com/rifledluffy/chairs/chairs/Chair.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/CommandManager.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/HelpCommand.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/MuteCommand.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/ReloadCommand.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/ResetCommand.java delete mode 100644 src/com/rifledluffy/chairs/command/commands/ToggleCommand.java delete mode 100644 src/com/rifledluffy/chairs/config/ConfigManager.java delete mode 100644 src/com/rifledluffy/chairs/events/ChairCheckEvent.java delete mode 100644 src/com/rifledluffy/chairs/events/ChairLeaveEvent.java delete mode 100644 src/com/rifledluffy/chairs/events/ChairReplaceEvent.java delete mode 100644 src/com/rifledluffy/chairs/events/ChairSitEvent.java delete mode 100644 src/com/rifledluffy/chairs/events/ChairTossEvent.java delete mode 100644 src/com/rifledluffy/chairs/managers/GriefPreventionManager.java delete mode 100644 src/com/rifledluffy/chairs/managers/PlotSquaredManager.java delete mode 100644 src/com/rifledluffy/chairs/managers/WorldGuardManager.java delete mode 100644 src/com/rifledluffy/chairs/messages/MessageEvent.java delete mode 100644 src/com/rifledluffy/chairs/messages/MessageType.java delete mode 100644 src/com/rifledluffy/chairs/messages/Messages.java delete mode 100644 src/com/rifledluffy/chairs/utility/Util.java create mode 100644 src/main/java/com/rifledluffy/chairs/ChairManager.java create mode 100644 src/main/java/com/rifledluffy/chairs/MessageManager.java create mode 100644 src/main/java/com/rifledluffy/chairs/RFChairs.java create mode 100644 src/main/java/com/rifledluffy/chairs/TargetInfo.java rename src/{ => main/java}/com/rifledluffy/chairs/chairs/BlockFilter.java (89%) create mode 100644 src/main/java/com/rifledluffy/chairs/chairs/Chair.java rename src/{ => main/java}/com/rifledluffy/chairs/command/CommandManager.java (62%) create mode 100644 src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java rename src/{ => main/java}/com/rifledluffy/chairs/command/commands/InfoCommand.java (53%) create mode 100644 src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java create mode 100644 src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java create mode 100644 src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java rename src/{ => main/java}/com/rifledluffy/chairs/command/commands/SubCommand.java (94%) create mode 100644 src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java create mode 100644 src/main/java/com/rifledluffy/chairs/config/ConfigManager.java create mode 100644 src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java rename src/{ => main/java}/com/rifledluffy/chairs/messages/MessageConstruct.java (69%) create mode 100644 src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java create mode 100644 src/main/java/com/rifledluffy/chairs/messages/MessageType.java create mode 100644 src/main/java/com/rifledluffy/chairs/messages/Messages.java rename src/{ => main/java}/com/rifledluffy/chairs/metrics/MetricsLite.java (95%) create mode 100644 src/main/java/com/rifledluffy/chairs/utility/Util.java rename config.yml => src/main/resources/config.yml (98%) create mode 100644 src/main/resources/messages.properties create mode 100644 src/main/resources/messages_en.properties rename plugin.yml => src/main/resources/plugin.yml (83%) delete mode 100644 src/messages.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3016ed4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,104 @@ +# ---> JetBrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties + +# ---> Eclipse +*.pydevproject +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + +# ---> Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# ---> Gradle +.gradle +build/ +target +run/ diff --git a/README.md b/README.md index 5a33340..5d92c83 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -Rifle's Chairs +Rifle's Chairs - Greensurvivors Fork diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..b3a8e87 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,72 @@ +plugins { + `java-library` + //java + id("io.papermc.paperweight.userdev") version "1.5.11" + id("xyz.jpenilla.run-paper") version "2.2.3" // Adds runServer and runMojangMappedServer tasks for testing +} + +group = "com.rifledluffy.chairs" +version = "7.0.0-SNAPSHOT" +description = "A Greensurvivors Plugin " +// this is the minecraft major version. If you need a subversion like 1.20.1, +// change it in the dependencies section as this is also used as the api version of the plugin.yml +val mainMCVersion by extra("1.20") + +java { + // Configure the java toolchain. This allows gradle to auto-provision JDK 17 on systems that only have JDK 8 installed for example. + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + +repositories { + mavenLocal() + + //paper + maven { + url = uri("https://repo.papermc.io/repository/maven-public/") + } + //world guard + maven { + url = uri("https://maven.enginehub.org/repo/") + } +} + +dependencies { + paperweight.paperDevBundle("$mainMCVersion.1-R0.1-SNAPSHOT") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + //plotsquared + implementation(platform("com.intellectualsites.bom:bom-newest:1.42")) + compileOnly("com.intellectualsites.plotsquared:plotsquared-core") + compileOnly("com.intellectualsites.plotsquared:plotsquared-bukkit") { isTransitive = false } +} + +tasks { + // Configure reobfJar to run when invoking the build task + assemble { + dependsOn(reobfJar) + } + + compileJava { + options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything + + // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. + // See https://openjdk.java.net/jeps/247 for more information. + options.release.set(17) + } + + processResources { + filteringCharset = Charsets.UTF_8.name() // We want UTF-8 for everything + + expand("version" to project.version, + "description" to project.description, + "apiVersion" to mainMCVersion) + } + + /* + reobfJar { + // This is an example of how you might change the output location for reobfJar. It's recommended not to do this + // for a variety of reasons, however it's asked frequently enough that an example of how to do it is included here. + outputJar.set(layout.buildDirectory.file("libs/PaperweightTestPlugin-${project.version}.jar")) + } + */ + +} \ 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 0000000000000000000000000000000000000000..7f93135c49b765f8051ef9d0a6055ff8e46073d8 GIT binary patch literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a80b22c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@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=. +@rem This is normally unused +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% equ 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% equ 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! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..fa39065 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,8 @@ +pluginManagement { + repositories { + gradlePluginPortal() + } +} + + +rootProject.name = "RFChairs" diff --git a/src/com/rifledluffy/chairs/ChairManager.java b/src/com/rifledluffy/chairs/ChairManager.java deleted file mode 100644 index f2c2bd4..0000000 --- a/src/com/rifledluffy/chairs/ChairManager.java +++ /dev/null @@ -1,629 +0,0 @@ -package com.rifledluffy.chairs; - -import com.rifledluffy.chairs.chairs.BlockFilter; -import com.rifledluffy.chairs.chairs.Chair; -import com.rifledluffy.chairs.config.ConfigManager; -import com.rifledluffy.chairs.events.ChairCheckEvent; -import com.rifledluffy.chairs.events.ChairLeaveEvent; -import com.rifledluffy.chairs.events.ChairReplaceEvent; -import com.rifledluffy.chairs.events.ChairSitEvent; -import com.rifledluffy.chairs.events.ChairTossEvent; -import com.rifledluffy.chairs.messages.MessageConstruct; -import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; -import com.rifledluffy.chairs.utility.Util; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.player.PlayerGameModeChangeEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.projectiles.ProjectileSource; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.util.Vector; -import org.spigotmc.event.entity.EntityDismountEvent; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.stream.Collectors; - -public class ChairManager implements Listener { - - private RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private ConfigManager configManager = plugin.getConfigManager(); - private FileConfiguration config = configManager.getConfig(); - - private Map chairMap = new HashMap<>(); - public List chairs = new ArrayList<>(); - private List fakeSeats = new ArrayList<>(); - private List leaving = new ArrayList<>(); - private List orienting = new ArrayList<>(); - private Map tossed = new HashMap<>(); - - public List toggled = new ArrayList<>(); - - private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); - private boolean regenWhenSitting; - - //Update related - private boolean disableCurrentUpdate; - private boolean disableUpdates; - - //Kick them off their seat if they take damage - private boolean canLaunch; - - //Toss them off their seat if they take damage - private boolean canToss; - //The minimum damage needed for a player to be tossed - private double minDamage; - - //Toss Configuration - private boolean faceAttacker; - private double tossVelocity; - private boolean scaleVelocity; - private double scaleAmount; - - //Maximum amount of items on hand that they can have when trying to sit - private int maxItemSit; - private double maxDistance; - private boolean checkForSigns; - private boolean priorityIfHasPerm; - private boolean trapSeats; - private boolean requireEmptyHand; - - //Mostly buggy, probably going to remove soon. - private boolean exitWhereFacing; - - public Vector stairSeatingPosition; - public Vector slabSeatingPosition; - public Vector carpetSeatingPosition; - - private List disabledWorlds = new ArrayList<>(); - - public void reload(RFChairs plugin) { - configManager = plugin.getConfigManager(); - config = configManager.getConfig(); - - regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); - regenWhenSitting = config.getBoolean("regen-when-sitting", true); - - disableCurrentUpdate = config.getBoolean("disable-update-message-if-on-latest", false); - disableUpdates = config.getBoolean("disable-update-messages", false); - - faceAttacker = config.getBoolean("face-attacker-when-ejected", false); - canToss = config.getBoolean("toss-player", false); - tossVelocity = config.getDouble("toss-velocity", 0.5D); - scaleVelocity = config.getBoolean("scale-toss-velocity", true); - scaleAmount = config.getDouble("velocity-scale-factor", 2D); - canLaunch = config.getBoolean("eject-player-on-damage", true); - minDamage = config.getDouble("minimum-eject-damage", 2D); - exitWhereFacing = config.getBoolean("exit-seat-where-facing", false); - maxItemSit = config.getInt("max-item-count-to-sit", -1); - maxDistance = config.getDouble("max-distance", 2D); - checkForSigns = config.getBoolean("require-signs-at-end", false); - priorityIfHasPerm = config.getBoolean("priority-on-if-has-perm", true); - trapSeats = config.getBoolean("allow-trap-door-chairs", true); - requireEmptyHand = config.getBoolean("require-empty-hand", false); - - try { - String[] vectorString = Objects.requireNonNull(config.getString("stair-seating-position", "0.5,0.3,0.5")).split(","); - stairSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); - } catch (NumberFormatException e) { - stairSeatingPosition = new Vector(0.5D,0.3D,0.5); - } - - try { - String[] vectorString = Objects.requireNonNull(config.getString("slab-seating-position", "0.5,0.3,0.5")).split(","); - slabSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); - } catch (NumberFormatException e) { - slabSeatingPosition= new Vector(0.5,0.3D,0.5); - } - - try { - String[] vectorString = Objects.requireNonNull(config.getString("carpet-seating-position", "0.5,-0.15,0.5")).split(","); - carpetSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); - } catch (NumberFormatException e) { - carpetSeatingPosition= new Vector(0.5,-0.15D,0.5); - } - - disabledWorlds = config.getStringList("disabled-worlds").stream() - .map(Bukkit::getWorld) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - @EventHandler - public void onChairSit(ChairSitEvent event) { - Chair chair = event.getChair(); - if (chair == null) return; - if (chair.getLocation() == null) return; - if (event.getPlayer() == null) return; - - if (plugin.hasWorldGuard()) if (!plugin.getWorldGuardManager().validateSeating(chair, event.getPlayer())) { - Util.callEvent(new MessageEvent(MessageType.WORLDGUARD, event.getPlayer())); - return; - } - - Player player = event.getPlayer(); - - if (Util.playerIsSeated(player.getUniqueId(), chairMap)) clearPlayer(player); - boolean done = sitPlayer(chair, player); - if (!done) return; - chairs.add(chair); - chairMap.put(player.getUniqueId(), chair); - if (regenWhenSitting) player.addPotionEffect(regenEffect); - } - - @EventHandler - public void onChairLeave(ChairLeaveEvent event) { - Chair chair = event.getChair(); - if (chair == null) return; - if (chair.getLocation() == null) return; - - Block block = chair.getLocation().getBlock(); - Player player = event.getPlayer(); - boolean flag = event.exitWhereFacing(); - - Location exit = block.getLocation(); - - clearPlayer(player); - player.removePotionEffect(PotionEffectType.REGENERATION); - if (flag) exit = findExitPoint(player.getLocation(), block).getLocation(); - if (Util.surroundedBlock(block) || Util.nearLiquid(player.getLocation().getBlock())) exit = block.getRelative(BlockFace.UP).getLocation(); - exit.setDirection(player.getEyeLocation().getDirection()); - exit.add(0.5,0,0.5); - player.teleport(exit); - if (!flag) { - Vector v = player.getEyeLocation().getDirection(); - v.setY(0); - v.normalize(); - v.setY(1); - player.setVelocity(v.multiply(0.25)); - } - } - - @EventHandler - public void onToss(ChairTossEvent event) { - Chair chair = event.getChair(); - if (chair == null) return; - if (chair.getLocation() == null) return; - - Block block = chair.getBlock(); - Player player = event.getPlayer(); - Entity attacker = event.getAttacker(); - TargetInfo info = event.getInfo(); - boolean silent = event.isSilent(); - - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, false); - Util.callEvent(leaveEvent); - - if (!silent) { - MessageEvent messageEvent; - MessageEvent otherEvent = null; - if (attacker instanceof Player) { - Player playerEntity = (Player) attacker; - if (info != null && !info.isSprinting()) messageEvent = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, player, playerEntity); - else messageEvent = new MessageEvent(MessageType.TOSSEDSPEED, MessageConstruct.DEFENSIVE, player, playerEntity); - - if (info != null && !info.isSprinting()) otherEvent = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, playerEntity, player); - else otherEvent = new MessageEvent(MessageType.TOSSINGSPEED, MessageConstruct.OFFENSIVE, playerEntity, player); - } - else messageEvent = new MessageEvent(MessageType.TOSSED, player, attacker); - Util.callEvent(messageEvent); - if (otherEvent != null) Util.callEvent(otherEvent); - } - - if (canToss) ejectPlayer(block, player, attacker); - } - - @EventHandler - public void onChairReplace(ChairReplaceEvent event) { - Chair chair = event.getChair(); - if (chair == null) return; - if (chair.getLocation() == null) return; - - Block block = chair.getBlock(); - Player player = event.getPlayer(); - Player seated = event.getReplaced(); - - if (player.getUniqueId() == seated.getUniqueId()) return; - - ChairTossEvent tossEvent = new ChairTossEvent(chair, seated, player, null, true); - Util.callEvent(tossEvent); - - MessageEvent tossed = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, seated, player); - Util.callEvent(tossed); - - ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); - Util.callEvent(sitEvent); - - MessageEvent tosser = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, player, seated); - Util.callEvent(tosser); - } - - @EventHandler - public void onChairCheck(ChairCheckEvent event) { - Player player = event.getPlayer(); - ItemStack item = player.getInventory().getItemInMainHand(); - Block block = event.getBlock(); - - if (!player.hasPermission("rfchairs.use")) { - Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); - return; - } - - if (player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) >= maxDistance) { - Util.callEvent(new MessageEvent(MessageType.TOOFAR, player)); - return; - } - - if (maxItemSit > 0 && item.getAmount() > maxItemSit) { - Util.callEvent(new MessageEvent(MessageType.TOOMANYITEMS, player)); - return; - } - - if (!Util.blockIsChair(block, chairs)) { - ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); - Util.callEvent(sitEvent); - } else { - Chair chair = Util.getChairFromBlock(block, chairs); - if (chair == null) return; - if (chair.getFakeSeat() != null && chair.getFakeSeat().getPassengers().size() == 0) { - chair.setPlayer(player); - chair.getFakeSeat().addPassenger(player); - if (regenWhenSitting) player.addPotionEffect(regenEffect); - return; - } - if (player.hasPermission("rfchairs.priority") && priorityIfHasPerm) { - ChairReplaceEvent replaceEvent = new ChairReplaceEvent(chair, chair.getPlayer(), player); - Util.callEvent(replaceEvent); - return; - } - if (chair.getPlayer() == null) return; - if (player.getUniqueId().equals(chair.getPlayer().getUniqueId())) { - orienting.add(player.getUniqueId()); - Location loc = chair.getFakeSeat().getLocation(); - loc.setDirection(player.getEyeLocation().getDirection().setY(0)); - chair.getFakeSeat().remove(); - ArmorStand newFakeSeat = Util.generateFakeSeatDir(chair, loc.getDirection()); - chair.setFakeSeat(newFakeSeat); - chair.getFakeSeat().addPassenger(player); - } else { - MessageEvent occupied = new MessageEvent(MessageType.OCCUPIED, MessageConstruct.OFFENSIVE, player, chair.getPlayer()); - Util.callEvent(occupied); - } - } - } - - @EventHandler - public void onRightClick(PlayerInteractEvent event) { - if (disabledWorlds.size() > 0 && disabledWorlds.contains(event.getPlayer().getWorld())) return; - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if (event.getPlayer().isSneaking()) return; - if (event.getHand() != EquipmentSlot.HAND) return; - if (toggled.contains(event.getPlayer().getUniqueId())) return; - - Block block = event.getClickedBlock(); - Player player = event.getPlayer(); - ItemStack item = event.getItem(); - if (block == null) return; - - if (requireEmptyHand && item != null) return; - - if (item != null && item.getType() != Material.AIR) { - if (item.getType().isBlock()) return; - } - - if (!BlockFilter.isStairsBlock(block.getType()) - && !BlockFilter.isCarpetBlock(block.getType()) - && !BlockFilter.isSlabBlock(block.getType())) return; - - if (BlockFilter.isStairsBlock(block.getType())) { - if (!Util.validStair(block)) return; - else { - if (checkForSigns) { - if (!Util.validCouch(block)) { - if (!trapSeats) return; - if (!Util.throneChair(block)) { - Util.callEvent(new MessageEvent(MessageType.NOSIGNS, player)); - return; - } - } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; - } - if (trapSeats && block.getRelative(BlockFace.UP).getType() != Material.AIR) { - if (!Util.throneChair(block)) return; - } - } - } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; - - if (BlockFilter.isSlabBlock(block.getType())) if (!Util.validSlab(block)) return; - - if (BlockFilter.isCarpetBlock(block.getType())) if (!Util.validCarpet(block)) return; - - if (event.getBlockFace() == BlockFace.DOWN) return; - - if (!player.hasPermission("rfchairs.use")) { - Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); - return; - } - - Util.callEvent(new ChairCheckEvent(block, player)); - } - - @EventHandler - public void onChangeGameMode(PlayerGameModeChangeEvent event) { - if (event.isCancelled()) return; - GameMode gameMode = event.getNewGameMode(); - Chair chair = chairMap.get(event.getPlayer().getUniqueId()); - if (gameMode == GameMode.SPECTATOR && chair != null) clearChair(chair); - } - - @EventHandler - public void onDismount(EntityDismountEvent event) { - if (!(event.getEntity() instanceof Player)) return; - Player player = (Player) event.getEntity(); - Chair chair = chairMap.get(player.getUniqueId()); - event.getDismounted(); - if (chair == null || event.getDismounted().getType() != EntityType.ARMOR_STAND) return; - if (leaving.contains(player.getUniqueId())) return; - if (orienting.contains(player.getUniqueId())) { - orienting.remove(player.getUniqueId()); - return; - } - if (tossed.containsKey(player.getUniqueId())) { - TargetInfo info = tossed.get(player.getUniqueId()); - Entity attacker = info.getEntity(); - if (info.hasSource() && info.livingSource()) attacker = info.getLivingSource(); - - ChairTossEvent tossEvent = new ChairTossEvent(chairMap.get(player.getUniqueId()), player, attacker, info, false); - Util.callEvent(tossEvent); - tossed.remove(player.getUniqueId()); - return; - } - leaving.add(player.getUniqueId()); - } - - @EventHandler - public void onMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - if (leaving.contains(player.getUniqueId())) { - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chairMap.get(player.getUniqueId()), player, exitWhereFacing); - Util.callEvent(leaveEvent); - leaving.remove(player.getUniqueId()); - } - } - - @EventHandler - public void takeDamage(EntityDamageByEntityEvent event) { - if (event.isCancelled()) return; - if (!(event.getEntity() instanceof Player)) return; - - Player player = (Player) event.getEntity(); - Entity attacker = event.getDamager(); - ProjectileSource source = null; - if (attacker instanceof Projectile) source = ((Projectile) attacker).getShooter(); - Chair chair = chairMap.get(player.getUniqueId()); - if (chair == null) return; - - if (event.getDamage() >= minDamage && canLaunch) { - TargetInfo info; - if (source == null) info = new TargetInfo(attacker, event.getDamage()); - else info = new TargetInfo(source, attacker, event.getDamage()); - tossed.put(player.getUniqueId(), info); - if (chair.getFakeSeat() != null) chair.getFakeSeat().removePassenger(player); - } - } - - @EventHandler - public void onBlockBreak(BlockBreakEvent event) { - if (event.isCancelled()) return; - chairs.stream() - .filter(Objects::nonNull) - .filter(c -> c.getLocation() != null) - .filter(c -> Util.samePosition(event.getBlock(), c.getBlock())) - .findAny() - .ifPresent(c -> { - if (!event.getPlayer().hasPermission("rfchairs.break")) event.setCancelled(true); - }); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void quit(PlayerQuitEvent event) { - Player player = event.getPlayer(); - Chair chair = chairMap.get(player.getUniqueId()); - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); - Util.callEvent(leaveEvent); - } - - @EventHandler - public void pistonExtend(BlockPistonExtendEvent event) { - for (Block block : event.getBlocks()) { - for (Chair chair: chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; - if (Util.samePosition(block, chair.getBlock())) { - event.setCancelled(true); - break; - } - } - } - } - - @EventHandler - public void pistonRetract(BlockPistonRetractEvent event) { - for (Block block : event.getBlocks()) { - for (Chair chair: chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; - if (Util.samePosition(block, chair.getBlock())) { - event.setCancelled(true); - break; - } - } - } - } - - @EventHandler - public void onDeath(PlayerDeathEvent event) { - Player player = event.getEntity(); - Chair chair = chairMap.get(player.getUniqueId()); - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); - Util.callEvent(leaveEvent); - } - - /* - * Sitting and Ejection Methods - */ - - private boolean sitPlayer(Chair chair, Player player) { - if (player == null) return false; - if (chair == null || chair.isOccupied()) return false; - - ArmorStand fakeSeat = chair.getFakeSeat(); - if (fakeSeat == null) fakeSeat = Util.generateFakeSeat(chair); - - fakeSeat.addPassenger(player); - chair.setFakeSeat(fakeSeat); - fakeSeats.add(fakeSeat.getUniqueId().toString()); - configManager.getData().set("UUIDs", fakeSeats); - return true; - } - - private void ejectPlayer(Block block, Player player, Entity entity) { - Block exit = block; - - if (exitWhereFacing) exit = findExitPoint(entity.getLocation(), block); - - Location exitLoc = exit.getLocation().add(0.5,0.5,0.5); - - if (!canToss) return; - - if (!faceAttacker) { - exitLoc.setPitch(player.getLocation().getPitch()); - exitLoc.setYaw(player.getLocation().getYaw()); - } else { - exitLoc.setDirection(Util.getVectorDir(player.getLocation(), entity.getLocation())); - } - - if (tossVelocity != 0) { - double finalVelocity = tossVelocity; - if (scaleVelocity && entity instanceof Player) { - if (((Player)entity).isSprinting()) finalVelocity = tossVelocity * scaleAmount; - } - player.setVelocity(exitLoc.getDirection().multiply(finalVelocity)); - } - } - - private Block findExitPoint(Location entity, Block block) { - Block blockToCheck = Util.getBlockFromDirection(block, Util.getCardinalDirection(entity)); - boolean foundValidExit = Util.canFitPlayer(blockToCheck) && Util.safePlace(blockToCheck); - - String[] directions = {"north", "east", "south", "west"}; - for (String direction: directions) { - if (foundValidExit) break; - blockToCheck = Util.getBlockFromDirection(block, direction); - foundValidExit = Util.canFitPlayer(blockToCheck) && Util.safePlace(blockToCheck); - } - if (!foundValidExit) blockToCheck = block.getRelative(BlockFace.UP); - return blockToCheck; - } - - /* - * Cleaning and Clearing - */ - - void saveToggled() { - List ids = new ArrayList<>(); - if (toggled == null || toggled.size() == 0) configManager.getData().set("Toggled", new ArrayList()); - for (UUID id : toggled) ids.add(id.toString()); - plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had toggled off."); - configManager.getData().set("Toggled", ids); - } - - void loadToggled() { - List toggled = configManager.getData().getStringList("Toggled"); - if (toggled.size() == 0) return; - plugin.getServer().getLogger().info("[RFChairs] " + toggled.size() + " Players had toggled off. Adding Them..."); - - toggled.stream() - .map(UUID::fromString) - .forEach(id -> this.toggled.add(id)); - - configManager.getData().set("Toggled", new ArrayList()); - } - - void shutdown() { - clearChairs(); - clearFakeSeats(); - } - - private void clearChair(Chair chair) { - if (chair == null) return; - if (chair.getPlayer() != null) chair.getPlayer().removePotionEffect(PotionEffectType.REGENERATION); - chair.clear(); - } - - private void clearChairs() { - for (Chair chair: chairs) clearChair(chair); - } - - private void clearPlayer(Player player) { - Chair chair = chairMap.get(player.getUniqueId()); - if (chair == null) return; - chairMap.remove(player.getUniqueId()); - chairs.remove(chair); - chair.clear(); - } - - public void clearFakeSeats() { - for (Chair chair : chairs) clearChair(chair); - } - - public void clearFakeSeatsFromFile(JavaPlugin plugin) { - List fakes = configManager.getData().getStringList("UUIDs"); - int leftoverFakes = fakes.size(); - if (leftoverFakes >= 1) { - plugin.getServer().getLogger().info("[RFChairs] Detected " + fakes.size() + " leftover seats! Removing..."); - for (String fake: fakes) { - UUID id = UUID.fromString(fake); - Entity armorStand = plugin.getServer().getEntity(id); - if (armorStand == null) continue; - armorStand.remove(); - } - configManager.getData().set("UUIDs", new ArrayList()); - } else { - plugin.getServer().getLogger().info("[RFChairs] No fake seats remaining! Proceeding"); - } - } - -} diff --git a/src/com/rifledluffy/chairs/ConfigManager.java b/src/com/rifledluffy/chairs/ConfigManager.java deleted file mode 100644 index 84d113a..0000000 --- a/src/com/rifledluffy/chairs/ConfigManager.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.rifledluffy.chairs; - -import java.io.File; -import java.io.IOException; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.java.JavaPlugin; - -public class ConfigManager { - - private JavaPlugin plugin = RFChairs.getPlugin(RFChairs.class); - - /* - * Configuration Files - */ - - FileConfiguration config; - File configFile; - - FileConfiguration fake; - File fakeFile; - - public void setup() { - configFile = new File(plugin.getDataFolder(), "config.yml"); - config = plugin.getConfig(); - config.options().copyDefaults(true); - saveConfig(); - - if (!plugin.getDataFolder().exists()) { - plugin.getDataFolder().mkdir(); - } - - fakeFile = new File(plugin.getDataFolder(), "fakes.yml"); - - if (!fakeFile.exists()) { - try { - fakeFile.createNewFile(); - } - catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not create fakes.yml!"); - } - } - - fake = YamlConfiguration.loadConfiguration(fakeFile); - } - - public FileConfiguration getData() { - return fake; - } - - public void saveData() { - try { - fake.save(fakeFile); - } - catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not save fakes.yml!"); - } - } - - public void reloadData() { - fake = YamlConfiguration.loadConfiguration(fakeFile); - } - - public FileConfiguration getConfig() { - return config; - } - - public void saveConfig() { - try { - config.save(configFile); - } - catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not save config.yml!"); - } - } - - public void reloadConfig() { - config = YamlConfiguration.loadConfiguration(configFile); - } - - public PluginDescriptionFile getDesc() { - return plugin.getDescription(); - } -} diff --git a/src/com/rifledluffy/chairs/MessageManager.java b/src/com/rifledluffy/chairs/MessageManager.java deleted file mode 100644 index f85343e..0000000 --- a/src/com/rifledluffy/chairs/MessageManager.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.rifledluffy.chairs; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; - -import com.rifledluffy.chairs.config.ConfigManager; -import com.rifledluffy.chairs.messages.MessageConstruct; -import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; -import com.rifledluffy.chairs.messages.Messages; -import com.rifledluffy.chairs.utility.Util; - -public class MessageManager implements Listener { - - private RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private ConfigManager configManager = plugin.getConfigManager(); - public FileConfiguration messages = configManager.getMessages(); - private boolean allowMessages; - private int tempMuteDuration; - - public List muted = new ArrayList(); - private List tempMute = new ArrayList(); - - public void reload(RFChairs plugin) { - configManager = plugin.getConfigManager(); - messages = configManager.getMessages(); - allowMessages = configManager.getConfig().getBoolean("allow-custom-messages", true); - tempMuteDuration = messages.getInt("temp-mute-duration", 0); - } - - private void tempMute(Player player) { - int duration = tempMuteDuration; - tempMute.add(player.getUniqueId()); - BukkitRunnable runnable = new BukkitRunnable() { - @Override - public void run() { - if (tempMuted(player)) tempMute.remove(player.getUniqueId()); - } - }; - runnable.runTaskLater(plugin, duration); - } - - private boolean tempMuted(Player player) { - return tempMute.contains(player.getUniqueId()); - } - - @EventHandler - public void onMessage(MessageEvent event) { - Player player = event.getPlayer(); - if (tempMute.contains(player.getUniqueId())) event.setCancelled(true); - if (event.isCancelled()) return; - if (tempMuteDuration > 0) tempMute(player); - if (allowMessages && !muted.contains(player.getUniqueId())) { - String string = processString(event); - if (!string.isEmpty()) player.sendMessage(string); - } - } - - private String processString(MessageEvent event) { - MessageType type = event.getType(); - MessageConstruct construct = event.getConstruct(); - String string; - - String stringOutput = Messages.getMessage(type); - if (stringOutput == null) { - string = Messages.getDefault(type); - } else { - string = stringOutput; - } - - string = messages.getString(string); - - String finalString = ""; - - if (construct == MessageConstruct.SINGLE) finalString = Util.replaceMessage(event.getPlayer(), string); - else if (construct == MessageConstruct.DEFENSIVE) finalString = Util.replaceMessage(event.getEntity(), event.getPlayer(), string); - else if (construct == MessageConstruct.OFFENSIVE && event.getEntity() instanceof Player) finalString = Util.replaceMessage(event.getPlayer(),(Player) event.getEntity(), string); - return finalString; - } - - void saveMuted() { - List ids = new ArrayList(); - if (muted == null || muted.size() == 0) configManager.getData().set("Muted", new ArrayList()); - for (UUID id : muted) ids.add(id.toString()); - plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had events muted."); - configManager.getData().set("Muted", ids); - } - - void loadMuted() { - List muted = configManager.getData().getStringList("Muted"); - if (muted == null || muted.size() == 0) return; - plugin.getServer().getLogger().info("[RFChairs] " + muted.size() + " Players had events muted off. Adding Them..."); - for (String toggler : muted) { - UUID id = UUID.fromString(toggler); - this.muted.add(id); - } - configManager.getData().set("Muted", new ArrayList()); - } - -} diff --git a/src/com/rifledluffy/chairs/RFChairs.java b/src/com/rifledluffy/chairs/RFChairs.java deleted file mode 100644 index 5f55f69..0000000 --- a/src/com/rifledluffy/chairs/RFChairs.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.rifledluffy.chairs; - -import java.io.IOException; - -import org.bukkit.Bukkit; -import org.bukkit.plugin.java.JavaPlugin; - -import com.rifledluffy.chairs.chairs.BlockFilter; -import com.rifledluffy.chairs.command.CommandManager; -import com.rifledluffy.chairs.config.ConfigManager; -import com.rifledluffy.chairs.managers.WorldGuardManager; -import com.rifledluffy.chairs.metrics.MetricsLite; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -public class RFChairs extends JavaPlugin { - - private static RFChairs instance; - public CommandManager commandManager; - public ConfigManager cfgManager; - public ChairManager chairManager; - public MessageManager messageManager; - public WorldGuardManager worldGuardManager; - - @Override - public void onLoad() { - setInstance(this); - loadWorldGuard(); - } - - private void loadWorldGuard() { - try { - Class.forName("com.sk89q.worldguard.WorldGuard"); - Class.forName("com.sk89q.worldedit.WorldEdit"); - Class.forName("com.sk89q.worldedit.math.BlockVector3"); - worldGuardManager = new WorldGuardManager(); - worldGuardManager.setup(); - getLogger().info("Found WorldGuard && WorldEdit! Applying Custom Flag..."); - } catch (ClassNotFoundException e) { - getLogger().info("Missing either WorldGuard or WorldEdit! Disabling Custom Flag Features..."); - getLogger().info("Latest WorldGuard/WorldEdit features could be missing. Please Update!"); - } - - if (worldGuardManager != null) worldGuardManager.register(); - } - - @Override - public void onEnable() { - - @SuppressWarnings("unused") - MetricsLite metrics = new MetricsLite(this); - - commandManager = new CommandManager(); - commandManager.setup(); - - loadConfigManager(); - - chairManager = new ChairManager(); - chairManager.clearFakeSeatsFromFile(this); - chairManager.loadToggled(); - - messageManager = new MessageManager(); - messageManager.loadMuted(); - - BlockFilter.reload(); - chairManager.reload(this); - messageManager.reload(this); - getServer().getPluginManager().registerEvents(chairManager, this); - getServer().getPluginManager().registerEvents(messageManager, this); - - getLogger().info("Rifle's Chairs has been enabled!"); - } - - @Override - public void onDisable() { - chairManager.saveToggled(); - messageManager.saveMuted(); - - chairManager.shutdown(); - - getLogger().info("Saving Configuration Files!"); - cfgManager.saveData(); - - Bukkit.getOnlinePlayers().forEach(p -> { - PotionEffect regen = p.getPotionEffect(PotionEffectType.REGENERATION); - if (regen == null) return; - if (regen.getDuration() > 1000) p.removePotionEffect(PotionEffectType.REGENERATION); - }); - - getLogger().info("Rifle's Chairs has been disabled!"); - } - - public void loadConfigManager() { - cfgManager = new ConfigManager(); - try { - cfgManager.setup(); - } catch (IOException e) { - e.printStackTrace(); - } - cfgManager.reloadConfig(); - } - - public ConfigManager getConfigManager() { - return cfgManager; - } - - public void setConfigManager(ConfigManager configManager) { - this.cfgManager = configManager; - } - - public static RFChairs getInstance() { - return instance; - } - - public WorldGuardManager getWorldGuardManager() { - return this.worldGuardManager; - } - - private static void setInstance(RFChairs instance) { - RFChairs.instance = instance; - } - - public void log(String string) { - getLogger().info(string); - } - - boolean hasWorldGuard() { - return worldGuardManager != null; - } - -} diff --git a/src/com/rifledluffy/chairs/TargetInfo.java b/src/com/rifledluffy/chairs/TargetInfo.java deleted file mode 100644 index cd1f28b..0000000 --- a/src/com/rifledluffy/chairs/TargetInfo.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.rifledluffy.chairs; - -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.projectiles.BlockProjectileSource; -import org.bukkit.projectiles.ProjectileSource; - -public class TargetInfo { - - Player player; - Entity attacker; - ProjectileSource source; - Double damage; - boolean sprinting = false; - - TargetInfo(ProjectileSource source, Entity attacker, Double damage) { - this.source = source; - this.attacker = attacker; - this.damage = damage; - } - - TargetInfo(Entity attacker, Double damage) { - this.source = null; - if (attacker instanceof Player) { - player = (Player) attacker; - sprinting = player.isSprinting(); - } - this.attacker = attacker; - this.damage = damage; - } - - Entity getEntity() { - return attacker; - } - - LivingEntity getLivingSource() { - return (LivingEntity) source; - } - - Block getBlockSource() { - return ((BlockProjectileSource)source).getBlock(); - } - - Double getDamage() { - return damage; - } - - boolean isSprinting() { - return this.sprinting; - } - - boolean hasSource() { - return source != null; - } - - boolean livingSource() { - return source != null && source instanceof LivingEntity; - } -} diff --git a/src/com/rifledluffy/chairs/chairs/Chair.java b/src/com/rifledluffy/chairs/chairs/Chair.java deleted file mode 100644 index 6653b99..0000000 --- a/src/com/rifledluffy/chairs/chairs/Chair.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.rifledluffy.chairs.chairs; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.data.BlockData; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Player; -import org.bukkit.material.Stairs; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; - -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.utility.Util; - -public class Chair { - - private BukkitRunnable clear; - private int clearID; - - private Location location; - private Block chair; - private ArmorStand fakeSeat = null; - private Player player; - - public Chair(Player player, Location location) { - this.location = location; - this.player = player; - this.chair = location.getBlock(); - - clear = new BukkitRunnable() { - - @Override - public void run() { - if (fakeSeat == null) { - clear(); - return; - } - if (fakeSeat.getPassengers().size() == 0) clear(); - } - - }; - clearID = clear.runTaskTimer(RFChairs.getInstance(), 20, 20).getTaskId(); - } - - /* - * Getters - */ - - public ArmorStand getFakeSeat() { - return fakeSeat; - } - - public Player getPlayer() { - return player; - } - - public Block getBlock() { - return location.getBlock(); - } - - public BlockState getBlockState() { - return chair.getState(); - } - - public BlockData getBlockData() { - return chair.getState().getBlockData(); - } - - public BlockFace getFacing() { - if (!BlockFilter.isStairsBlock(chair.getType())) return null; - return ((Stairs)chair.getState().getData()).getFacing(); - } - - public Location getLocation() { - return location; - } - - public boolean isOccupied() { - return !(fakeSeat == null) && !fakeSeat.isEmpty(); - } - - /* - * Setters - */ - - public void setPlayer(Player player) { - this.player = player; - } - - /* - * Methods - */ - - public void setFakeSeat(ArmorStand armorStand) { - fakeSeat = armorStand; - } - - public void clear() { - if (fakeSeat != null) fakeSeat.remove(); - if (player != null) player.removePotionEffect(PotionEffectType.REGENERATION); - chair = null; - location = null; - fakeSeat = null; - player = null; - if (Bukkit.getScheduler().isCurrentlyRunning(clearID)) clear.cancel(); - } - -} diff --git a/src/com/rifledluffy/chairs/command/commands/CommandManager.java b/src/com/rifledluffy/chairs/command/commands/CommandManager.java deleted file mode 100644 index 2c87600..0000000 --- a/src/com/rifledluffy/chairs/command/commands/CommandManager.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.RFChairs; - -import net.md_5.bungee.api.ChatColor; - -public class CommandManager implements CommandExecutor { - - private ArrayList commands = new ArrayList(); - private RFChairs plugin = RFChairs.getInstance(); - - public CommandManager(){} - - //Sub Commands - public String main = "rfchairs"; - public String info = "info"; - public String reload = "reload"; - public String reset = "reset"; - - public void setup() { - plugin.getCommand(main).setExecutor(this); - - this.commands.add(new HelpCommand()); - this.commands.add(new InfoCommand()); - this.commands.add(new ReloadCommand()); - this.commands.add(new ResetCommand()); - } - - public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { - - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Only players can use commands for this plugin."); - return true; - } - - Player player = (Player) sender; - - if (command.getName().equalsIgnoreCase(main)) { - if (args.length == 0) { - player.sendMessage(ChatColor.RED + "Missing Arguments. Type /rfchairs help for info"); - return true; - } - - SubCommand target = this.get(args[0]); - - if (target == null) { - player.sendMessage(ChatColor.RED + "Invalid subcommand"); - return true; - } - - ArrayList arrayList = new ArrayList(); - - arrayList.addAll(Arrays.asList(args)); - arrayList.remove(0); - - try{ - target.onCommand(player,args); - }catch (Exception e){ - player.sendMessage(ChatColor.RED + "An error has occurred."); - - e.printStackTrace(); - } - } - - return true; - } - - private SubCommand get(String name) { - Iterator subcommands = this.commands.iterator(); - - while (subcommands.hasNext()) { - SubCommand sc = (SubCommand) subcommands.next(); - - if (sc.name().equalsIgnoreCase(name)) { - return sc; - } - - String[] aliases; - int length = (aliases = sc.aliases()).length; - - for (int var5 = 0; var5 < length; ++var5) { - String alias = aliases[var5]; - if (name.equalsIgnoreCase(alias)) { - return sc; - } - - } - } - return null; - } - - } diff --git a/src/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/com/rifledluffy/chairs/command/commands/HelpCommand.java deleted file mode 100644 index 657607f..0000000 --- a/src/com/rifledluffy/chairs/command/commands/HelpCommand.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.RFChairs; - -import net.md_5.bungee.api.ChatColor; - -public class HelpCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); - sender.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages [Console Can Cast]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs [Console Can Cast]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor [Player Only]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor [Player Only]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version [Console Can Cast]"); - sender.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); - } - - @Override - public void onCommand(Player player, String[] args) { - player.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); - player.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); - player.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages"); - player.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs"); - player.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor"); - player.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor"); - player.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version"); - player.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); - } - - @Override - public String name() { - return plugin.commandManager.help; - } - - @Override - public String info() { - return null; - } - - @Override - public String[] aliases() { - return new String[0]; - } -} \ No newline at end of file diff --git a/src/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/com/rifledluffy/chairs/command/commands/MuteCommand.java deleted file mode 100644 index c93036a..0000000 --- a/src/com/rifledluffy/chairs/command/commands/MuteCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import java.util.List; -import java.util.UUID; - -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.MessageManager; -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; -import com.rifledluffy.chairs.utility.Util; - -public class MuteCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("�cOnly players can use commands for this plugin."); - } - - @Override - public void onCommand(Player player, String[] args) { - MessageManager messageManager = plugin.messageManager; - List muted = messageManager.muted; - String message; - if (!player.hasPermission("rfchairs.mute")) return; - if (muted.contains(player.getUniqueId())) { - String string = messageManager.messages.getString("mute-message-enabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); - muted.remove(player.getUniqueId()); - } - else { - String string = messageManager.messages.getString("mute-message-disabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); - muted.add(player.getUniqueId()); - } - } - - @Override - public String name() { - return plugin.commandManager.mute; - } - - @Override - public String info() { - return ""; - } - - @Override - public String[] aliases() { - return new String[0]; - } - -} diff --git a/src/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/com/rifledluffy/chairs/command/commands/ReloadCommand.java deleted file mode 100644 index 082a544..0000000 --- a/src/com/rifledluffy/chairs/command/commands/ReloadCommand.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.chairs.BlockFilter; -import com.rifledluffy.chairs.config.ConfigManager; - -import net.md_5.bungee.api.ChatColor; - -public class ReloadCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - ConfigManager newConfig = plugin.getConfigManager(); - newConfig.reloadConfig(); - newConfig.reloadMessages(); - plugin.setConfigManager(newConfig); - plugin.chairManager.reload(plugin); - plugin.messageManager.reload(plugin); - sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); - } - - @Override - public void onCommand(Player player, String[] args) { - if (!player.hasPermission("rfchairs.reload") && !player.hasPermission("rfchairs.manage")) return; - ConfigManager newConfig = plugin.getConfigManager(); - newConfig.reloadConfig(); - newConfig.reloadMessages(); - plugin.setConfigManager(newConfig); - BlockFilter.reload(); - plugin.chairManager.reload(plugin); - plugin.messageManager.reload(plugin); - player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); - } - - @Override - public String name() { - return plugin.commandManager.reload; - } - - @Override - public String info() { - return "Reloads the config and messages"; - } - - @Override - public String[] aliases() { - return new String[0]; - } - -} diff --git a/src/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/com/rifledluffy/chairs/command/commands/ResetCommand.java deleted file mode 100644 index e68ac18..0000000 --- a/src/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.RFChairs; - -import net.md_5.bungee.api.ChatColor; - -public class ResetCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - plugin.chairManager.clearFakeSeats(); - plugin.chairManager.clearFakeSeatsFromFile(plugin); - plugin.getLogger().info("Chairs Reset!"); - sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); - } - - @Override - public void onCommand(Player player, String[] args) { - if (!player.hasPermission("rfchairs.reset") && !player.hasPermission("rfchairs.manage")) return; - plugin.chairManager.clearFakeSeats(); - plugin.chairManager.clearFakeSeatsFromFile(plugin); - plugin.getLogger().info("Chairs Reset!"); - player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); - } - - @Override - public String name() { - return plugin.commandManager.reset; - } - - @Override - public String info() { - return "Resets all chairs"; - } - - @Override - public String[] aliases() { - return new String[0]; - } - -} \ No newline at end of file diff --git a/src/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/com/rifledluffy/chairs/command/commands/ToggleCommand.java deleted file mode 100644 index c04a575..0000000 --- a/src/com/rifledluffy/chairs/command/commands/ToggleCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.rifledluffy.chairs.command.commands; - -import java.util.List; -import java.util.UUID; - -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; - -import com.rifledluffy.chairs.MessageManager; -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; -import com.rifledluffy.chairs.utility.Util; - -public class ToggleCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("�cOnly players can use commands for this plugin."); - } - - @Override - public void onCommand(Player player, String[] args) { - MessageManager messageManager = plugin.messageManager; - List toggled = plugin.chairManager.toggled; - String message; - if (!player.hasPermission("rfchairs.toggle")) return; - if (toggled.contains(player.getUniqueId())) { - String string = messageManager.messages.getString("toggle-message-enabled", "&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); - toggled.remove(player.getUniqueId()); - } - else { - String string = messageManager.messages.getString("toggle-message-disabled", "&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); - toggled.add(player.getUniqueId()); - } - } - - @Override - public String name() { - return plugin.commandManager.toggle; - } - - @Override - public String info() { - return ""; - } - - @Override - public String[] aliases() { - return new String[0]; - } - -} diff --git a/src/com/rifledluffy/chairs/config/ConfigManager.java b/src/com/rifledluffy/chairs/config/ConfigManager.java deleted file mode 100644 index f3b269c..0000000 --- a/src/com/rifledluffy/chairs/config/ConfigManager.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.rifledluffy.chairs.config; - -import java.io.File; -import java.io.IOException; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.java.JavaPlugin; - -import com.rifledluffy.chairs.RFChairs; - -public class ConfigManager { - - private JavaPlugin plugin = RFChairs.getPlugin(RFChairs.class); - - /* - * Configuration Files - */ - - FileConfiguration config; - File configFile; - - FileConfiguration fake; - File fakeFile; - - FileConfiguration message; - File messageFile; - - public void setup() throws IOException { - configFile = new File(plugin.getDataFolder(), "config.yml"); - config = plugin.getConfig(); - config.options().copyDefaults(true); - saveConfig(); - - if (!plugin.getDataFolder().exists()) { - plugin.getDataFolder().mkdir(); - } - - fakeFile = new File(plugin.getDataFolder(), "fakes.yml"); - - if (!fakeFile.exists()) { - try { - fakeFile.createNewFile(); - } - catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not create fakes.yml!"); - } - } - - messageFile = new File(plugin.getDataFolder(), "messages.yml"); - - if (!messageFile.exists()) { - messageFile.getParentFile().mkdirs(); - plugin.saveResource("messages.yml", false); - } - - fake = YamlConfiguration.loadConfiguration(fakeFile); - message = YamlConfiguration.loadConfiguration(messageFile); - } - - public FileConfiguration getData() { - return fake; - } - - public void saveData() { - try { - fake.save(fakeFile); - } - catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not save fakes.yml!"); - } - } - - public void reloadData() { - fake = YamlConfiguration.loadConfiguration(fakeFile); - } - - public FileConfiguration getMessages() { - return message; - } - - public void saveMessages() { - try { - message.save(messageFile); - } - catch (IOException e) { - plugin.getLogger().info("[Rifle's Chairs] Could not save messages.yml!"); - } - } - - public void reloadMessages() { - message = YamlConfiguration.loadConfiguration(messageFile); - } - - public FileConfiguration getConfig() { - return config; - } - - public void saveConfig() { - try { - config.save(configFile); - } - catch (IOException e) { - plugin.getLogger().info("[Rifle's Chairs] Could not save config.yml!"); - } - } - - public void reloadConfig() { - config = YamlConfiguration.loadConfiguration(configFile); - } - - public PluginDescriptionFile getDesc() { - return plugin.getDescription(); - } -} \ No newline at end of file diff --git a/src/com/rifledluffy/chairs/events/ChairCheckEvent.java b/src/com/rifledluffy/chairs/events/ChairCheckEvent.java deleted file mode 100644 index f04aa60..0000000 --- a/src/com/rifledluffy/chairs/events/ChairCheckEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.rifledluffy.chairs.events; - -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.rifledluffy.chairs.chairs.Chair; - -public class ChairCheckEvent extends Event { - - Chair chair; - Block block; - Player player; - - public ChairCheckEvent(Chair chair, Player player) { - this.chair = chair; - this.player = player; - } - - public ChairCheckEvent(Block block, Player player) { - this.block = block; - this.player = player; - } - - public Chair getChair() { - return this.chair; - } - - public Block getBlock() { - return this.block; - } - - public Player getPlayer() { - return this.player; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/rifledluffy/chairs/events/ChairLeaveEvent.java b/src/com/rifledluffy/chairs/events/ChairLeaveEvent.java deleted file mode 100644 index 720220b..0000000 --- a/src/com/rifledluffy/chairs/events/ChairLeaveEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.rifledluffy.chairs.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.rifledluffy.chairs.chairs.Chair; - -public class ChairLeaveEvent extends Event { - - private Chair chair; - private Player player; - private boolean exitWhereFacing = false; - - public ChairLeaveEvent(Chair chair, Player player, boolean flag) { - this.chair = chair; - this.player = player; - this.exitWhereFacing = flag; - } - - public ChairLeaveEvent(Chair chair, Player player) { - this.chair = chair; - this.player = player; - } - - public Chair getChair() { - return this.chair; - } - - public Player getPlayer() { - return this.player; - } - - public boolean exitWhereFacing() { - return this.exitWhereFacing; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/rifledluffy/chairs/events/ChairReplaceEvent.java b/src/com/rifledluffy/chairs/events/ChairReplaceEvent.java deleted file mode 100644 index bc344fe..0000000 --- a/src/com/rifledluffy/chairs/events/ChairReplaceEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.rifledluffy.chairs.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.rifledluffy.chairs.chairs.Chair; - -public class ChairReplaceEvent extends Event { - - Chair chair; - Player replaced; - Player player; - - public ChairReplaceEvent(Chair chair, Player replaced, Player player) { - this.chair = chair; - this.replaced = replaced; - this.player = player; - } - - public Chair getChair() { - return this.chair; - } - - public Player getReplaced() { - return this.replaced; - } - - public Player getPlayer() { - return this.player; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/rifledluffy/chairs/events/ChairSitEvent.java b/src/com/rifledluffy/chairs/events/ChairSitEvent.java deleted file mode 100644 index 9266bc7..0000000 --- a/src/com/rifledluffy/chairs/events/ChairSitEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.rifledluffy.chairs.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.rifledluffy.chairs.chairs.Chair; - -public class ChairSitEvent extends Event { - - Chair chair; - Player player; - - public ChairSitEvent(Chair chair, Player player) { - this.chair = chair; - this.player = player; - } - - public Chair getChair() { - return this.chair; - } - - public Player getPlayer() { - return this.player; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/rifledluffy/chairs/events/ChairTossEvent.java b/src/com/rifledluffy/chairs/events/ChairTossEvent.java deleted file mode 100644 index 0631297..0000000 --- a/src/com/rifledluffy/chairs/events/ChairTossEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.rifledluffy.chairs.events; - -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.rifledluffy.chairs.TargetInfo; -import com.rifledluffy.chairs.chairs.Chair; - -public class ChairTossEvent extends Event { - - Chair chair; - Player player; - Entity attacker; - TargetInfo info; - boolean silent; - - public ChairTossEvent(Chair chair, Player player, Entity attacker, TargetInfo info, boolean flag) { - this.chair = chair; - this.player = player; - this.attacker = attacker; - this.info = info; - this.silent = flag; - } - - public Chair getChair() { - return this.chair; - } - - public Player getPlayer() { - return this.player; - } - - public Entity getAttacker() { - return this.attacker; - } - - public TargetInfo getInfo() { - return this.info; - } - - public boolean isSilent() { - return this.silent; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/rifledluffy/chairs/managers/GriefPreventionManager.java b/src/com/rifledluffy/chairs/managers/GriefPreventionManager.java deleted file mode 100644 index 415af47..0000000 --- a/src/com/rifledluffy/chairs/managers/GriefPreventionManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.rifledluffy.chairs.managers; - -import me.ryanhamshire.GriefPrevention.Claim; -import me.ryanhamshire.GriefPrevention.GriefPrevention; -import org.bukkit.Location; - -import java.util.HashMap; -import java.util.Map; - -public class GriefPreventionManager { - - private GriefPrevention instance; - - public GriefPreventionManager() {} - - public void setup() { - instance = GriefPrevention.instance; - } - - public boolean isAdminClaim(Location location) { - if (location == null) return false; - if (instance.dataStore == null) return false; - Claim claim = instance.dataStore.getClaimAt(location, true, null); - return claim.isAdminClaim(); - } - -} diff --git a/src/com/rifledluffy/chairs/managers/PlotSquaredManager.java b/src/com/rifledluffy/chairs/managers/PlotSquaredManager.java deleted file mode 100644 index 4f2050f..0000000 --- a/src/com/rifledluffy/chairs/managers/PlotSquaredManager.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.rifledluffy.chairs.managers; - -import com.github.intellectualsites.plotsquared.api.PlotAPI; -import com.github.intellectualsites.plotsquared.plot.flag.BooleanFlag; -import com.rifledluffy.chairs.chairs.Chair; -import com.github.intellectualsites.plotsquared.plot.object.Location; - -public class PlotSquaredManager { - - private PlotAPI api; - private BooleanFlag seating = new BooleanFlag("seating"); - - public PlotSquaredManager() {} - - public void setup() { - api = new PlotAPI(); - api.addFlag(seating); - } - - public boolean canSit(Chair chair) { - org.bukkit.Location location = chair.getLocation(); - Location loc = new Location(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); - - return api.getAllPlots().stream() - .filter(plot -> plot.getArea().contains(loc)) - .noneMatch(plot -> plot.getFlag(seating).orElse(true)); - } - -} diff --git a/src/com/rifledluffy/chairs/managers/WorldGuardManager.java b/src/com/rifledluffy/chairs/managers/WorldGuardManager.java deleted file mode 100644 index fb0e90f..0000000 --- a/src/com/rifledluffy/chairs/managers/WorldGuardManager.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.rifledluffy.chairs.managers; - -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.chairs.Chair; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.WorldGuard; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.Flag; -import com.sk89q.worldguard.protection.flags.StateFlag; -import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; -import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; -import com.sk89q.worldguard.protection.regions.RegionContainer; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; - -import java.util.List; -import java.util.stream.Collectors; - -public class WorldGuardManager { - - private RFChairs plugin = RFChairs.getInstance(); - public WorldGuard worldGuard; - public WorldGuardPlugin worldGuardPlugin; - public RegionContainer container; - @SuppressWarnings("rawtypes") - public static Flag flag; - - public WorldGuardManager() {} - - public void setup() { - worldGuard = WorldGuard.getInstance(); - } - - public void register() { - flag = new StateFlag("allow-seating", true); - FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry(); - try { - registry.register(flag); - plugin.log("Custom Flag Registered!"); - } catch (FlagConflictException e) { - plugin.log("Unable to register custom worldguard flag!"); - } - } - - public WorldGuardPlugin getWorldGuard() { - Plugin plugin = this.plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - - if (!(plugin instanceof WorldGuardPlugin)) return null; - return (WorldGuardPlugin) plugin; - } - - public boolean validateSeating(Chair chair, Player player) { - double xPos = chair.getLocation().getX(); - double yPos = chair.getLocation().getY(); - double zPos = chair.getLocation().getZ(); - - WorldGuardManager worldManager = plugin.getWorldGuardManager(); - - LocalPlayer localPlayer = worldManager.getWorldGuard().wrapPlayer(player); - - BlockVector3 vector3 = BlockVector3.at(xPos, yPos, zPos); - - List regionSetList = getContainer().getLoaded().stream() - .map(manager -> manager.getApplicableRegions(vector3)) - .collect(Collectors.toList()); - - if (regionSetList.size() == 0) return true; - - return regionSetList.stream() - .allMatch(set -> set.testState(localPlayer, (StateFlag) worldManager.getFlag())); - } - - public RegionContainer getContainer() { - return worldGuard.getPlatform().getRegionContainer(); - } - - public Flag getFlag() { - return flag; - } - -} diff --git a/src/com/rifledluffy/chairs/messages/MessageEvent.java b/src/com/rifledluffy/chairs/messages/MessageEvent.java deleted file mode 100644 index dab2391..0000000 --- a/src/com/rifledluffy/chairs/messages/MessageEvent.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.rifledluffy.chairs.messages; - -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class MessageEvent extends Event implements Cancellable { - - boolean cancelled; - - MessageType type; - MessageConstruct construct; - Player player; - Entity other; - - public MessageEvent(MessageType type, MessageConstruct construct, Player player, Player other) { - this.type = type; - this.construct = construct; - this.player = player; - this.other = other; - } - - public MessageEvent(MessageType type, Player player, Entity other) { - this.type = type; - this.construct = MessageConstruct.DEFENSIVE; - this.player = player; - this.other = other; - } - - public MessageEvent(MessageType type, Player player) { - this.type = type; - this.construct = MessageConstruct.SINGLE; - this.player = player; - this.other = null; - } - - public MessageType getType() { - return this.type; - } - - public MessageConstruct getConstruct() { - return this.construct; - } - - public Player getPlayer() { - return this.player; - } - - public Entity getEntity() { - return this.other; - } - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - static public HandlerList getHandlerList() { - return handlers; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } -} diff --git a/src/com/rifledluffy/chairs/messages/MessageType.java b/src/com/rifledluffy/chairs/messages/MessageType.java deleted file mode 100644 index 18c82f4..0000000 --- a/src/com/rifledluffy/chairs/messages/MessageType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.rifledluffy.chairs.messages; - -public enum MessageType { - - OCCUPIED,TOOFAR,NOPERMS,TOOMANYITEMS,TOSSED,TOSSEDSPEED,TOSSING,TOSSINGSPEED,PRIORITYTOSS,NOSIGNS,WORLDGUARD,PLOTSQUARED - -} diff --git a/src/com/rifledluffy/chairs/messages/Messages.java b/src/com/rifledluffy/chairs/messages/Messages.java deleted file mode 100644 index 362679c..0000000 --- a/src/com/rifledluffy/chairs/messages/Messages.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.rifledluffy.chairs.messages; - -public class Messages { - - private final static String occupied = "occupied-seat"; - private final static String tooFar = "too-far-from-seat"; - private final static String noPerms = "no-permission"; - private final static String tooMany = "too-many-items"; - private final static String tossed = "tossed-out-of-chair"; - private final static String tossedSpeed = "tossed-out-with-speed"; - private final static String tossing = "tossing-someone"; - private final static String tossingSpeed = "tossing-someone-with-speed"; - private final static String priority = "priority-replaced"; - private final static String noSigns = "no-sign-at-ends"; - private final static String worldGuard = "denied-by-worldguard"; - private final static String plotSquared = "denied-by-plotsquared"; - - private final static String defaultOccupied = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&a, my homie &7%seated%&c sits there."; - private final static String defaultTooFar = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!"; - private final static String defaultNoPerms = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!"; - private final static String defaultTooMany = "&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!"; - private final static String defaultTossed = "&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%."; - private final static String defaultTossedSpeed = "&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%."; - private final static String defaultTossing = "&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!"; - private final static String defaultTossingSpeed = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!"; - private final static String defaultPriority = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%"; - private final static String defaultNoSigns = "&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!"; - private final static String defaultWorldGuard = "&8[&6Rifle's Chairs&8] &cYou may not sit in this region!"; - private final static String defaultPlotSquared = "&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!"; - - public static String getDefault(MessageType type) { - switch (type) { - default: - return null; - case OCCUPIED: - return Messages.defaultOccupied; - case TOOFAR: - return Messages.defaultTooFar; - case NOPERMS: - return Messages.defaultNoPerms; - case TOOMANYITEMS: - return Messages.defaultTooMany; - case TOSSED: - return Messages.defaultTossed; - case TOSSEDSPEED: - return Messages.defaultTossedSpeed; - case TOSSING: - return Messages.defaultTossing; - case TOSSINGSPEED: - return Messages.defaultTossingSpeed; - case PRIORITYTOSS: - return Messages.defaultPriority; - case NOSIGNS: - return Messages.defaultNoSigns; - case WORLDGUARD: - return Messages.defaultWorldGuard; - case PLOTSQUARED: - return Messages.defaultPlotSquared; - } - } - - public static String getMessage(MessageType type) { - switch (type) { - default: - return null; - case OCCUPIED: - return Messages.occupied; - case TOOFAR: - return Messages.tooFar; - case NOPERMS: - return Messages.noPerms; - case TOOMANYITEMS: - return Messages.tooMany; - case TOSSED: - return Messages.tossed; - case TOSSEDSPEED: - return Messages.tossedSpeed; - case TOSSING: - return Messages.tossing; - case TOSSINGSPEED: - return Messages.tossingSpeed; - case PRIORITYTOSS: - return Messages.priority; - case NOSIGNS: - return Messages.noSigns; - case WORLDGUARD: - return Messages.worldGuard; - case PLOTSQUARED: - return Messages.plotSquared; - } - } -} diff --git a/src/com/rifledluffy/chairs/utility/Util.java b/src/com/rifledluffy/chairs/utility/Util.java deleted file mode 100644 index d0c03e3..0000000 --- a/src/com/rifledluffy/chairs/utility/Util.java +++ /dev/null @@ -1,316 +0,0 @@ -package com.rifledluffy.chairs.utility; - -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.chairs.BlockFilter; -import com.rifledluffy.chairs.chairs.Chair; -import com.rifledluffy.chairs.config.ConfigManager; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Bisected; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Levelled; -import org.bukkit.block.data.type.Slab; -import org.bukkit.block.data.type.Stairs; -import org.bukkit.block.data.type.TrapDoor; -import org.bukkit.block.data.type.WallSign; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public class Util { - - private static RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private static ConfigManager configManager = plugin.getConfigManager(); - - public static ConfigManager getConfigManager() { - return configManager; - } - - public static void debug(String message) { - for (Player player : plugin.getServer().getOnlinePlayers()) player.sendMessage(message); - } - - public static void debug(Object message) { - debug(message.toString()); - } - - public static void debug(List messages) { - messages.forEach(Util::debug); - } - - public static String replaceMessage(Player player, String string) { - string = ChatColor.translateAlternateColorCodes('&',string); - string = string.replace("%user%", player.getDisplayName()); - return string; - } - - public static String replaceMessage(Entity entity, Player target, String string) { - if (entity instanceof LivingEntity) return replaceMessage((LivingEntity)entity, target, string); - - string = ChatColor.translateAlternateColorCodes('&',string); - string = string.replace("%user%", entity.getName()); - string = string.replace("%seated%", target.getName()); - return string; - } - - public static String replaceMessage(LivingEntity entity, Player target, String string) { - if (entity instanceof Player) return replaceMessage((Player)entity, target, string); - - string = ChatColor.translateAlternateColorCodes('&',string); - string = string.replace("%user%", entity.getName()); - string = string.replace("%seated%", target.getName()); - return string; - } - - public static String replaceMessage(Player player, Player target, String string) { - string = ChatColor.translateAlternateColorCodes('&',string); - string = string.replace("%user%", player.getDisplayName()); - string = string.replace("%seated%", target.getName()); - return string; - } - - public static boolean validStair(Block block) { - if (!BlockFilter.validateStairs(block.getType())) return false; - Stairs stair = (Stairs) block.getState().getBlockData(); - return stair.getHalf() != Bisected.Half.TOP; - } - - public static boolean validSlab(Block block) { - if (!BlockFilter.validateSlab(block.getType())) return false; - Slab slab = (Slab) block.getState().getBlockData(); - return slab.getType() == Slab.Type.BOTTOM; - } - - public static boolean validCarpet(Block block) { - return BlockFilter.validateCarpet(block.getType()); - } - - private static boolean validatedChair(Block block) { - return BlockFilter.isStairsBlock(block.getType()) && validStair(block); - } - - public static boolean playerIsSeated(UUID uuid, Map chairMap) { - Chair chair = chairMap.get(uuid); - return chair != null; - } - - public static boolean nearLiquid(Block block) { - return isLiqiudOrMagma(block.getRelative(BlockFace.NORTH)) - || isLiqiudOrMagma(block.getRelative(BlockFace.EAST)) - || isLiqiudOrMagma(block.getRelative(BlockFace.SOUTH)) - || isLiqiudOrMagma(block.getRelative(BlockFace.WEST)); - } - - public static boolean surroundedBlock(Block block) { - return !validExit(block.getRelative(BlockFace.NORTH)) - && !validExit(block.getRelative(BlockFace.EAST)) - && !validExit(block.getRelative(BlockFace.SOUTH)) - && !validExit(block.getRelative(BlockFace.WEST)); - } - - private static boolean validExit(Block block) { - Material type = block.getType(); - return type == Material.AIR || type.name().equals("WALL_SIGN") || type.name().endsWith("_WALL_SIGN"); - } - - public static boolean isLiqiudOrMagma(Block block) { - return block.getBlockData() instanceof Levelled || block.getRelative(BlockFace.DOWN).getType() == Material.MAGMA_BLOCK; - } - - public static boolean validCouch(Block block) { - int validSides = 0; - if (!validatedChair(block)) return false; - Stairs stair = (Stairs) block.getState().getBlockData(); - - Set blockFaces = stair.getFaces(); - List faces = new ArrayList(blockFaces); - faces.remove(stair.getFacing()); - faces.remove(stair.getFacing().getOppositeFace()); - faces.remove(BlockFace.DOWN); - faces.remove(BlockFace.UP); - - BlockFace side = faces.get(0); - BlockFace otherSide = faces.get(1); - - if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return false; - - if (validatedChair(block.getRelative(side))) if (validSeat(block.getRelative(side), side, block)) validSides++; - if (validatedChair(block.getRelative(otherSide))) if (validSeat(block.getRelative(otherSide), otherSide, block)) validSides++; - - if (!validatedChair(block.getRelative(side))) if (validSeat(block, side, block)) validSides++; - if (!validatedChair(block.getRelative(otherSide))) if (validSeat(block, otherSide, block)) validSides++; - return validSides == 2; - } - - public static boolean validSeat(Block block, BlockFace side, Block original) { - Stairs stair = (Stairs) block.getState().getBlockData(); - Stairs first = (Stairs) original.getState().getBlockData(); - if (stair.getFacing() != first.getFacing()) return false; - if (block.getRelative(side).getBlockData() instanceof WallSign || block.getRelative(side).getBlockData() instanceof TrapDoor) { - Directional sign =((Directional)block.getRelative(side).getBlockData()); - return sign.getFacing() == side; - } - else if (validatedChair(block.getRelative(side))) return validSeat(block.getRelative(side), side, original); - return false; - } - - public static boolean sameSeat(Player player, Block block, Map chairMap) { - Chair chair = chairMap.get(player.getUniqueId()); - if (chair == null) return false; - return chair.getLocation().equals(block.getLocation()); - } - - public static boolean samePosition(Block block, Block target) { - return block.getX() == target.getX() && block.getY() == target.getY() && block.getZ() == target.getZ(); - } - - public static boolean throneChair(Block block) { - if (!(block.getBlockData() instanceof Stairs)) return false; - if (block.getRelative(BlockFace.UP).getBlockData() instanceof TrapDoor) { - TrapDoor trapDoor = (TrapDoor) block.getRelative(BlockFace.UP).getBlockData(); - if (!trapDoor.isOpen()) return false; - return trapDoor.getFacing().getOppositeFace() == ((Stairs) block.getBlockData()).getFacing(); - } - return false; - } - - public static boolean blockIsChair(Block block, List chairs) { - for (Chair chair: chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; - if (samePosition(block, chair.getBlock())) return true; - } - return false; - } - - public static Chair getChairFromBlock(Block block, List chairs) { - for (Chair chair : chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; - if (samePosition(chair.getBlock(), block)) return chair; - } - return null; - } - - public static ArmorStand generateFakeSeat(Chair chair) { - if (chair == null) return null; - Vector seatingPosition = new Vector(0.5,0.3D,0.5); - Location seat = chair.getLocation(); - BlockFace facing = null; - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) facing = ((Stairs)chair.getBlock().getState().getBlockData()).getFacing(); - Location playerLoc = chair.getPlayer().getEyeLocation(); - playerLoc.setPitch(0); - Vector vector; - if (facing != null) vector = getVectorFromFace(chair.getBlock(), facing.getOppositeFace()); - else vector = getVectorFromNearBlock(chair.getBlock(), playerLoc.getBlock()); - - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.stairSeatingPosition; - if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.carpetSeatingPosition; - if (BlockFilter.isSlabBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.slabSeatingPosition; - - //Thank you VicenteRD and carlpoole! - return seat.getWorld().spawn( - seat.clone().add(seatingPosition).setDirection(vector), - ArmorStand.class, - stand -> { - stand.setVisible(false); - stand.setGravity(false); - stand.setInvulnerable(true); - stand.setMarker(true); - stand.setCollidable(false); - }); - } - - public static ArmorStand generateFakeSeatDir(Chair chair, Vector dir) { - if (chair == null) return null; - Vector seatingPosition = new Vector(0.5,0.3D,0.5); - Location seat = chair.getLocation(); - Location playerLoc = chair.getPlayer().getEyeLocation(); - playerLoc.setPitch(0); - - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.stairSeatingPosition; - if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.carpetSeatingPosition; - if (BlockFilter.isSlabBlock(chair.getBlock().getType())) seatingPosition = plugin.chairManager.slabSeatingPosition; - - //Thank you VicenteRD and carlpoole! - return seat.getWorld().spawn( - seat.clone().add(seatingPosition).setDirection(dir), - ArmorStand.class, - stand -> { - stand.setVisible(false); - stand.setGravity(false); - stand.setInvulnerable(true); - stand.setMarker(true); - stand.setCollidable(false); - }); - } - - public static float getAbsoluteAngle(Location loc) { - float y = loc.getYaw(); - if (y < 0) y += 360; - y %= 360; - if (y <= 45 || y >= 315) return 0; - if (y >= 45 && y <= 135) return 90; - if (y >= 135 && y <= 225) return 180; - return 270; - } - - public static String getCardinalDirection(Location loc) { - float y = loc.getYaw(); - if (y < 0) y += 360; - y %= 360; - if (y <= 45 || y >= 315) return "south"; - if (y >= 45 && y <= 135) return "west"; - if (y >= 135 && y <= 225) return "north"; - return "east"; - } - - public static Block getBlockFromDirection(Block block, String direction) { - if (direction.equalsIgnoreCase("north")) return block.getRelative(BlockFace.NORTH); - else if (direction.equalsIgnoreCase("west")) return block.getRelative(BlockFace.WEST); - else if (direction.equalsIgnoreCase("east")) return block.getRelative(BlockFace.EAST); - else if (direction.equalsIgnoreCase("south")) return block.getRelative(BlockFace.SOUTH); - else if (direction.equalsIgnoreCase("down")) return block.getRelative(BlockFace.DOWN); - else if (direction.equalsIgnoreCase("up")) return block.getRelative(BlockFace.UP); - return block; - } - - public static boolean canFitPlayer(Block block) { - return block.getType() == Material.AIR && block.getRelative(BlockFace.UP).getType() == Material.AIR; - } - - public static boolean safePlace(Block block) { - return block.getRelative(BlockFace.DOWN).getType() != Material.AIR; - } - - public static Vector getVectorDir(Location caster, Location target) { - return target.clone().subtract(caster.toVector()).toVector(); - } - - public static Vector getVectorFromFace(Block block, BlockFace face) { - Location blockLoc = block.getLocation(); - Location faceLoc = block.getRelative(face).getLocation(); - return getVectorDir(blockLoc, faceLoc); - } - - public static Vector getVectorFromNearBlock(Block block, Block target) { - return target.getLocation().toVector().subtract(block.getLocation().toVector()); - } - - public static void callEvent(Event event) { - plugin.getServer().getPluginManager().callEvent(event); - } - -} diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java new file mode 100644 index 0000000..bb695dc --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -0,0 +1,599 @@ +package com.rifledluffy.chairs; + +import com.rifledluffy.chairs.chairs.BlockFilter; +import com.rifledluffy.chairs.chairs.Chair; +import com.rifledluffy.chairs.config.ConfigManager; +import com.rifledluffy.chairs.events.*; +import com.rifledluffy.chairs.messages.MessageConstruct; +import com.rifledluffy.chairs.messages.MessageEvent; +import com.rifledluffy.chairs.messages.MessageType; +import com.rifledluffy.chairs.utility.Util; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerGameModeChangeEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.projectiles.ProjectileSource; +import org.bukkit.util.Vector; +import org.spigotmc.event.entity.EntityDismountEvent; + +import java.util.*; +import java.util.stream.Collectors; + +public class ChairManager implements Listener { + private final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); + private final Map chairMap = new HashMap<>(); + private final List fakeSeats = new ArrayList<>(); + private final List leaving = new ArrayList<>(); + private final List orienting = new ArrayList<>(); + private final Map tossed = new HashMap<>(); + public List chairs = new ArrayList<>(); + public List toggled = new ArrayList<>(); + public Vector stairSeatingPosition; + public Vector slabSeatingPosition; + public Vector carpetSeatingPosition; + private ConfigManager configManager = plugin.getConfigManager(); + private FileConfiguration config = configManager.getConfig(); + private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); + private boolean regenWhenSitting; + //Update related + private boolean disableCurrentUpdate; + private boolean disableUpdates; + //Kick them off their seat if they take damage + private boolean canLaunch; + //Toss them off their seat if they take damage + private boolean canToss; + //The minimum damage needed for a player to be tossed + private double minDamage; + //Toss Configuration + private boolean faceAttacker; + private double tossVelocity; + private boolean scaleVelocity; + private double scaleAmount; + //Maximum amount of items on hand that they can have when trying to sit + private int maxItemSit; + private double maxDistance; + private boolean checkForSigns; + private boolean priorityIfHasPerm; + private boolean trapSeats; + private boolean requireEmptyHand; + //Mostly buggy, probably going to remove soon. + private boolean exitWhereFacing; + private List disabledWorlds = new ArrayList<>(); + + public void reload(RFChairs plugin) { + configManager = plugin.getConfigManager(); + config = configManager.getConfig(); + + regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); + regenWhenSitting = config.getBoolean("regen-when-sitting", true); + + disableCurrentUpdate = config.getBoolean("disable-update-message-if-on-latest", false); + disableUpdates = config.getBoolean("disable-update-messages", false); + + faceAttacker = config.getBoolean("face-attacker-when-ejected", false); + canToss = config.getBoolean("toss-player", false); + tossVelocity = config.getDouble("toss-velocity", 0.5D); + scaleVelocity = config.getBoolean("scale-toss-velocity", true); + scaleAmount = config.getDouble("velocity-scale-factor", 2D); + canLaunch = config.getBoolean("eject-player-on-damage", true); + minDamage = config.getDouble("minimum-eject-damage", 2D); + exitWhereFacing = config.getBoolean("exit-seat-where-facing", false); + maxItemSit = config.getInt("max-item-count-to-sit", -1); + maxDistance = config.getDouble("max-distance", 2D); + checkForSigns = config.getBoolean("require-signs-at-end", false); + priorityIfHasPerm = config.getBoolean("priority-on-if-has-perm", true); + trapSeats = config.getBoolean("allow-trap-door-chairs", true); + requireEmptyHand = config.getBoolean("require-empty-hand", false); + + try { + String[] vectorString = Objects.requireNonNull(config.getString("stair-seating-position", "0.5,0.3,0.5")).split(","); + stairSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); + } catch (NumberFormatException e) { + stairSeatingPosition = new Vector(0.5D, 0.3D, 0.5); + } + + try { + String[] vectorString = Objects.requireNonNull(config.getString("slab-seating-position", "0.5,0.3,0.5")).split(","); + slabSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); + } catch (NumberFormatException e) { + slabSeatingPosition = new Vector(0.5, 0.3D, 0.5); + } + + try { + String[] vectorString = Objects.requireNonNull(config.getString("carpet-seating-position", "0.5,-0.15,0.5")).split(","); + carpetSeatingPosition = new Vector(Double.parseDouble(vectorString[0]), Double.parseDouble(vectorString[1]), Double.parseDouble(vectorString[2])); + } catch (NumberFormatException e) { + carpetSeatingPosition = new Vector(0.5, -0.15D, 0.5); + } + + disabledWorlds = config.getStringList("disabled-worlds").stream() + .map(Bukkit::getWorld) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + @EventHandler + public void onChairSit(ChairSitEvent event) { + Chair chair = event.getChair(); + if (chair == null) return; + if (chair.getLocation() == null) return; + if (event.getPlayer() == null) return; + + if (plugin.hasWorldGuard()) if (!plugin.getWorldGuardManager().validateSeating(chair, event.getPlayer())) { + Util.callEvent(new MessageEvent(MessageType.WORLDGUARD, event.getPlayer())); + return; + } + + Player player = event.getPlayer(); + + if (Util.playerIsSeated(player.getUniqueId(), chairMap)) clearPlayer(player); + boolean done = sitPlayer(chair, player); + if (!done) return; + chairs.add(chair); + chairMap.put(player.getUniqueId(), chair); + if (regenWhenSitting) player.addPotionEffect(regenEffect); + } + + @EventHandler + public void onChairLeave(ChairLeaveEvent event) { + Chair chair = event.getChair(); + if (chair == null) return; + if (chair.getLocation() == null) return; + + Block block = chair.getLocation().getBlock(); + Player player = event.getPlayer(); + boolean flag = event.exitWhereFacing(); + + Location exit = block.getLocation(); + + clearPlayer(player); + player.removePotionEffect(PotionEffectType.REGENERATION); + if (flag) exit = findExitPoint(player.getLocation(), block).getLocation(); + if (Util.surroundedBlock(block) || Util.nearLiquid(player.getLocation().getBlock())) + exit = block.getRelative(BlockFace.UP).getLocation(); + exit.setDirection(player.getEyeLocation().getDirection()); + exit.add(0.5, 0, 0.5); + player.teleport(exit); + if (!flag) { + Vector v = player.getEyeLocation().getDirection(); + v.setY(0); + v.normalize(); + v.setY(1); + player.setVelocity(v.multiply(0.25)); + } + } + + @EventHandler + public void onToss(ChairTossEvent event) { + Chair chair = event.getChair(); + if (chair == null) return; + if (chair.getLocation() == null) return; + + Block block = chair.getBlock(); + Player player = event.getPlayer(); + Entity attacker = event.getAttacker(); + TargetInfo info = event.getInfo(); + boolean silent = event.isSilent(); + + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, false); + Util.callEvent(leaveEvent); + + if (!silent) { + MessageEvent messageEvent; + MessageEvent otherEvent = null; + if (attacker instanceof Player playerEntity) { + if (info != null && !info.isSprinting()) + messageEvent = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, player, playerEntity); + else + messageEvent = new MessageEvent(MessageType.TOSSEDSPEED, MessageConstruct.DEFENSIVE, player, playerEntity); + + if (info != null && !info.isSprinting()) + otherEvent = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, playerEntity, player); + else + otherEvent = new MessageEvent(MessageType.TOSSINGSPEED, MessageConstruct.OFFENSIVE, playerEntity, player); + } else messageEvent = new MessageEvent(MessageType.TOSSED, player, attacker); + Util.callEvent(messageEvent); + if (otherEvent != null) Util.callEvent(otherEvent); + } + + if (canToss) ejectPlayer(block, player, attacker); + } + + @EventHandler + public void onChairReplace(ChairReplaceEvent event) { + Chair chair = event.getChair(); + if (chair == null) return; + if (chair.getLocation() == null) return; + + Block block = chair.getBlock(); + Player player = event.getPlayer(); + Player seated = event.getReplaced(); + + if (player.getUniqueId() == seated.getUniqueId()) return; + + ChairTossEvent tossEvent = new ChairTossEvent(chair, seated, player, null, true); + Util.callEvent(tossEvent); + + MessageEvent tossed = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, seated, player); + Util.callEvent(tossed); + + ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); + Util.callEvent(sitEvent); + + MessageEvent tosser = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, player, seated); + Util.callEvent(tosser); + } + + @EventHandler + public void onChairCheck(ChairCheckEvent event) { + Player player = event.getPlayer(); + ItemStack item = player.getInventory().getItemInMainHand(); + Block block = event.getBlock(); + + if (!player.hasPermission("rfchairs.use")) { + Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); + return; + } + + if (player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) >= maxDistance) { + Util.callEvent(new MessageEvent(MessageType.TOOFAR, player)); + return; + } + + if (maxItemSit > 0 && item.getAmount() > maxItemSit) { + Util.callEvent(new MessageEvent(MessageType.TOOMANYITEMS, player)); + return; + } + + if (!Util.blockIsChair(block, chairs)) { + ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); + Util.callEvent(sitEvent); + } else { + Chair chair = Util.getChairFromBlock(block, chairs); + if (chair == null) return; + if (chair.getFakeSeat() != null && chair.getFakeSeat().getPassengers().size() == 0) { + chair.setPlayer(player); + chair.getFakeSeat().addPassenger(player); + if (regenWhenSitting) player.addPotionEffect(regenEffect); + return; + } + if (player.hasPermission("rfchairs.priority") && priorityIfHasPerm) { + ChairReplaceEvent replaceEvent = new ChairReplaceEvent(chair, chair.getPlayer(), player); + Util.callEvent(replaceEvent); + return; + } + if (chair.getPlayer() == null) return; + if (player.getUniqueId().equals(chair.getPlayer().getUniqueId())) { + orienting.add(player.getUniqueId()); + Location loc = chair.getFakeSeat().getLocation(); + loc.setDirection(player.getEyeLocation().getDirection().setY(0)); + chair.getFakeSeat().remove(); + ArmorStand newFakeSeat = Util.generateFakeSeatDir(chair, loc.getDirection()); + chair.setFakeSeat(newFakeSeat); + chair.getFakeSeat().addPassenger(player); + } else { + MessageEvent occupied = new MessageEvent(MessageType.OCCUPIED, MessageConstruct.OFFENSIVE, player, chair.getPlayer()); + Util.callEvent(occupied); + } + } + } + + @EventHandler + public void onRightClick(PlayerInteractEvent event) { + if (disabledWorlds.size() > 0 && disabledWorlds.contains(event.getPlayer().getWorld())) return; + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getPlayer().isSneaking()) return; + if (event.getHand() != EquipmentSlot.HAND) return; + if (toggled.contains(event.getPlayer().getUniqueId())) return; + + Block block = event.getClickedBlock(); + Player player = event.getPlayer(); + ItemStack item = event.getItem(); + if (block == null) return; + + if (requireEmptyHand && item != null) return; + + if (item != null && item.getType() != Material.AIR) { + if (item.getType().isBlock()) return; + } + + if (!BlockFilter.isStairsBlock(block.getType()) + && !BlockFilter.isCarpetBlock(block.getType()) + && !BlockFilter.isSlabBlock(block.getType())) return; + + if (BlockFilter.isStairsBlock(block.getType())) { + if (!Util.validStair(block)) return; + else { + if (checkForSigns) { + if (!Util.validCouch(block)) { + if (!trapSeats) return; + if (!Util.throneChair(block)) { + Util.callEvent(new MessageEvent(MessageType.NOSIGNS, player)); + return; + } + } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; + } + if (trapSeats && block.getRelative(BlockFace.UP).getType() != Material.AIR) { + if (!Util.throneChair(block)) return; + } + } + } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; + + if (BlockFilter.isSlabBlock(block.getType())) if (!Util.validSlab(block)) return; + + if (BlockFilter.isCarpetBlock(block.getType())) if (!Util.validCarpet(block)) return; + + if (event.getBlockFace() == BlockFace.DOWN) return; + + if (!player.hasPermission("rfchairs.use")) { + Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); + return; + } + + Util.callEvent(new ChairCheckEvent(block, player)); + } + + @EventHandler + public void onChangeGameMode(PlayerGameModeChangeEvent event) { + if (event.isCancelled()) return; + GameMode gameMode = event.getNewGameMode(); + Chair chair = chairMap.get(event.getPlayer().getUniqueId()); + if (gameMode == GameMode.SPECTATOR && chair != null) clearChair(chair); + } + + @EventHandler + public void onDismount(EntityDismountEvent event) { + if (!(event.getEntity() instanceof Player player)) return; + Chair chair = chairMap.get(player.getUniqueId()); + event.getDismounted(); + if (chair == null || event.getDismounted().getType() != EntityType.ARMOR_STAND) return; + if (leaving.contains(player.getUniqueId())) return; + if (orienting.contains(player.getUniqueId())) { + orienting.remove(player.getUniqueId()); + return; + } + if (tossed.containsKey(player.getUniqueId())) { + TargetInfo info = tossed.get(player.getUniqueId()); + Entity attacker = info.getEntity(); + if (info.hasSource() && info.livingSource()) attacker = info.getLivingSource(); + + ChairTossEvent tossEvent = new ChairTossEvent(chairMap.get(player.getUniqueId()), player, attacker, info, false); + Util.callEvent(tossEvent); + tossed.remove(player.getUniqueId()); + return; + } + leaving.add(player.getUniqueId()); + } + + @EventHandler + public void onMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + if (leaving.contains(player.getUniqueId())) { + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chairMap.get(player.getUniqueId()), player, exitWhereFacing); + Util.callEvent(leaveEvent); + leaving.remove(player.getUniqueId()); + } + } + + @EventHandler + public void takeDamage(EntityDamageByEntityEvent event) { + if (event.isCancelled()) return; + if (!(event.getEntity() instanceof Player player)) return; + + Entity attacker = event.getDamager(); + ProjectileSource source = null; + if (attacker instanceof Projectile) source = ((Projectile) attacker).getShooter(); + Chair chair = chairMap.get(player.getUniqueId()); + if (chair == null) return; + + if (event.getDamage() >= minDamage && canLaunch) { + TargetInfo info; + if (source == null) info = new TargetInfo(attacker, event.getDamage()); + else info = new TargetInfo(source, attacker, event.getDamage()); + tossed.put(player.getUniqueId(), info); + if (chair.getFakeSeat() != null) chair.getFakeSeat().removePassenger(player); + } + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (event.isCancelled()) return; + chairs.stream() + .filter(Objects::nonNull) + .filter(c -> c.getLocation() != null) + .filter(c -> Util.samePosition(event.getBlock(), c.getBlock())) + .findAny() + .ifPresent(c -> { + if (!event.getPlayer().hasPermission("rfchairs.break")) event.setCancelled(true); + }); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void quit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + Chair chair = chairMap.get(player.getUniqueId()); + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); + Util.callEvent(leaveEvent); + } + + @EventHandler + public void pistonExtend(BlockPistonExtendEvent event) { + for (Block block : event.getBlocks()) { + for (Chair chair : chairs) { + if (chair == null) continue; + if (chair.getLocation() == null) continue; + if (Util.samePosition(block, chair.getBlock())) { + event.setCancelled(true); + break; + } + } + } + } + + @EventHandler + public void pistonRetract(BlockPistonRetractEvent event) { + for (Block block : event.getBlocks()) { + for (Chair chair : chairs) { + if (chair == null) continue; + if (chair.getLocation() == null) continue; + if (Util.samePosition(block, chair.getBlock())) { + event.setCancelled(true); + break; + } + } + } + } + + @EventHandler + public void onDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + Chair chair = chairMap.get(player.getUniqueId()); + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); + Util.callEvent(leaveEvent); + } + + /* + * Sitting and Ejection Methods + */ + + private boolean sitPlayer(Chair chair, Player player) { + if (player == null) return false; + if (chair == null || chair.isOccupied()) return false; + + ArmorStand fakeSeat = chair.getFakeSeat(); + if (fakeSeat == null) fakeSeat = Util.generateFakeSeat(chair); + + fakeSeat.addPassenger(player); + chair.setFakeSeat(fakeSeat); + fakeSeats.add(fakeSeat.getUniqueId().toString()); + configManager.getData().set("UUIDs", fakeSeats); + return true; + } + + private void ejectPlayer(Block block, Player player, Entity entity) { + Block exit = block; + + if (exitWhereFacing) exit = findExitPoint(entity.getLocation(), block); + + Location exitLoc = exit.getLocation().add(0.5, 0.5, 0.5); + + if (!canToss) return; + + if (!faceAttacker) { + exitLoc.setPitch(player.getLocation().getPitch()); + exitLoc.setYaw(player.getLocation().getYaw()); + } else { + exitLoc.setDirection(Util.getVectorDir(player.getLocation(), entity.getLocation())); + } + + if (tossVelocity != 0) { + double finalVelocity = tossVelocity; + if (scaleVelocity && entity instanceof Player) { + if (((Player) entity).isSprinting()) finalVelocity = tossVelocity * scaleAmount; + } + player.setVelocity(exitLoc.getDirection().multiply(finalVelocity)); + } + } + + private Block findExitPoint(Location entity, Block block) { + Block blockToCheck = Util.getBlockFromDirection(block, Util.getCardinalDirection(entity)); + boolean foundValidExit = Util.canFitPlayer(blockToCheck) && Util.safePlace(blockToCheck); + + String[] directions = {"north", "east", "south", "west"}; + for (String direction : directions) { + if (foundValidExit) break; + blockToCheck = Util.getBlockFromDirection(block, direction); + foundValidExit = Util.canFitPlayer(blockToCheck) && Util.safePlace(blockToCheck); + } + if (!foundValidExit) blockToCheck = block.getRelative(BlockFace.UP); + return blockToCheck; + } + + /* + * Cleaning and Clearing + */ + + void saveToggled() { + List ids = new ArrayList<>(); + if (toggled == null || toggled.size() == 0) configManager.getData().set("Toggled", new ArrayList()); + for (UUID id : toggled) ids.add(id.toString()); + plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had toggled off."); + configManager.getData().set("Toggled", ids); + } + + void loadToggled() { + List toggled = configManager.getData().getStringList("Toggled"); + if (toggled.size() == 0) return; + plugin.getServer().getLogger().info("[RFChairs] " + toggled.size() + " Players had toggled off. Adding Them..."); + + toggled.stream() + .map(UUID::fromString) + .forEach(id -> this.toggled.add(id)); + + configManager.getData().set("Toggled", new ArrayList()); + } + + void shutdown() { + clearChairs(); + clearFakeSeats(); + } + + private void clearChair(Chair chair) { + if (chair == null) return; + if (chair.getPlayer() != null) chair.getPlayer().removePotionEffect(PotionEffectType.REGENERATION); + chair.clear(); + } + + private void clearChairs() { + for (Chair chair : chairs) clearChair(chair); + } + + private void clearPlayer(Player player) { + Chair chair = chairMap.get(player.getUniqueId()); + if (chair == null) return; + chairMap.remove(player.getUniqueId()); + chairs.remove(chair); + chair.clear(); + } + + public void clearFakeSeats() { + for (Chair chair : chairs) clearChair(chair); + } + + public void clearFakeSeatsFromFile(JavaPlugin plugin) { + List fakes = configManager.getData().getStringList("UUIDs"); + int leftoverFakes = fakes.size(); + if (leftoverFakes >= 1) { + plugin.getServer().getLogger().info("[RFChairs] Detected " + fakes.size() + " leftover seats! Removing..."); + for (String fake : fakes) { + UUID id = UUID.fromString(fake); + Entity armorStand = plugin.getServer().getEntity(id); + if (armorStand == null) continue; + armorStand.remove(); + } + configManager.getData().set("UUIDs", new ArrayList()); + } else { + plugin.getServer().getLogger().info("[RFChairs] No fake seats remaining! Proceeding"); + } + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java new file mode 100644 index 0000000..1ef7f8f --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -0,0 +1,107 @@ +package com.rifledluffy.chairs; + +import com.rifledluffy.chairs.config.ConfigManager; +import com.rifledluffy.chairs.messages.MessageConstruct; +import com.rifledluffy.chairs.messages.MessageEvent; +import com.rifledluffy.chairs.messages.MessageType; +import com.rifledluffy.chairs.messages.Messages; +import com.rifledluffy.chairs.utility.Util; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class MessageManager implements Listener { + + private final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); + private final List tempMute = new ArrayList(); + public List muted = new ArrayList(); + private ConfigManager configManager = plugin.getConfigManager(); + public FileConfiguration messages = configManager.getMessages(); + private boolean allowMessages; + private int tempMuteDuration; + + public void reload(RFChairs plugin) { + configManager = plugin.getConfigManager(); + messages = configManager.getMessages(); + allowMessages = configManager.getConfig().getBoolean("allow-custom-messages", true); + tempMuteDuration = messages.getInt("temp-mute-duration", 0); + } + + private void tempMute(Player player) { + int duration = tempMuteDuration; + tempMute.add(player.getUniqueId()); + BukkitRunnable runnable = new BukkitRunnable() { + @Override + public void run() { + if (tempMuted(player)) tempMute.remove(player.getUniqueId()); + } + }; + runnable.runTaskLater(plugin, duration); + } + + private boolean tempMuted(Player player) { + return tempMute.contains(player.getUniqueId()); + } + + @EventHandler + public void onMessage(MessageEvent event) { + Player player = event.getPlayer(); + if (tempMute.contains(player.getUniqueId())) event.setCancelled(true); + if (event.isCancelled()) return; + if (tempMuteDuration > 0) tempMute(player); + if (allowMessages && !muted.contains(player.getUniqueId())) { + String string = processString(event); + if (!string.isEmpty()) player.sendMessage(string); + } + } + + private String processString(MessageEvent event) { + MessageType type = event.getType(); + MessageConstruct construct = event.getConstruct(); + String string; + + String stringOutput = Messages.getMessage(type); + if (stringOutput == null) { + string = Messages.getDefault(type); + } else { + string = stringOutput; + } + + string = messages.getString(string); + + String finalString = ""; + + if (construct == MessageConstruct.SINGLE) finalString = Util.replaceMessage(event.getPlayer(), string); + else if (construct == MessageConstruct.DEFENSIVE) + finalString = Util.replaceMessage(event.getEntity(), event.getPlayer(), string); + else if (construct == MessageConstruct.OFFENSIVE && event.getEntity() instanceof Player) + finalString = Util.replaceMessage(event.getPlayer(), (Player) event.getEntity(), string); + return finalString; + } + + void saveMuted() { + List ids = new ArrayList(); + if (muted == null || muted.size() == 0) configManager.getData().set("Muted", new ArrayList()); + for (UUID id : muted) ids.add(id.toString()); + plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had events muted."); + configManager.getData().set("Muted", ids); + } + + void loadMuted() { + List muted = configManager.getData().getStringList("Muted"); + if (muted == null || muted.size() == 0) return; + plugin.getServer().getLogger().info("[RFChairs] " + muted.size() + " Players had events muted off. Adding Them..."); + for (String toggler : muted) { + UUID id = UUID.fromString(toggler); + this.muted.add(id); + } + configManager.getData().set("Muted", new ArrayList()); + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java new file mode 100644 index 0000000..5746346 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -0,0 +1,130 @@ +package com.rifledluffy.chairs; + +import com.rifledluffy.chairs.chairs.BlockFilter; +import com.rifledluffy.chairs.command.CommandManager; +import com.rifledluffy.chairs.config.ConfigManager; +import com.rifledluffy.chairs.managers.WorldGuardManager; +import com.rifledluffy.chairs.metrics.MetricsLite; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.io.IOException; + +public class RFChairs extends JavaPlugin { + + private static RFChairs instance; + public CommandManager commandManager; + public ConfigManager cfgManager; + public ChairManager chairManager; + public MessageManager messageManager; + public WorldGuardManager worldGuardManager; + + public static RFChairs getInstance() { + return instance; + } + + private static void setInstance(RFChairs instance) { + RFChairs.instance = instance; + } + + @Override + public void onLoad() { + setInstance(this); + loadWorldGuard(); + } + + private void loadWorldGuard() { + try { + Class.forName("com.sk89q.worldguard.WorldGuard"); + Class.forName("com.sk89q.worldedit.WorldEdit"); + Class.forName("com.sk89q.worldedit.math.BlockVector3"); + worldGuardManager = new WorldGuardManager(); + worldGuardManager.setup(); + getLogger().info("Found WorldGuard && WorldEdit! Applying Custom Flag..."); + } catch (ClassNotFoundException e) { + getLogger().info("Missing either WorldGuard or WorldEdit! Disabling Custom Flag Features..."); + getLogger().info("Latest WorldGuard/WorldEdit features could be missing. Please Update!"); + } + + if (worldGuardManager != null) worldGuardManager.register(); + } + + @Override + public void onEnable() { + + @SuppressWarnings("unused") + MetricsLite metrics = new MetricsLite(this); + + commandManager = new CommandManager(); + commandManager.setup(); + + loadConfigManager(); + + chairManager = new ChairManager(); + chairManager.clearFakeSeatsFromFile(this); + chairManager.loadToggled(); + + messageManager = new MessageManager(); + messageManager.loadMuted(); + + BlockFilter.reload(); + chairManager.reload(this); + messageManager.reload(this); + getServer().getPluginManager().registerEvents(chairManager, this); + getServer().getPluginManager().registerEvents(messageManager, this); + + getLogger().info("Rifle's Chairs has been enabled!"); + } + + @Override + public void onDisable() { + chairManager.saveToggled(); + messageManager.saveMuted(); + + chairManager.shutdown(); + + getLogger().info("Saving Configuration Files!"); + cfgManager.saveData(); + + Bukkit.getOnlinePlayers().forEach(p -> { + PotionEffect regen = p.getPotionEffect(PotionEffectType.REGENERATION); + if (regen == null) return; + if (regen.getDuration() > 1000) p.removePotionEffect(PotionEffectType.REGENERATION); + }); + + getLogger().info("Rifle's Chairs has been disabled!"); + } + + public void loadConfigManager() { + cfgManager = new ConfigManager(); + try { + cfgManager.setup(); + } catch (IOException e) { + e.printStackTrace(); + } + cfgManager.reloadConfig(); + } + + public ConfigManager getConfigManager() { + return cfgManager; + } + + public void setConfigManager(ConfigManager configManager) { + this.cfgManager = configManager; + } + + public WorldGuardManager getWorldGuardManager() { + return this.worldGuardManager; + } + + public void log(String string) { + getLogger().info(string); + } + + boolean hasWorldGuard() { + return worldGuardManager != null; + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/TargetInfo.java b/src/main/java/com/rifledluffy/chairs/TargetInfo.java new file mode 100644 index 0000000..af705d5 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/TargetInfo.java @@ -0,0 +1,60 @@ +package com.rifledluffy.chairs; + +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.projectiles.BlockProjectileSource; +import org.bukkit.projectiles.ProjectileSource; + +public class TargetInfo { + Player player; + Entity attacker; + ProjectileSource source; + Double damage; + boolean sprinting = false; + + TargetInfo(ProjectileSource source, Entity attacker, Double damage) { + this.source = source; + this.attacker = attacker; + this.damage = damage; + } + + TargetInfo(Entity attacker, Double damage) { + this.source = null; + if (attacker instanceof Player) { + player = (Player) attacker; + sprinting = player.isSprinting(); + } + this.attacker = attacker; + this.damage = damage; + } + + Entity getEntity() { + return attacker; + } + + LivingEntity getLivingSource() { + return (LivingEntity) source; + } + + Block getBlockSource() { + return ((BlockProjectileSource) source).getBlock(); + } + + Double getDamage() { + return damage; + } + + boolean isSprinting() { + return this.sprinting; + } + + boolean hasSource() { + return source != null; + } + + boolean livingSource() { + return source != null && source instanceof LivingEntity; + } +} diff --git a/src/com/rifledluffy/chairs/chairs/BlockFilter.java b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java similarity index 89% rename from src/com/rifledluffy/chairs/chairs/BlockFilter.java rename to src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java index c222bf2..7929089 100644 --- a/src/com/rifledluffy/chairs/chairs/BlockFilter.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java @@ -4,18 +4,23 @@ import org.bukkit.Material; import org.bukkit.configuration.file.FileConfiguration; -import java.util.*; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; public class BlockFilter { - + + private static final Set carpetTypeSet; + private static final Set slabTypeSet; + private static final Set stairsTypeSet; private static Set whitelist, blacklist; - private static Set carpetTypeSet, slabTypeSet, stairsTypeSet; - + static { carpetTypeSet = EnumSet.noneOf(Material.class); slabTypeSet = EnumSet.noneOf(Material.class); stairsTypeSet = EnumSet.noneOf(Material.class); - + Arrays.stream(Material.values()) .filter(m -> !m.name().startsWith("LEGACY_")) .forEach(m -> { @@ -28,47 +33,47 @@ else if (name.endsWith("_STAIRS")) stairsTypeSet.add(m); }); } - + public static void reload() { FileConfiguration config = RFChairs.getInstance().getConfig(); whitelist = new HashSet<>(config.getStringList("allowed-chairs")); blacklist = new HashSet<>(config.getStringList("blacklisted-chairs")); } - + public static boolean isWhitelisted(Material type, String category) { if (whitelist.contains("ALL_" + category)) return true; return whitelist.contains(type.name()); } - + public static boolean isBlacklisted(Material type, String category) { if (blacklist.contains("ALL_" + category)) return true; return blacklist.contains(type.name()); } - + // validate - + public static boolean validateCarpet(Material type) { return isWhitelisted(type, "CARPETS") && !isBlacklisted(type, "CARPET"); } - + public static boolean validateSlab(Material type) { return isWhitelisted(type, "SLABS") && !isBlacklisted(type, "SLAB"); } - + public static boolean validateStairs(Material type) { return isWhitelisted(type, "STAIRS") && !isBlacklisted(type, "STAIRS"); } - + // check - + public static boolean isCarpetBlock(Material type) { return carpetTypeSet.contains(type); } - + public static boolean isSlabBlock(Material type) { return slabTypeSet.contains(type); } - + public static boolean isStairsBlock(Material type) { return stairsTypeSet.contains(type); } diff --git a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java new file mode 100644 index 0000000..6f08cfe --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java @@ -0,0 +1,109 @@ +package com.rifledluffy.chairs.chairs; + +import com.rifledluffy.chairs.RFChairs; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.material.Stairs; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +public class Chair { + + private final BukkitRunnable clear; + private final int clearID; + + private Location location; + private Block chair; + private ArmorStand fakeSeat = null; + private Player player; + + public Chair(Player player, Location location) { + this.location = location; + this.player = player; + this.chair = location.getBlock(); + + clear = new BukkitRunnable() { + + @Override + public void run() { + if (fakeSeat == null) { + clear(); + return; + } + if (fakeSeat.getPassengers().size() == 0) clear(); + } + + }; + clearID = clear.runTaskTimer(RFChairs.getInstance(), 20, 20).getTaskId(); + } + + /* + * Getters + */ + + public ArmorStand getFakeSeat() { + return fakeSeat; + } + + public void setFakeSeat(ArmorStand armorStand) { + fakeSeat = armorStand; + } + + public Player getPlayer() { + return player; + } + + public void setPlayer(Player player) { + this.player = player; + } + + public Block getBlock() { + return location.getBlock(); + } + + public BlockState getBlockState() { + return chair.getState(); + } + + public BlockData getBlockData() { + return chair.getState().getBlockData(); + } + + public BlockFace getFacing() { + if (!BlockFilter.isStairsBlock(chair.getType())) return null; + return ((Stairs) chair.getState().getData()).getFacing(); + } + + /* + * Setters + */ + + public Location getLocation() { + return location; + } + + /* + * Methods + */ + + public boolean isOccupied() { + return !(fakeSeat == null) && !fakeSeat.isEmpty(); + } + + public void clear() { + if (fakeSeat != null) fakeSeat.remove(); + if (player != null) player.removePotionEffect(PotionEffectType.REGENERATION); + chair = null; + location = null; + fakeSeat = null; + player = null; + if (Bukkit.getScheduler().isCurrentlyRunning(clearID)) clear.cancel(); + } + +} diff --git a/src/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java similarity index 62% rename from src/com/rifledluffy/chairs/command/CommandManager.java rename to src/main/java/com/rifledluffy/chairs/command/CommandManager.java index b6c50b4..d797e0f 100644 --- a/src/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -1,39 +1,30 @@ package com.rifledluffy.chairs.command; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; - +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.command.commands.*; +import net.md_5.bungee.api.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; -import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.command.commands.HelpCommand; -import com.rifledluffy.chairs.command.commands.InfoCommand; -import com.rifledluffy.chairs.command.commands.MuteCommand; -import com.rifledluffy.chairs.command.commands.ReloadCommand; -import com.rifledluffy.chairs.command.commands.ResetCommand; -import com.rifledluffy.chairs.command.commands.SubCommand; -import com.rifledluffy.chairs.command.commands.ToggleCommand; - -import net.md_5.bungee.api.ChatColor; +import java.util.ArrayList; +import java.util.Arrays; public class CommandManager implements CommandExecutor { - - private ArrayList commands = new ArrayList(); - private RFChairs plugin = RFChairs.getInstance(); - - public CommandManager(){} - - //Sub Commands - public String main = "rfchairs"; - public String help = "help"; + private final ArrayList commands = new ArrayList<>(); + private final RFChairs plugin = RFChairs.getInstance(); + //Sub Commands + public String main = "rfchairs"; + public String help = "help"; public String info = "info"; public String reload = "reload"; public String reset = "reset"; - public String toggle = "toggle"; - public String mute = "mute"; + public String toggle = "toggle"; + public String mute = "mute"; + + public CommandManager() { + } public void setup() { plugin.getCommand(main).setExecutor(this); @@ -46,7 +37,7 @@ public void setup() { this.commands.add(new MuteCommand()); } - public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNull String s, String[] args) { if (command.getName().equalsIgnoreCase(main)) { if (args.length == 0) { @@ -61,14 +52,14 @@ public boolean onCommand(CommandSender sender, Command command, String s, String return true; } - ArrayList arrayList = new ArrayList(); + ArrayList arrayList = new ArrayList<>(); arrayList.addAll(Arrays.asList(args)); arrayList.remove(0); - try{ - target.onCommand(sender,args); - }catch (Exception e){ + try { + target.onCommand(sender, args); + } catch (Exception e) { sender.sendMessage(ChatColor.RED + "An error has occurred."); e.printStackTrace(); @@ -79,11 +70,7 @@ public boolean onCommand(CommandSender sender, Command command, String s, String } private SubCommand get(String name) { - Iterator subcommands = this.commands.iterator(); - - while (subcommands.hasNext()) { - SubCommand sc = (SubCommand) subcommands.next(); - + for (SubCommand sc : this.commands) { if (sc.name().equalsIgnoreCase(name)) { return sc; } @@ -100,6 +87,5 @@ private SubCommand get(String name) { } } return null; -} - + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java new file mode 100644 index 0000000..43cd291 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java @@ -0,0 +1,61 @@ +package com.rifledluffy.chairs.command.commands; + +import com.rifledluffy.chairs.RFChairs; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +public class HelpCommand extends SubCommand { + + private final RFChairs plugin = RFChairs.getInstance(); + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + + @Override + public void onCommand(ConsoleCommandSender sender, String[] args) { + sender.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); + sender.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); + sender.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages [Console Can Cast]"); + sender.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs [Console Can Cast]"); + sender.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor [Player Only]"); + sender.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor [Player Only]"); + sender.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version [Console Can Cast]"); + sender.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); + } + + @Override + public void onCommand(Player player, String[] args) { + player.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); + player.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); + player.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages"); + player.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs"); + player.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor"); + player.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor"); + player.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version"); + player.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); + } + + @Override + public String name() { + return plugin.commandManager.help; + } + + @Override + public String info() { + return null; + } + + @Override + public String[] aliases() { + return new String[0]; + } +} \ No newline at end of file diff --git a/src/com/rifledluffy/chairs/command/commands/InfoCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java similarity index 53% rename from src/com/rifledluffy/chairs/command/commands/InfoCommand.java rename to src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java index b1435b5..59ee5d4 100644 --- a/src/com/rifledluffy/chairs/command/commands/InfoCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java @@ -1,28 +1,28 @@ package com.rifledluffy.chairs.command.commands; +import com.rifledluffy.chairs.RFChairs; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; -import com.rifledluffy.chairs.RFChairs; - public class InfoCommand extends SubCommand { - - private RFChairs plugin = RFChairs.getInstance(); - + + private final RFChairs plugin = RFChairs.getInstance(); + @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else return; - } - + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("§cOnly players can use commands for this plugin."); - } + public void onCommand(ConsoleCommandSender sender, String[] args) { + sender.sendMessage("�cOnly players can use commands for this plugin."); + } @Override public void onCommand(Player player, String[] args) { diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java new file mode 100644 index 0000000..469afc1 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java @@ -0,0 +1,66 @@ +package com.rifledluffy.chairs.command.commands; + +import com.rifledluffy.chairs.MessageManager; +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.utility.Util; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; + +public class MuteCommand extends SubCommand { + + private final RFChairs plugin = RFChairs.getInstance(); + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + + @Override + public void onCommand(ConsoleCommandSender sender, String[] args) { + sender.sendMessage("�cOnly players can use commands for this plugin."); + } + + @Override + public void onCommand(Player player, String[] args) { + MessageManager messageManager = plugin.messageManager; + List muted = messageManager.muted; + String message; + if (!player.hasPermission("rfchairs.mute")) return; + if (muted.contains(player.getUniqueId())) { + String string = messageManager.messages.getString("mute-message-enabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!"); + message = Util.replaceMessage(player, string); + player.sendMessage(message); + muted.remove(player.getUniqueId()); + } else { + String string = messageManager.messages.getString("mute-message-disabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!"); + message = Util.replaceMessage(player, string); + player.sendMessage(message); + muted.add(player.getUniqueId()); + } + } + + @Override + public String name() { + return plugin.commandManager.mute; + } + + @Override + public String info() { + return ""; + } + + @Override + public String[] aliases() { + return new String[0]; + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java new file mode 100644 index 0000000..67acdee --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java @@ -0,0 +1,64 @@ +package com.rifledluffy.chairs.command.commands; + +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.chairs.BlockFilter; +import com.rifledluffy.chairs.config.ConfigManager; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +public class ReloadCommand extends SubCommand { + + private final RFChairs plugin = RFChairs.getInstance(); + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + + @Override + public void onCommand(ConsoleCommandSender sender, String[] args) { + ConfigManager newConfig = plugin.getConfigManager(); + newConfig.reloadConfig(); + newConfig.reloadMessages(); + plugin.setConfigManager(newConfig); + plugin.chairManager.reload(plugin); + plugin.messageManager.reload(plugin); + sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); + } + + @Override + public void onCommand(Player player, String[] args) { + if (!player.hasPermission("rfchairs.reload") && !player.hasPermission("rfchairs.manage")) return; + ConfigManager newConfig = plugin.getConfigManager(); + newConfig.reloadConfig(); + newConfig.reloadMessages(); + plugin.setConfigManager(newConfig); + BlockFilter.reload(); + plugin.chairManager.reload(plugin); + plugin.messageManager.reload(plugin); + player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); + } + + @Override + public String name() { + return plugin.commandManager.reload; + } + + @Override + public String info() { + return "Reloads the config and messages"; + } + + @Override + public String[] aliases() { + return new String[0]; + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java new file mode 100644 index 0000000..dc78281 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -0,0 +1,55 @@ +package com.rifledluffy.chairs.command.commands; + +import com.rifledluffy.chairs.RFChairs; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +public class ResetCommand extends SubCommand { + + private final RFChairs plugin = RFChairs.getInstance(); + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + + @Override + public void onCommand(ConsoleCommandSender sender, String[] args) { + plugin.chairManager.clearFakeSeats(); + plugin.chairManager.clearFakeSeatsFromFile(plugin); + plugin.getLogger().info("Chairs Reset!"); + sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); + } + + @Override + public void onCommand(Player player, String[] args) { + if (!player.hasPermission("rfchairs.reset") && !player.hasPermission("rfchairs.manage")) return; + plugin.chairManager.clearFakeSeats(); + plugin.chairManager.clearFakeSeatsFromFile(plugin); + plugin.getLogger().info("Chairs Reset!"); + player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); + } + + @Override + public String name() { + return plugin.commandManager.reset; + } + + @Override + public String info() { + return "Resets all chairs"; + } + + @Override + public String[] aliases() { + return new String[0]; + } + +} \ No newline at end of file diff --git a/src/com/rifledluffy/chairs/command/commands/SubCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java similarity index 94% rename from src/com/rifledluffy/chairs/command/commands/SubCommand.java rename to src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java index 881fa20..fd6c341 100644 --- a/src/com/rifledluffy/chairs/command/commands/SubCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java @@ -10,10 +10,11 @@ public abstract class SubCommand { / args[0] args[1] */ - public SubCommand() {} - + public SubCommand() { + } + public abstract void onCommand(CommandSender sender, String[] args); - + public abstract void onCommand(ConsoleCommandSender sender, String[] args); public abstract void onCommand(Player player, String[] args); diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java new file mode 100644 index 0000000..770c39e --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java @@ -0,0 +1,66 @@ +package com.rifledluffy.chairs.command.commands; + +import com.rifledluffy.chairs.MessageManager; +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.utility.Util; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; + +public class ToggleCommand extends SubCommand { + + private final RFChairs plugin = RFChairs.getInstance(); + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (sender instanceof Player) { + onCommand((Player) sender, args); + } else if (sender instanceof ConsoleCommandSender) { + onCommand((ConsoleCommandSender) sender, args); + } else { + } + } + + @Override + public void onCommand(ConsoleCommandSender sender, String[] args) { + sender.sendMessage("�cOnly players can use commands for this plugin."); + } + + @Override + public void onCommand(Player player, String[] args) { + MessageManager messageManager = plugin.messageManager; + List toggled = plugin.chairManager.toggled; + String message; + if (!player.hasPermission("rfchairs.toggle")) return; + if (toggled.contains(player.getUniqueId())) { + String string = messageManager.messages.getString("toggle-message-enabled", "&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!"); + message = Util.replaceMessage(player, string); + player.sendMessage(message); + toggled.remove(player.getUniqueId()); + } else { + String string = messageManager.messages.getString("toggle-message-disabled", "&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!"); + message = Util.replaceMessage(player, string); + player.sendMessage(message); + toggled.add(player.getUniqueId()); + } + } + + @Override + public String name() { + return plugin.commandManager.toggle; + } + + @Override + public String info() { + return ""; + } + + @Override + public String[] aliases() { + return new String[0]; + } + +} diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java new file mode 100644 index 0000000..97d6be9 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -0,0 +1,108 @@ +package com.rifledluffy.chairs.config; + +import com.rifledluffy.chairs.RFChairs; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; + +public class ConfigManager { + + private final JavaPlugin plugin = RFChairs.getPlugin(RFChairs.class); + FileConfiguration config; + /* + * Configuration Files + */ + File configFile; + FileConfiguration fake; + File fakeFile; + FileConfiguration message; + File messageFile; + + public void setup() throws IOException { + configFile = new File(plugin.getDataFolder(), "config.yml"); + config = plugin.getConfig(); + config.options().copyDefaults(true); + saveConfig(); + + if (!plugin.getDataFolder().exists()) { + plugin.getDataFolder().mkdir(); + } + + fakeFile = new File(plugin.getDataFolder(), "fakes.yml"); + + if (!fakeFile.exists()) { + try { + fakeFile.createNewFile(); + } catch (IOException e) { + Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not create fakes.yml!"); + } + } + + messageFile = new File(plugin.getDataFolder(), "messages.yml"); + + if (!messageFile.exists()) { + messageFile.getParentFile().mkdirs(); + plugin.saveResource("messages.yml", false); + } + + fake = YamlConfiguration.loadConfiguration(fakeFile); + message = YamlConfiguration.loadConfiguration(messageFile); + } + + public FileConfiguration getData() { + return fake; + } + + public void saveData() { + try { + fake.save(fakeFile); + } catch (IOException e) { + Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not save fakes.yml!"); + } + } + + public void reloadData() { + fake = YamlConfiguration.loadConfiguration(fakeFile); + } + + public FileConfiguration getMessages() { + return message; + } + + public void saveMessages() { + try { + message.save(messageFile); + } catch (IOException e) { + plugin.getLogger().info("[Rifle's Chairs] Could not save messages.yml!"); + } + } + + public void reloadMessages() { + message = YamlConfiguration.loadConfiguration(messageFile); + } + + public FileConfiguration getConfig() { + return config; + } + + public void saveConfig() { + try { + config.save(configFile); + } catch (IOException e) { + plugin.getLogger().info("[Rifle's Chairs] Could not save config.yml!"); + } + } + + public void reloadConfig() { + config = YamlConfiguration.loadConfiguration(configFile); + } + + public PluginDescriptionFile getDesc() { + return plugin.getDescription(); + } +} \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java new file mode 100644 index 0000000..b53ffca --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java @@ -0,0 +1,46 @@ +package com.rifledluffy.chairs.events; + +import com.rifledluffy.chairs.chairs.Chair; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ChairCheckEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + Chair chair; + Block block; + Player player; + + public ChairCheckEvent(Chair chair, Player player) { + this.chair = chair; + this.player = player; + } + + public ChairCheckEvent(Block block, Player player) { + this.block = block; + this.player = player; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public Chair getChair() { + return this.chair; + } + + public Block getBlock() { + return this.block; + } + + public Player getPlayer() { + return this.player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java new file mode 100644 index 0000000..b68f7cf --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java @@ -0,0 +1,46 @@ +package com.rifledluffy.chairs.events; + +import com.rifledluffy.chairs.chairs.Chair; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ChairLeaveEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + private final Chair chair; + private final Player player; + private boolean exitWhereFacing = false; + + public ChairLeaveEvent(Chair chair, Player player, boolean flag) { + this.chair = chair; + this.player = player; + this.exitWhereFacing = flag; + } + + public ChairLeaveEvent(Chair chair, Player player) { + this.chair = chair; + this.player = player; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public Chair getChair() { + return this.chair; + } + + public Player getPlayer() { + return this.player; + } + + public boolean exitWhereFacing() { + return this.exitWhereFacing; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java new file mode 100644 index 0000000..de66626 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java @@ -0,0 +1,41 @@ +package com.rifledluffy.chairs.events; + +import com.rifledluffy.chairs.chairs.Chair; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ChairReplaceEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + Chair chair; + Player replaced; + Player player; + + public ChairReplaceEvent(Chair chair, Player replaced, Player player) { + this.chair = chair; + this.replaced = replaced; + this.player = player; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public Chair getChair() { + return this.chair; + } + + public Player getReplaced() { + return this.replaced; + } + + public Player getPlayer() { + return this.player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java new file mode 100644 index 0000000..3032c70 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java @@ -0,0 +1,35 @@ +package com.rifledluffy.chairs.events; + +import com.rifledluffy.chairs.chairs.Chair; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ChairSitEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + Chair chair; + Player player; + + public ChairSitEvent(Chair chair, Player player) { + this.chair = chair; + this.player = player; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public Chair getChair() { + return this.chair; + } + + public Player getPlayer() { + return this.player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java new file mode 100644 index 0000000..50129c3 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java @@ -0,0 +1,55 @@ +package com.rifledluffy.chairs.events; + +import com.rifledluffy.chairs.TargetInfo; +import com.rifledluffy.chairs.chairs.Chair; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ChairTossEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + Chair chair; + Player player; + Entity attacker; + TargetInfo info; + boolean silent; + + public ChairTossEvent(Chair chair, Player player, Entity attacker, TargetInfo info, boolean flag) { + this.chair = chair; + this.player = player; + this.attacker = attacker; + this.info = info; + this.silent = flag; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public Chair getChair() { + return this.chair; + } + + public Player getPlayer() { + return this.player; + } + + public Entity getAttacker() { + return this.attacker; + } + + public TargetInfo getInfo() { + return this.info; + } + + public boolean isSilent() { + return this.silent; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java new file mode 100644 index 0000000..933d256 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java @@ -0,0 +1,84 @@ +package com.rifledluffy.chairs.managers; + +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.chairs.Chair; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; +import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; +import com.sk89q.worldguard.protection.regions.RegionContainer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import java.util.List; +import java.util.stream.Collectors; + +public class WorldGuardManager { + + @SuppressWarnings("rawtypes") + public static Flag flag; + private final RFChairs plugin = RFChairs.getInstance(); + public WorldGuard worldGuard; + public WorldGuardPlugin worldGuardPlugin; + public RegionContainer container; + + public WorldGuardManager() { + } + + public void setup() { + worldGuard = WorldGuard.getInstance(); + } + + public void register() { + flag = new StateFlag("allow-seating", true); + FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry(); + try { + registry.register(flag); + plugin.log("Custom Flag Registered!"); + } catch (FlagConflictException e) { + plugin.log("Unable to register custom worldguard flag!"); + } + } + + public WorldGuardPlugin getWorldGuard() { + Plugin plugin = this.plugin.getServer().getPluginManager().getPlugin("WorldGuard"); + + if (!(plugin instanceof WorldGuardPlugin)) return null; + return (WorldGuardPlugin) plugin; + } + + public boolean validateSeating(Chair chair, Player player) { + double xPos = chair.getLocation().getX(); + double yPos = chair.getLocation().getY(); + double zPos = chair.getLocation().getZ(); + + WorldGuardManager worldManager = plugin.getWorldGuardManager(); + + LocalPlayer localPlayer = worldManager.getWorldGuard().wrapPlayer(player); + + BlockVector3 vector3 = BlockVector3.at(xPos, yPos, zPos); + + List regionSetList = getContainer().getLoaded().stream() + .map(manager -> manager.getApplicableRegions(vector3)) + .collect(Collectors.toList()); + + if (regionSetList.size() == 0) return true; + + return regionSetList.stream() + .allMatch(set -> set.testState(localPlayer, (StateFlag) worldManager.getFlag())); + } + + public RegionContainer getContainer() { + return worldGuard.getPlatform().getRegionContainer(); + } + + public Flag getFlag() { + return flag; + } + +} diff --git a/src/com/rifledluffy/chairs/messages/MessageConstruct.java b/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java similarity index 69% rename from src/com/rifledluffy/chairs/messages/MessageConstruct.java rename to src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java index 1fb298a..8588cc1 100644 --- a/src/com/rifledluffy/chairs/messages/MessageConstruct.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java @@ -1,6 +1,5 @@ package com.rifledluffy.chairs.messages; public enum MessageConstruct { - - SINGLE, OFFENSIVE, DEFENSIVE + SINGLE, OFFENSIVE, DEFENSIVE } diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java new file mode 100644 index 0000000..1ded62b --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java @@ -0,0 +1,73 @@ +package com.rifledluffy.chairs.messages; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class MessageEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + boolean cancelled; + MessageType type; + MessageConstruct construct; + Player player; + Entity other; + + public MessageEvent(MessageType type, MessageConstruct construct, Player player, Player other) { + this.type = type; + this.construct = construct; + this.player = player; + this.other = other; + } + + public MessageEvent(MessageType type, Player player, Entity other) { + this.type = type; + this.construct = MessageConstruct.DEFENSIVE; + this.player = player; + this.other = other; + } + + public MessageEvent(MessageType type, Player player) { + this.type = type; + this.construct = MessageConstruct.SINGLE; + this.player = player; + this.other = null; + } + + static public HandlerList getHandlerList() { + return handlers; + } + + public MessageType getType() { + return this.type; + } + + public MessageConstruct getConstruct() { + return this.construct; + } + + public Player getPlayer() { + return this.player; + } + + public Entity getEntity() { + return this.other; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageType.java b/src/main/java/com/rifledluffy/chairs/messages/MessageType.java new file mode 100644 index 0000000..95fad42 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageType.java @@ -0,0 +1,7 @@ +package com.rifledluffy.chairs.messages; + +public enum MessageType { + + OCCUPIED, TOOFAR, NOPERMS, TOOMANYITEMS, TOSSED, TOSSEDSPEED, TOSSING, TOSSINGSPEED, PRIORITYTOSS, NOSIGNS, WORLDGUARD, PLOTSQUARED + +} diff --git a/src/main/java/com/rifledluffy/chairs/messages/Messages.java b/src/main/java/com/rifledluffy/chairs/messages/Messages.java new file mode 100644 index 0000000..f2e9db6 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/messages/Messages.java @@ -0,0 +1,92 @@ +package com.rifledluffy.chairs.messages; + +public class Messages { + + private final static String occupied = "occupied-seat"; + private final static String tooFar = "too-far-from-seat"; + private final static String noPerms = "no-permission"; + private final static String tooMany = "too-many-items"; + private final static String tossed = "tossed-out-of-chair"; + private final static String tossedSpeed = "tossed-out-with-speed"; + private final static String tossing = "tossing-someone"; + private final static String tossingSpeed = "tossing-someone-with-speed"; + private final static String priority = "priority-replaced"; + private final static String noSigns = "no-sign-at-ends"; + private final static String worldGuard = "denied-by-worldguard"; + private final static String plotSquared = "denied-by-plotsquared"; + + private final static String defaultOccupied = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&a, my homie &7%seated%&c sits there."; + private final static String defaultTooFar = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!"; + private final static String defaultNoPerms = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!"; + private final static String defaultTooMany = "&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!"; + private final static String defaultTossed = "&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%."; + private final static String defaultTossedSpeed = "&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%."; + private final static String defaultTossing = "&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!"; + private final static String defaultTossingSpeed = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!"; + private final static String defaultPriority = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%"; + private final static String defaultNoSigns = "&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!"; + private final static String defaultWorldGuard = "&8[&6Rifle's Chairs&8] &cYou may not sit in this region!"; + private final static String defaultPlotSquared = "&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!"; + + public static String getDefault(MessageType type) { + switch (type) { + default: + return null; + case OCCUPIED: + return Messages.defaultOccupied; + case TOOFAR: + return Messages.defaultTooFar; + case NOPERMS: + return Messages.defaultNoPerms; + case TOOMANYITEMS: + return Messages.defaultTooMany; + case TOSSED: + return Messages.defaultTossed; + case TOSSEDSPEED: + return Messages.defaultTossedSpeed; + case TOSSING: + return Messages.defaultTossing; + case TOSSINGSPEED: + return Messages.defaultTossingSpeed; + case PRIORITYTOSS: + return Messages.defaultPriority; + case NOSIGNS: + return Messages.defaultNoSigns; + case WORLDGUARD: + return Messages.defaultWorldGuard; + case PLOTSQUARED: + return Messages.defaultPlotSquared; + } + } + + public static String getMessage(MessageType type) { + switch (type) { + default: + return null; + case OCCUPIED: + return Messages.occupied; + case TOOFAR: + return Messages.tooFar; + case NOPERMS: + return Messages.noPerms; + case TOOMANYITEMS: + return Messages.tooMany; + case TOSSED: + return Messages.tossed; + case TOSSEDSPEED: + return Messages.tossedSpeed; + case TOSSING: + return Messages.tossing; + case TOSSINGSPEED: + return Messages.tossingSpeed; + case PRIORITYTOSS: + return Messages.priority; + case NOSIGNS: + return Messages.noSigns; + case WORLDGUARD: + return Messages.worldGuard; + case PLOTSQUARED: + return Messages.plotSquared; + } + } +} diff --git a/src/com/rifledluffy/chairs/metrics/MetricsLite.java b/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java similarity index 95% rename from src/com/rifledluffy/chairs/metrics/MetricsLite.java rename to src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java index b433772..2c02906 100644 --- a/src/com/rifledluffy/chairs/metrics/MetricsLite.java +++ b/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java @@ -2,8 +2,8 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.entity.Player; +import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.java.JavaPlugin; import org.json.simple.JSONArray; @@ -17,6 +17,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Timer; import java.util.TimerTask; @@ -26,11 +27,20 @@ /** * bStats collects some data for plugin authors. - * + *

* Check out https://bStats.org/ to learn more about bStats! */ public class MetricsLite { + // The version of this bStats class + public static final int B_STATS_VERSION = 1; + // The url to which the data is sent + private static final String URL = "https://bStats.org/submitData/bukkit"; + // Should failed requests be logged? + private static boolean logFailedRequests; + // The uuid of the server + private static String serverUUID; + static { // You can use the property to disable the check in your test environment if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) { @@ -45,18 +55,6 @@ public class MetricsLite { } } - // The version of this bStats class - public static final int B_STATS_VERSION = 1; - - // The url to which the data is sent - private static final String URL = "https://bStats.org/submitData/bukkit"; - - // Should failed requests be logged? - private static boolean logFailedRequests; - - // The uuid of the server - private static String serverUUID; - // The plugin private final JavaPlugin plugin; @@ -95,7 +93,8 @@ public MetricsLite(JavaPlugin plugin) { ).copyDefaults(true); try { config.save(configFile); - } catch (IOException ignored) { } + } catch (IOException ignored) { + } } // Load the data @@ -109,7 +108,8 @@ public MetricsLite(JavaPlugin plugin) { service.getField("B_STATS_VERSION"); // Our identifier :) found = true; // We aren't the first break; - } catch (NoSuchFieldException ignored) { } + } catch (NoSuchFieldException ignored) { + } } // Register our service Bukkit.getServicesManager().register(MetricsLite.class, this, plugin, ServicePriority.Normal); @@ -120,6 +120,61 @@ public MetricsLite(JavaPlugin plugin) { } } + /** + * Sends the data to the bStats server. + * + * @param data The data to send. + * @throws Exception If the request failed. + */ + private static void sendData(JSONObject data) throws Exception { + if (data == null) { + throw new IllegalArgumentException("Data cannot be null!"); + } + if (Bukkit.isPrimaryThread()) { + throw new IllegalAccessException("This method must not be called from the main thread!"); + } + HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); + + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + + // Add headers + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format + connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); + + // Send data + connection.setDoOutput(true); + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + outputStream.write(compressedData); + outputStream.flush(); + outputStream.close(); + + connection.getInputStream().close(); // We don't care about the response - Just send our data :) + } + + /** + * Gzips the given String. + * + * @param str The string to gzip. + * @return The gzipped String. + * @throws IOException If the compression failed. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + GZIPOutputStream gzip = new GZIPOutputStream(outputStream); + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + gzip.close(); + return outputStream.toByteArray(); + } + /** * Starts the Scheduler which submits our data every 30 minutes. */ @@ -141,7 +196,7 @@ public void run() { } }); } - }, 1000*60*5, 1000*60*30); + }, 1000 * 60 * 5, 1000 * 60 * 30); // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! // WARNING: Just don't do it! @@ -154,7 +209,7 @@ public void run() { * @return The plugin specific data. */ @SuppressWarnings("unchecked") - public JSONObject getPluginData() { + public JSONObject getPluginData() { JSONObject data = new JSONObject(); String pluginName = plugin.getDescription().getName(); @@ -174,7 +229,7 @@ public JSONObject getPluginData() { * @return The server specific data. */ @SuppressWarnings("unchecked") - private JSONObject getServerData() { + private JSONObject getServerData() { // Minecraft specific data int playerAmount; try { @@ -219,7 +274,7 @@ private JSONObject getServerData() { * Collects the data and sends it afterwards. */ @SuppressWarnings("unchecked") - private void submitData() { + private void submitData() { final JSONObject data = getServerData(); JSONArray pluginData = new JSONArray(); @@ -231,10 +286,12 @@ private void submitData() { for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) { try { pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider())); - } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { + } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | + InvocationTargetException ignored) { } } - } catch (NoSuchFieldException ignored) { } + } catch (NoSuchFieldException ignored) { + } } data.put("plugins", pluginData); @@ -256,59 +313,4 @@ public void run() { }).start(); } - /** - * Sends the data to the bStats server. - * - * @param data The data to send. - * @throws Exception If the request failed. - */ - private static void sendData(JSONObject data) throws Exception { - if (data == null) { - throw new IllegalArgumentException("Data cannot be null!"); - } - if (Bukkit.isPrimaryThread()) { - throw new IllegalAccessException("This method must not be called from the main thread!"); - } - HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); - - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - - // Add headers - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format - connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); - - // Send data - connection.setDoOutput(true); - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - outputStream.write(compressedData); - outputStream.flush(); - outputStream.close(); - - connection.getInputStream().close(); // We don't care about the response - Just send our data :) - } - - /** - * Gzips the given String. - * - * @param str The string to gzip. - * @return The gzipped String. - * @throws IOException If the compression failed. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - GZIPOutputStream gzip = new GZIPOutputStream(outputStream); - gzip.write(str.getBytes("UTF-8")); - gzip.close(); - return outputStream.toByteArray(); - } - } diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java new file mode 100644 index 0000000..cdb2888 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -0,0 +1,318 @@ +package com.rifledluffy.chairs.utility; + +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.chairs.BlockFilter; +import com.rifledluffy.chairs.chairs.Chair; +import com.rifledluffy.chairs.config.ConfigManager; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Levelled; +import org.bukkit.block.data.type.Slab; +import org.bukkit.block.data.type.Stairs; +import org.bukkit.block.data.type.TrapDoor; +import org.bukkit.block.data.type.WallSign; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.util.Vector; + +import java.util.*; + +public class Util { + + private static final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); + private static final ConfigManager configManager = plugin.getConfigManager(); + + public static ConfigManager getConfigManager() { + return configManager; + } + + public static void debug(String message) { + for (Player player : plugin.getServer().getOnlinePlayers()) player.sendMessage(message); + } + + public static void debug(Object message) { + debug(message.toString()); + } + + public static void debug(List messages) { + messages.forEach(Util::debug); + } + + public static String replaceMessage(Player player, String string) { + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("%user%", player.getDisplayName()); + return string; + } + + public static String replaceMessage(Entity entity, Player target, String string) { + if (entity instanceof LivingEntity) return replaceMessage((LivingEntity) entity, target, string); + + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("%user%", entity.getName()); + string = string.replace("%seated%", target.getName()); + return string; + } + + public static String replaceMessage(LivingEntity entity, Player target, String string) { + if (entity instanceof Player) return replaceMessage((Player) entity, target, string); + + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("%user%", entity.getName()); + string = string.replace("%seated%", target.getName()); + return string; + } + + public static String replaceMessage(Player player, Player target, String string) { + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("%user%", player.getDisplayName()); + string = string.replace("%seated%", target.getName()); + return string; + } + + public static boolean validStair(Block block) { + if (!BlockFilter.validateStairs(block.getType())) return false; + Stairs stair = (Stairs) block.getState().getBlockData(); + return stair.getHalf() != Bisected.Half.TOP; + } + + public static boolean validSlab(Block block) { + if (!BlockFilter.validateSlab(block.getType())) return false; + Slab slab = (Slab) block.getState().getBlockData(); + return slab.getType() == Slab.Type.BOTTOM; + } + + public static boolean validCarpet(Block block) { + return BlockFilter.validateCarpet(block.getType()); + } + + private static boolean validatedChair(Block block) { + return BlockFilter.isStairsBlock(block.getType()) && validStair(block); + } + + public static boolean playerIsSeated(UUID uuid, Map chairMap) { + Chair chair = chairMap.get(uuid); + return chair != null; + } + + public static boolean nearLiquid(Block block) { + return isLiqiudOrMagma(block.getRelative(BlockFace.NORTH)) + || isLiqiudOrMagma(block.getRelative(BlockFace.EAST)) + || isLiqiudOrMagma(block.getRelative(BlockFace.SOUTH)) + || isLiqiudOrMagma(block.getRelative(BlockFace.WEST)); + } + + public static boolean surroundedBlock(Block block) { + return !validExit(block.getRelative(BlockFace.NORTH)) + && !validExit(block.getRelative(BlockFace.EAST)) + && !validExit(block.getRelative(BlockFace.SOUTH)) + && !validExit(block.getRelative(BlockFace.WEST)); + } + + private static boolean validExit(Block block) { + Material type = block.getType(); + return type == Material.AIR || type.name().equals("WALL_SIGN") || type.name().endsWith("_WALL_SIGN"); + } + + public static boolean isLiqiudOrMagma(Block block) { + return block.getBlockData() instanceof Levelled || block.getRelative(BlockFace.DOWN).getType() == Material.MAGMA_BLOCK; + } + + public static boolean validCouch(Block block) { + int validSides = 0; + if (!validatedChair(block)) return false; + Stairs stair = (Stairs) block.getState().getBlockData(); + + Set blockFaces = stair.getFaces(); + List faces = new ArrayList(blockFaces); + faces.remove(stair.getFacing()); + faces.remove(stair.getFacing().getOppositeFace()); + faces.remove(BlockFace.DOWN); + faces.remove(BlockFace.UP); + + BlockFace side = faces.get(0); + BlockFace otherSide = faces.get(1); + + if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return false; + + if (validatedChair(block.getRelative(side))) if (validSeat(block.getRelative(side), side, block)) validSides++; + if (validatedChair(block.getRelative(otherSide))) + if (validSeat(block.getRelative(otherSide), otherSide, block)) validSides++; + + if (!validatedChair(block.getRelative(side))) if (validSeat(block, side, block)) validSides++; + if (!validatedChair(block.getRelative(otherSide))) if (validSeat(block, otherSide, block)) validSides++; + return validSides == 2; + } + + public static boolean validSeat(Block block, BlockFace side, Block original) { + Stairs stair = (Stairs) block.getState().getBlockData(); + Stairs first = (Stairs) original.getState().getBlockData(); + if (stair.getFacing() != first.getFacing()) return false; + if (block.getRelative(side).getBlockData() instanceof WallSign || block.getRelative(side).getBlockData() instanceof TrapDoor) { + Directional sign = ((Directional) block.getRelative(side).getBlockData()); + return sign.getFacing() == side; + } else if (validatedChair(block.getRelative(side))) return validSeat(block.getRelative(side), side, original); + return false; + } + + public static boolean sameSeat(Player player, Block block, Map chairMap) { + Chair chair = chairMap.get(player.getUniqueId()); + if (chair == null) return false; + return chair.getLocation().equals(block.getLocation()); + } + + public static boolean samePosition(Block block, Block target) { + return block.getX() == target.getX() && block.getY() == target.getY() && block.getZ() == target.getZ(); + } + + public static boolean throneChair(Block block) { + if (!(block.getBlockData() instanceof Stairs)) return false; + if (block.getRelative(BlockFace.UP).getBlockData() instanceof TrapDoor trapDoor) { + if (!trapDoor.isOpen()) return false; + return trapDoor.getFacing().getOppositeFace() == ((Stairs) block.getBlockData()).getFacing(); + } + return false; + } + + public static boolean blockIsChair(Block block, List chairs) { + for (Chair chair : chairs) { + if (chair == null) continue; + if (chair.getLocation() == null) continue; + if (samePosition(block, chair.getBlock())) return true; + } + return false; + } + + public static Chair getChairFromBlock(Block block, List chairs) { + for (Chair chair : chairs) { + if (chair == null) continue; + if (chair.getLocation() == null) continue; + if (samePosition(chair.getBlock(), block)) return chair; + } + return null; + } + + public static ArmorStand generateFakeSeat(Chair chair) { + if (chair == null) return null; + Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); + Location seat = chair.getLocation(); + BlockFace facing = null; + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) + facing = ((Stairs) chair.getBlock().getState().getBlockData()).getFacing(); + Location playerLoc = chair.getPlayer().getEyeLocation(); + playerLoc.setPitch(0); + Vector vector; + if (facing != null) vector = getVectorFromFace(chair.getBlock(), facing.getOppositeFace()); + else vector = getVectorFromNearBlock(chair.getBlock(), playerLoc.getBlock()); + + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.stairSeatingPosition; + if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.carpetSeatingPosition; + if (BlockFilter.isSlabBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.slabSeatingPosition; + + //Thank you VicenteRD and carlpoole! + return seat.getWorld().spawn( + seat.clone().add(seatingPosition).setDirection(vector), + ArmorStand.class, + stand -> { + stand.setVisible(false); + stand.setGravity(false); + stand.setInvulnerable(true); + stand.setMarker(true); + stand.setCollidable(false); + }); + } + + public static ArmorStand generateFakeSeatDir(Chair chair, Vector dir) { + if (chair == null) return null; + Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); + Location seat = chair.getLocation(); + Location playerLoc = chair.getPlayer().getEyeLocation(); + playerLoc.setPitch(0); + + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.stairSeatingPosition; + if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.carpetSeatingPosition; + if (BlockFilter.isSlabBlock(chair.getBlock().getType())) + seatingPosition = plugin.chairManager.slabSeatingPosition; + + //Thank you VicenteRD and carlpoole! + return seat.getWorld().spawn( + seat.clone().add(seatingPosition).setDirection(dir), + ArmorStand.class, + stand -> { + stand.setVisible(false); + stand.setGravity(false); + stand.setInvulnerable(true); + stand.setMarker(true); + stand.setCollidable(false); + }); + } + + public static float getAbsoluteAngle(Location loc) { + float y = loc.getYaw(); + if (y < 0) y += 360; + y %= 360; + if (y <= 45 || y >= 315) return 0; + if (y >= 45 && y <= 135) return 90; + if (y >= 135 && y <= 225) return 180; + return 270; + } + + public static String getCardinalDirection(Location loc) { + float y = loc.getYaw(); + if (y < 0) y += 360; + y %= 360; + if (y <= 45 || y >= 315) return "south"; + if (y >= 45 && y <= 135) return "west"; + if (y >= 135 && y <= 225) return "north"; + return "east"; + } + + public static Block getBlockFromDirection(Block block, String direction) { + if (direction.equalsIgnoreCase("north")) return block.getRelative(BlockFace.NORTH); + else if (direction.equalsIgnoreCase("west")) return block.getRelative(BlockFace.WEST); + else if (direction.equalsIgnoreCase("east")) return block.getRelative(BlockFace.EAST); + else if (direction.equalsIgnoreCase("south")) return block.getRelative(BlockFace.SOUTH); + else if (direction.equalsIgnoreCase("down")) return block.getRelative(BlockFace.DOWN); + else if (direction.equalsIgnoreCase("up")) return block.getRelative(BlockFace.UP); + return block; + } + + public static boolean canFitPlayer(Block block) { + return block.getType() == Material.AIR && block.getRelative(BlockFace.UP).getType() == Material.AIR; + } + + public static boolean safePlace(Block block) { + return block.getRelative(BlockFace.DOWN).getType() != Material.AIR; + } + + public static Vector getVectorDir(Location caster, Location target) { + return target.clone().subtract(caster.toVector()).toVector(); + } + + public static Vector getVectorFromFace(Block block, BlockFace face) { + Location blockLoc = block.getLocation(); + Location faceLoc = block.getRelative(face).getLocation(); + return getVectorDir(blockLoc, faceLoc); + } + + public static Vector getVectorFromNearBlock(Block block, Block target) { + return target.getLocation().toVector().subtract(block.getLocation().toVector()); + } + + public static void callEvent(Event event) { + plugin.getServer().getPluginManager().callEvent(event); + } + +} diff --git a/config.yml b/src/main/resources/config.yml similarity index 98% rename from config.yml rename to src/main/resources/config.yml index 0fb2e9b..5d1d6f1 100644 --- a/config.yml +++ b/src/main/resources/config.yml @@ -58,5 +58,5 @@ allowed-chairs: - STAIRS* - SLAB* - CARPET* -blacklisted-chairs: [] -disabled-worlds: [] \ No newline at end of file +blacklisted-chairs: [ ] +disabled-worlds: [ ] \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties new file mode 100644 index 0000000..517fc8f --- /dev/null +++ b/src/main/resources/messages.properties @@ -0,0 +1,53 @@ +# Certain events occur when users use this plugin. Here you can define what messages might be said. +# +# Use %user% to refer to the user's name +# Use %seated% to refer to the seated's name +# +# General Events +# +# occupied-seat: Triggers when someone is already seated on the chair +# too-far-from-seat: Triggers when someone is too far to seat from their chair +# no-permission: Triggers when someone has no permission +# too-many-items: Triggers when someone sits with too large of an item stack +# +# Combat +# +# tossed-out-of-chair: Sends a message to the tossed player when they get tossed off +# Example: %user% tossed you out of your seat! +# Output; if Rifle hit you: Rifle tossed you out of your seat! +# +# tossed-out-with-speed: Sends a message to the tossed player but the tosser was running +# Example: %user% really knocked you of your seat! +# Output; if Rifle hit you: Rifle really knocked you of your seat! +# +# tossing-someone: Sends a message to the player that tossed someone off their chair +# Example: You tossed %seated% out of their chair! +# Output; if Rifle was sitting: You tossed Rifle out of their chair! +# +# tossing-someone-with-speed: Sends a message to the player that tossed someone off their chair with speed! +# Example: You really knocked %seated% out of their chair! +# Output; if Rifle was sitting: You really knocked Rifle out of their chair! +# +# Other Plugins +# +# denied-by-worldguard: called when worldguard blocks seating in a region. +# WorldGuard and WorldEdit must be enabled for these features to work! +temp-mute-duration=60 +mute-message-enabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!" +mute-message-disabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!" +toggle-message-enabled="&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!" +toggle-message-disabled="&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!" +occupied-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%, &amy homie &7%seated%&c sits there." +too-far-from-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!" +no-permission="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!" +too-many-items="&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!" +tossed-out-of-chair="&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%." +tossed-out-with-speed="&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%." +tossing-someone="&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!" +tossing-someone-with-speed="&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!" +priority-replaced="&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%" +no-sign-at-ends="&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!" +denied-by-worldguard="&8[&6Rifle's Chairs&8] &cYou may not sit in this region!" +denied-by-plotsquared="&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!" +denied-by-griefprevention="&8[&6Rifle's Chairs&8] &cYou may not sit in this claim!" + diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties new file mode 100644 index 0000000..517fc8f --- /dev/null +++ b/src/main/resources/messages_en.properties @@ -0,0 +1,53 @@ +# Certain events occur when users use this plugin. Here you can define what messages might be said. +# +# Use %user% to refer to the user's name +# Use %seated% to refer to the seated's name +# +# General Events +# +# occupied-seat: Triggers when someone is already seated on the chair +# too-far-from-seat: Triggers when someone is too far to seat from their chair +# no-permission: Triggers when someone has no permission +# too-many-items: Triggers when someone sits with too large of an item stack +# +# Combat +# +# tossed-out-of-chair: Sends a message to the tossed player when they get tossed off +# Example: %user% tossed you out of your seat! +# Output; if Rifle hit you: Rifle tossed you out of your seat! +# +# tossed-out-with-speed: Sends a message to the tossed player but the tosser was running +# Example: %user% really knocked you of your seat! +# Output; if Rifle hit you: Rifle really knocked you of your seat! +# +# tossing-someone: Sends a message to the player that tossed someone off their chair +# Example: You tossed %seated% out of their chair! +# Output; if Rifle was sitting: You tossed Rifle out of their chair! +# +# tossing-someone-with-speed: Sends a message to the player that tossed someone off their chair with speed! +# Example: You really knocked %seated% out of their chair! +# Output; if Rifle was sitting: You really knocked Rifle out of their chair! +# +# Other Plugins +# +# denied-by-worldguard: called when worldguard blocks seating in a region. +# WorldGuard and WorldEdit must be enabled for these features to work! +temp-mute-duration=60 +mute-message-enabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!" +mute-message-disabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!" +toggle-message-enabled="&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!" +toggle-message-disabled="&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!" +occupied-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%, &amy homie &7%seated%&c sits there." +too-far-from-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!" +no-permission="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!" +too-many-items="&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!" +tossed-out-of-chair="&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%." +tossed-out-with-speed="&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%." +tossing-someone="&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!" +tossing-someone-with-speed="&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!" +priority-replaced="&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%" +no-sign-at-ends="&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!" +denied-by-worldguard="&8[&6Rifle's Chairs&8] &cYou may not sit in this region!" +denied-by-plotsquared="&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!" +denied-by-griefprevention="&8[&6Rifle's Chairs&8] &cYou may not sit in this claim!" + diff --git a/plugin.yml b/src/main/resources/plugin.yml similarity index 83% rename from plugin.yml rename to src/main/resources/plugin.yml index 047cea7..9d43323 100644 --- a/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,15 +1,15 @@ main: com.rifledluffy.chairs.RFChairs name: RFChairs -version: 6.0 -authors: [Rifle D. Luffy, VicenteRD, carlpoole, i0xHeX] -api-version: 1.13 -description: Chairs but Rifle's way. -softdepend: [WorldGuard, WorldEdit] +api-version: '${apiVersion}' +version: ${version} +description: ${description} +authors: [ Rifle D. Luffy, VicenteRD, carlpoole, i0xHeX, GreensurvivorsTeam ] +softdepend: [ WorldGuard, WorldEdit ] commands: rfchairs: usage: / description: The main prefix for other commands. Type /rfchairs help for more info - aliases: [rfc] + aliases: [ rfc ] permissions: rfchairs.use: description: Use of chairs diff --git a/src/messages.yml b/src/messages.yml deleted file mode 100644 index 362c156..0000000 --- a/src/messages.yml +++ /dev/null @@ -1,53 +0,0 @@ -# Certain events occur when users use this plugin. Here you can define what messages might be said. -# -# Use %user% to refer to the user's name -# Use %seated% to refer to the seated's name -# -# General Events -# -# occupied-seat: Triggers when someone is already seated on the chair -# too-far-from-seat: Triggers when someone is too far to seat from their chair -# no-permission: Triggers when someone has no permission -# too-many-items: Triggers when someone sits with too large of an item stack -# -# Combat -# -# tossed-out-of-chair: Sends a message to the tossed player when they get tossed off -# Example: %user% tossed you out of your seat! -# Output; if Rifle hit you: Rifle tossed you out of your seat! -# -# tossed-out-with-speed: Sends a message to the tossed player but the tosser was running -# Example: %user% really knocked you of your seat! -# Output; if Rifle hit you: Rifle really knocked you of your seat! -# -# tossing-someone: Sends a message to the player that tossed someone off their chair -# Example: You tossed %seated% out of their chair! -# Output; if Rifle was sitting: You tossed Rifle out of their chair! -# -# tossing-someone-with-speed: Sends a message to the player that tossed someone off their chair with speed! -# Example: You really knocked %seated% out of their chair! -# Output; if Rifle was sitting: You really knocked Rifle out of their chair! -# -# Other Plugins -# -# denied-by-worldguard: called when worldguard blocks seating in a region. -# WorldGuard and WorldEdit must be enabled for these features to work! -temp-mute-duration: 60 -mute-message-enabled: "&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!" -mute-message-disabled: "&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!" -toggle-message-enabled: "&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!" -toggle-message-disabled: "&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!" -occupied-seat: "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%, &amy homie &7%seated%&c sits there." -too-far-from-seat: "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!" -no-permission: "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!" -too-many-items: "&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!" -tossed-out-of-chair: "&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%." -tossed-out-with-speed: "&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%." -tossing-someone: "&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!" -tossing-someone-with-speed: "&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!" -priority-replaced: "&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%" -no-sign-at-ends: "&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!" -denied-by-worldguard: "&8[&6Rifle's Chairs&8] &cYou may not sit in this region!" -denied-by-plotsquared: "&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!" -denied-by-griefprevention: "&8[&6Rifle's Chairs&8] &cYou may not sit in this claim!" - From 66cbf5fde81e38cb5b9f947b6f6177b26080d1e1 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Tue, 26 Mar 2024 23:18:54 +0100 Subject: [PATCH 02/18] Code style --- build.gradle.kts | 5 +- .../com/rifledluffy/chairs/ChairManager.java | 74 +++++---- .../rifledluffy/chairs/MessageManager.java | 16 +- .../java/com/rifledluffy/chairs/RFChairs.java | 29 ++-- .../chairs/chairs/BlockFilter.java | 50 ++---- .../com/rifledluffy/chairs/chairs/Chair.java | 40 +++-- .../chairs/command/CommandManager.java | 41 +++-- .../chairs/command/commands/HelpCommand.java | 52 +++--- .../chairs/command/commands/InfoCommand.java | 39 ++--- .../chairs/command/commands/MuteCommand.java | 43 +++-- .../command/commands/ReloadCommand.java | 52 +++--- .../chairs/command/commands/ResetCommand.java | 48 +++--- .../chairs/command/commands/SubCommand.java | 27 ++- .../command/commands/ToggleCommand.java | 45 +++-- .../chairs/config/ConfigManager.java | 13 +- .../chairs/events/ChairCheckEvent.java | 27 +-- .../chairs/events/ChairLeaveEvent.java | 20 +-- .../chairs/events/ChairReplaceEvent.java | 22 +-- .../chairs/events/ChairSitEvent.java | 18 +- .../chairs/events/ChairTossEvent.java | 31 ++-- .../chairs/managers/WorldGuardManager.java | 11 +- .../chairs/messages/MessageConstruct.java | 4 +- .../chairs/messages/MessageEvent.java | 33 ++-- .../chairs/messages/MessageType.java | 14 +- .../rifledluffy/chairs/messages/Messages.java | 91 ++++------ .../chairs/metrics/MetricsLite.java | 93 ++++------- .../com/rifledluffy/chairs/utility/Util.java | 155 +++++++++--------- 27 files changed, 504 insertions(+), 589 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b3a8e87..d07a54c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,10 +33,7 @@ repositories { dependencies { paperweight.paperDevBundle("$mainMCVersion.1-R0.1-SNAPSHOT") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") - //plotsquared - implementation(platform("com.intellectualsites.bom:bom-newest:1.42")) - compileOnly("com.intellectualsites.plotsquared:plotsquared-core") - compileOnly("com.intellectualsites.plotsquared:plotsquared-bukkit") { isTransitive = false } + compileOnly("org.jetbrains:annotations:24.1.0") } tasks { diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index bb695dc..3e34295 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -55,8 +55,8 @@ public class ChairManager implements Listener { private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); private boolean regenWhenSitting; //Update related - private boolean disableCurrentUpdate; - private boolean disableUpdates; + private boolean disableCurrentUpdate; //todo + private boolean disableUpdates; //todo //Kick them off their seat if they take damage private boolean canLaunch; //Toss them off their seat if they take damage @@ -139,7 +139,7 @@ public void onChairSit(ChairSitEvent event) { if (event.getPlayer() == null) return; if (plugin.hasWorldGuard()) if (!plugin.getWorldGuardManager().validateSeating(chair, event.getPlayer())) { - Util.callEvent(new MessageEvent(MessageType.WORLDGUARD, event.getPlayer())); + new MessageEvent(MessageType.WORLDGUARD, event.getPlayer()).callEvent(); return; } @@ -195,27 +195,33 @@ public void onToss(ChairTossEvent event) { boolean silent = event.isSilent(); ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, false); - Util.callEvent(leaveEvent); + leaveEvent.callEvent(); if (!silent) { MessageEvent messageEvent; MessageEvent otherEvent = null; if (attacker instanceof Player playerEntity) { - if (info != null && !info.isSprinting()) + if (info != null && !info.isSprinting()) { messageEvent = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, player, playerEntity); - else + } else { messageEvent = new MessageEvent(MessageType.TOSSEDSPEED, MessageConstruct.DEFENSIVE, player, playerEntity); + } - if (info != null && !info.isSprinting()) + if (info != null && !info.isSprinting()) { otherEvent = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, playerEntity, player); - else + } else { otherEvent = new MessageEvent(MessageType.TOSSINGSPEED, MessageConstruct.OFFENSIVE, playerEntity, player); + } } else messageEvent = new MessageEvent(MessageType.TOSSED, player, attacker); - Util.callEvent(messageEvent); - if (otherEvent != null) Util.callEvent(otherEvent); + messageEvent.callEvent(); + if (otherEvent != null) { + otherEvent.callEvent(); + } } - if (canToss) ejectPlayer(block, player, attacker); + if (canToss) { + ejectPlayer(block, player, attacker); + } } @EventHandler @@ -231,16 +237,16 @@ public void onChairReplace(ChairReplaceEvent event) { if (player.getUniqueId() == seated.getUniqueId()) return; ChairTossEvent tossEvent = new ChairTossEvent(chair, seated, player, null, true); - Util.callEvent(tossEvent); + tossEvent.callEvent(); MessageEvent tossed = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, seated, player); - Util.callEvent(tossed); + tossed.callEvent(); ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); - Util.callEvent(sitEvent); + sitEvent.callEvent(); MessageEvent tosser = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, player, seated); - Util.callEvent(tosser); + tosser.callEvent(); } @EventHandler @@ -250,35 +256,37 @@ public void onChairCheck(ChairCheckEvent event) { Block block = event.getBlock(); if (!player.hasPermission("rfchairs.use")) { - Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); + new MessageEvent(MessageType.NOPERMS, player).callEvent(); return; } if (player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) >= maxDistance) { - Util.callEvent(new MessageEvent(MessageType.TOOFAR, player)); + new MessageEvent(MessageType.TOOFAR, player).callEvent(); return; } if (maxItemSit > 0 && item.getAmount() > maxItemSit) { - Util.callEvent(new MessageEvent(MessageType.TOOMANYITEMS, player)); + new MessageEvent(MessageType.TOOMANYITEMS, player).callEvent(); return; } if (!Util.blockIsChair(block, chairs)) { ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); - Util.callEvent(sitEvent); + sitEvent.callEvent(); } else { Chair chair = Util.getChairFromBlock(block, chairs); if (chair == null) return; - if (chair.getFakeSeat() != null && chair.getFakeSeat().getPassengers().size() == 0) { + if (chair.getFakeSeat() != null && chair.getFakeSeat().getPassengers().isEmpty()) { chair.setPlayer(player); chair.getFakeSeat().addPassenger(player); - if (regenWhenSitting) player.addPotionEffect(regenEffect); + if (regenWhenSitting) { + player.addPotionEffect(regenEffect); + } return; } if (player.hasPermission("rfchairs.priority") && priorityIfHasPerm) { ChairReplaceEvent replaceEvent = new ChairReplaceEvent(chair, chair.getPlayer(), player); - Util.callEvent(replaceEvent); + replaceEvent.callEvent(); return; } if (chair.getPlayer() == null) return; @@ -292,14 +300,14 @@ public void onChairCheck(ChairCheckEvent event) { chair.getFakeSeat().addPassenger(player); } else { MessageEvent occupied = new MessageEvent(MessageType.OCCUPIED, MessageConstruct.OFFENSIVE, player, chair.getPlayer()); - Util.callEvent(occupied); + occupied.callEvent(); } } } @EventHandler public void onRightClick(PlayerInteractEvent event) { - if (disabledWorlds.size() > 0 && disabledWorlds.contains(event.getPlayer().getWorld())) return; + if (!disabledWorlds.isEmpty() && disabledWorlds.contains(event.getPlayer().getWorld())) return; if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (event.getPlayer().isSneaking()) return; if (event.getHand() != EquipmentSlot.HAND) return; @@ -327,7 +335,7 @@ public void onRightClick(PlayerInteractEvent event) { if (!Util.validCouch(block)) { if (!trapSeats) return; if (!Util.throneChair(block)) { - Util.callEvent(new MessageEvent(MessageType.NOSIGNS, player)); + new MessageEvent(MessageType.NOSIGNS, player).callEvent(); return; } } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; @@ -345,11 +353,11 @@ public void onRightClick(PlayerInteractEvent event) { if (event.getBlockFace() == BlockFace.DOWN) return; if (!player.hasPermission("rfchairs.use")) { - Util.callEvent(new MessageEvent(MessageType.NOPERMS, player)); + new MessageEvent(MessageType.NOPERMS, player).callEvent(); return; } - Util.callEvent(new ChairCheckEvent(block, player)); + new ChairCheckEvent(block, player).callEvent(); } @EventHandler @@ -377,7 +385,7 @@ public void onDismount(EntityDismountEvent event) { if (info.hasSource() && info.livingSource()) attacker = info.getLivingSource(); ChairTossEvent tossEvent = new ChairTossEvent(chairMap.get(player.getUniqueId()), player, attacker, info, false); - Util.callEvent(tossEvent); + tossEvent.callEvent(); tossed.remove(player.getUniqueId()); return; } @@ -389,7 +397,7 @@ public void onMove(PlayerMoveEvent event) { Player player = event.getPlayer(); if (leaving.contains(player.getUniqueId())) { ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chairMap.get(player.getUniqueId()), player, exitWhereFacing); - Util.callEvent(leaveEvent); + leaveEvent.callEvent(); leaving.remove(player.getUniqueId()); } } @@ -432,7 +440,7 @@ public void quit(PlayerQuitEvent event) { Player player = event.getPlayer(); Chair chair = chairMap.get(player.getUniqueId()); ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); - Util.callEvent(leaveEvent); + leaveEvent.callEvent(); } @EventHandler @@ -468,7 +476,7 @@ public void onDeath(PlayerDeathEvent event) { Player player = event.getEntity(); Chair chair = chairMap.get(player.getUniqueId()); ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); - Util.callEvent(leaveEvent); + leaveEvent.callEvent(); } /* @@ -534,7 +542,7 @@ private Block findExitPoint(Location entity, Block block) { void saveToggled() { List ids = new ArrayList<>(); - if (toggled == null || toggled.size() == 0) configManager.getData().set("Toggled", new ArrayList()); + if (toggled == null || toggled.isEmpty()) configManager.getData().set("Toggled", new ArrayList()); for (UUID id : toggled) ids.add(id.toString()); plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had toggled off."); configManager.getData().set("Toggled", ids); @@ -542,7 +550,7 @@ void saveToggled() { void loadToggled() { List toggled = configManager.getData().getStringList("Toggled"); - if (toggled.size() == 0) return; + if (toggled.isEmpty()) return; plugin.getServer().getLogger().info("[RFChairs] " + toggled.size() + " Players had toggled off. Adding Them..."); toggled.stream() diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java index 1ef7f8f..a4b2c15 100644 --- a/src/main/java/com/rifledluffy/chairs/MessageManager.java +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -11,29 +11,29 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class MessageManager implements Listener { - private final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private final List tempMute = new ArrayList(); - public List muted = new ArrayList(); + private final List tempMute = new ArrayList<>(); + public List muted = new ArrayList<>(); private ConfigManager configManager = plugin.getConfigManager(); public FileConfiguration messages = configManager.getMessages(); private boolean allowMessages; private int tempMuteDuration; - public void reload(RFChairs plugin) { + public void reload(@NotNull RFChairs plugin) { configManager = plugin.getConfigManager(); messages = configManager.getMessages(); allowMessages = configManager.getConfig().getBoolean("allow-custom-messages", true); tempMuteDuration = messages.getInt("temp-mute-duration", 0); } - private void tempMute(Player player) { + private void tempMute(@NotNull Player player) { int duration = tempMuteDuration; tempMute.add(player.getUniqueId()); BukkitRunnable runnable = new BukkitRunnable() { @@ -45,12 +45,12 @@ public void run() { runnable.runTaskLater(plugin, duration); } - private boolean tempMuted(Player player) { + private boolean tempMuted(@NotNull Player player) { return tempMute.contains(player.getUniqueId()); } @EventHandler - public void onMessage(MessageEvent event) { + public void onMessage(@NotNull MessageEvent event) { Player player = event.getPlayer(); if (tempMute.contains(player.getUniqueId())) event.setCancelled(true); if (event.isCancelled()) return; @@ -61,7 +61,7 @@ public void onMessage(MessageEvent event) { } } - private String processString(MessageEvent event) { + private String processString(@NotNull MessageEvent event) { MessageType type = event.getType(); MessageConstruct construct = event.getConstruct(); String string; diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 5746346..0bc00ea 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -13,13 +13,12 @@ import java.io.IOException; public class RFChairs extends JavaPlugin { - private static RFChairs instance; - public CommandManager commandManager; - public ConfigManager cfgManager; - public ChairManager chairManager; - public MessageManager messageManager; - public WorldGuardManager worldGuardManager; + private CommandManager commandManager; + private ConfigManager cfgManager; + private ChairManager chairManager; + private MessageManager messageManager; + private WorldGuardManager worldGuardManager; public static RFChairs getInstance() { return instance; @@ -53,9 +52,8 @@ private void loadWorldGuard() { @Override public void onEnable() { - @SuppressWarnings("unused") - MetricsLite metrics = new MetricsLite(this); + MetricsLite metrics = new MetricsLite(); commandManager = new CommandManager(); commandManager.setup(); @@ -102,7 +100,7 @@ public void loadConfigManager() { try { cfgManager.setup(); } catch (IOException e) { - e.printStackTrace(); + getInstance().getComponentLogger().info("Could not setup ConfigManager", e); } cfgManager.reloadConfig(); } @@ -115,6 +113,18 @@ public void setConfigManager(ConfigManager configManager) { this.cfgManager = configManager; } + public MessageManager getMessageManager() { + return messageManager; + } + + public ChairManager getChairManager() { + return chairManager; + } + + public CommandManager getCommandManager() { + return commandManager; + } + public WorldGuardManager getWorldGuardManager() { return this.worldGuardManager; } @@ -126,5 +136,4 @@ public void log(String string) { boolean hasWorldGuard() { return worldGuardManager != null; } - } diff --git a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java index 7929089..47dfa7c 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java @@ -2,37 +2,15 @@ import com.rifledluffy.chairs.RFChairs; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.EnumSet; import java.util.HashSet; import java.util.Set; public class BlockFilter { - - private static final Set carpetTypeSet; - private static final Set slabTypeSet; - private static final Set stairsTypeSet; - private static Set whitelist, blacklist; - - static { - carpetTypeSet = EnumSet.noneOf(Material.class); - slabTypeSet = EnumSet.noneOf(Material.class); - stairsTypeSet = EnumSet.noneOf(Material.class); - - Arrays.stream(Material.values()) - .filter(m -> !m.name().startsWith("LEGACY_")) - .forEach(m -> { - String name = m.name(); - if (name.endsWith("_CARPET")) - carpetTypeSet.add(m); - else if (name.endsWith("_SLAB")) - slabTypeSet.add(m); - else if (name.endsWith("_STAIRS")) - stairsTypeSet.add(m); - }); - } + private static Set<@NotNull String> whitelist, blacklist; public static void reload() { FileConfiguration config = RFChairs.getInstance().getConfig(); @@ -40,41 +18,41 @@ public static void reload() { blacklist = new HashSet<>(config.getStringList("blacklisted-chairs")); } - public static boolean isWhitelisted(Material type, String category) { + public static boolean isWhitelisted(@NotNull Material type, @NotNull String category) { if (whitelist.contains("ALL_" + category)) return true; return whitelist.contains(type.name()); } - public static boolean isBlacklisted(Material type, String category) { + public static boolean isBlacklisted(@NotNull Material type, @NotNull String category) { if (blacklist.contains("ALL_" + category)) return true; return blacklist.contains(type.name()); } // validate - public static boolean validateCarpet(Material type) { + public static boolean validateCarpet(@NotNull Material type) { return isWhitelisted(type, "CARPETS") && !isBlacklisted(type, "CARPET"); } - public static boolean validateSlab(Material type) { + public static boolean validateSlab(@NotNull Material type) { return isWhitelisted(type, "SLABS") && !isBlacklisted(type, "SLAB"); } - public static boolean validateStairs(Material type) { + public static boolean validateStairs(@NotNull Material type) { return isWhitelisted(type, "STAIRS") && !isBlacklisted(type, "STAIRS"); } // check - public static boolean isCarpetBlock(Material type) { - return carpetTypeSet.contains(type); + public static boolean isCarpetBlock(@NotNull Material type) { + return Tag.WOOL_CARPETS.isTagged(type); } - public static boolean isSlabBlock(Material type) { - return slabTypeSet.contains(type); + public static boolean isSlabBlock(@NotNull Material type) { + return Tag.SLABS.isTagged(type); } - public static boolean isStairsBlock(Material type) { - return stairsTypeSet.contains(type); + public static boolean isStairsBlock(@NotNull Material type) { + return Tag.STAIRS.isTagged(type); } } diff --git a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java index 6f08cfe..f4bb4e0 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java @@ -12,18 +12,19 @@ import org.bukkit.material.Stairs; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class Chair { - private final BukkitRunnable clear; private final int clearID; - private Location location; - private Block chair; + private @Nullable Location location; + private @Nullable Block chair; private ArmorStand fakeSeat = null; - private Player player; + private @Nullable Player player; - public Chair(Player player, Location location) { + public Chair(@NotNull Player player, @NotNull Location location) { this.location = location; this.player = player; this.chair = location.getBlock(); @@ -36,7 +37,9 @@ public void run() { clear(); return; } - if (fakeSeat.getPassengers().size() == 0) clear(); + if (fakeSeat.getPassengers().isEmpty()) { + clear(); + } } }; @@ -47,35 +50,35 @@ public void run() { * Getters */ - public ArmorStand getFakeSeat() { + public @Nullable ArmorStand getFakeSeat() { return fakeSeat; } - public void setFakeSeat(ArmorStand armorStand) { + public void setFakeSeat(@NotNull ArmorStand armorStand) { fakeSeat = armorStand; } - public Player getPlayer() { + public @Nullable Player getPlayer() { return player; } - public void setPlayer(Player player) { + public void setPlayer(@NotNull Player player) { this.player = player; } - public Block getBlock() { + public @Nullable Block getBlock() { return location.getBlock(); } - public BlockState getBlockState() { + public @Nullable BlockState getBlockState() { return chair.getState(); } - public BlockData getBlockData() { + public @Nullable BlockData getBlockData() { return chair.getState().getBlockData(); } - public BlockFace getFacing() { + public @Nullable BlockFace getFacing() { if (!BlockFilter.isStairsBlock(chair.getType())) return null; return ((Stairs) chair.getState().getData()).getFacing(); } @@ -84,7 +87,7 @@ public BlockFace getFacing() { * Setters */ - public Location getLocation() { + public @Nullable Location getLocation() { return location; } @@ -98,12 +101,13 @@ public boolean isOccupied() { public void clear() { if (fakeSeat != null) fakeSeat.remove(); - if (player != null) player.removePotionEffect(PotionEffectType.REGENERATION); + player.removePotionEffect(PotionEffectType.REGENERATION); chair = null; location = null; fakeSeat = null; player = null; - if (Bukkit.getScheduler().isCurrentlyRunning(clearID)) clear.cancel(); + if (Bukkit.getScheduler().isCurrentlyRunning(clearID)) { + clear.cancel(); + } } - } diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index d797e0f..7f5d49f 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -6,39 +6,32 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; public class CommandManager implements CommandExecutor { - private final ArrayList commands = new ArrayList<>(); - private final RFChairs plugin = RFChairs.getInstance(); - //Sub Commands - public String main = "rfchairs"; - public String help = "help"; - public String info = "info"; - public String reload = "reload"; - public String reset = "reset"; - public String toggle = "toggle"; - public String mute = "mute"; + private final String main = "rfchairs"; + private final @NotNull ArrayList<@NotNull SubCommand> commands = new ArrayList<>(); public CommandManager() { } public void setup() { - plugin.getCommand(main).setExecutor(this); + RFChairs.getInstance().getCommand(main).setExecutor(this); this.commands.add(new HelpCommand()); - this.commands.add(new InfoCommand()); + //this.commands.add(new InfoCommand()); this.commands.add(new ReloadCommand()); this.commands.add(new ResetCommand()); this.commands.add(new ToggleCommand()); this.commands.add(new MuteCommand()); } - public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNull String s, String[] args) { - + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { if (command.getName().equalsIgnoreCase(main)) { if (args.length == 0) { sender.sendMessage(ChatColor.RED + "Missing Arguments. Type /rfchairs help for info"); @@ -57,19 +50,25 @@ public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNul arrayList.addAll(Arrays.asList(args)); arrayList.remove(0); - try { - target.onCommand(sender, args); - } catch (Exception e) { - sender.sendMessage(ChatColor.RED + "An error has occurred."); - - e.printStackTrace(); + if (target.checkPermission(sender)) { + if (target.needsPlayer()) { + if (sender instanceof Player player) { + target.onPlayerCommand(player, args); + } else { + sender.sendMessage("You need to be a player to use this command!"); + } + } else { + target.onCommand(sender, args); + } + } else { + sender.sendMessage("No permission!"); } } return true; } - private SubCommand get(String name) { + private @Nullable SubCommand get(@NotNull String name) { for (SubCommand sc : this.commands) { if (sc.name().equalsIgnoreCase(name)) { return sc; diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java index 43cd291..bb82971 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java @@ -1,27 +1,14 @@ package com.rifledluffy.chairs.command.commands; -import com.rifledluffy.chairs.RFChairs; import net.md_5.bungee.api.ChatColor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; -public class HelpCommand extends SubCommand { +public class HelpCommand implements SubCommand { - private final RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { //todo check permissions! sender.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); sender.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); sender.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages [Console Can Cast]"); @@ -33,29 +20,32 @@ public void onCommand(ConsoleCommandSender sender, String[] args) { } @Override - public void onCommand(Player player, String[] args) { - player.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); - player.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); - player.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages"); - player.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs"); - player.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor"); - player.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor"); - player.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version"); - player.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + onCommand(player, args); } @Override - public String name() { - return plugin.commandManager.help; + public @NotNull String name() { + return "help"; } @Override - public String info() { - return null; + public @NotNull String info() { + return ""; } @Override - public String[] aliases() { + public @NotNull String @NotNull [] aliases() { return new String[0]; } + + @Override + public boolean needsPlayer() { + return false; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return true; + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java index 59ee5d4..d4aece3 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java @@ -1,46 +1,43 @@ package com.rifledluffy.chairs.command.commands; -import com.rifledluffy.chairs.RFChairs; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; -public class InfoCommand extends SubCommand { - - private final RFChairs plugin = RFChairs.getInstance(); +public class InfoCommand implements SubCommand { //todo @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("�cOnly players can use commands for this plugin."); } @Override - public void onCommand(Player player, String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public String name() { - return plugin.commandManager.info; + public @NotNull String name() { + return "info"; } @Override - public String info() { + public @NotNull String info() { return ""; } @Override - public String[] aliases() { + public String @NotNull [] aliases() { return new String[0]; } + @Override + public boolean needsPlayer() { + return true; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return permissible.hasPermission("rfchairs.info"); + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java index 469afc1..2391258 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java @@ -4,37 +4,23 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.utility.Util; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.UUID; -public class MuteCommand extends SubCommand { +public class MuteCommand implements SubCommand { - private final RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("�cOnly players can use commands for this plugin."); + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { } @Override - public void onCommand(Player player, String[] args) { - MessageManager messageManager = plugin.messageManager; + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + MessageManager messageManager = RFChairs.getInstance().getMessageManager(); List muted = messageManager.muted; String message; - if (!player.hasPermission("rfchairs.mute")) return; if (muted.contains(player.getUniqueId())) { String string = messageManager.messages.getString("mute-message-enabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!"); message = Util.replaceMessage(player, string); @@ -49,18 +35,27 @@ public void onCommand(Player player, String[] args) { } @Override - public String name() { - return plugin.commandManager.mute; + public @NotNull String name() { + return "mute"; } @Override - public String info() { + public @NotNull String info() { return ""; } @Override - public String[] aliases() { + public String @NotNull [] aliases() { return new String[0]; } + @Override + public boolean needsPlayer() { + return true; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return permissible.hasPermission("rfchairs.mute"); + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java index 67acdee..89dd0ca 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java @@ -5,60 +5,52 @@ import com.rifledluffy.chairs.config.ConfigManager; import net.md_5.bungee.api.ChatColor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; -public class ReloadCommand extends SubCommand { - +public class ReloadCommand implements SubCommand { private final RFChairs plugin = RFChairs.getInstance(); @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { ConfigManager newConfig = plugin.getConfigManager(); newConfig.reloadConfig(); newConfig.reloadMessages(); plugin.setConfigManager(newConfig); - plugin.chairManager.reload(plugin); - plugin.messageManager.reload(plugin); + BlockFilter.reload(); + plugin.getChairManager().reload(plugin); + plugin.getMessageManager().reload(plugin); sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); } @Override - public void onCommand(Player player, String[] args) { - if (!player.hasPermission("rfchairs.reload") && !player.hasPermission("rfchairs.manage")) return; - ConfigManager newConfig = plugin.getConfigManager(); - newConfig.reloadConfig(); - newConfig.reloadMessages(); - plugin.setConfigManager(newConfig); - BlockFilter.reload(); - plugin.chairManager.reload(plugin); - plugin.messageManager.reload(plugin); - player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + onCommand(player, args); } @Override - public String name() { - return plugin.commandManager.reload; + public @NotNull String name() { + return "reload"; } @Override - public String info() { + public @NotNull String info() { return "Reloads the config and messages"; } @Override - public String[] aliases() { + public String @NotNull [] aliases() { return new String[0]; } + @Override + public boolean needsPlayer() { + return false; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return permissible.hasPermission("rfchairs.reload") || permissible.hasPermission("rfchairs.manage"); + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java index dc78281..acbfb2b 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -3,53 +3,47 @@ import com.rifledluffy.chairs.RFChairs; import net.md_5.bungee.api.ChatColor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; -public class ResetCommand extends SubCommand { - +public class ResetCommand implements SubCommand { private final RFChairs plugin = RFChairs.getInstance(); - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - plugin.chairManager.clearFakeSeats(); - plugin.chairManager.clearFakeSeatsFromFile(plugin); + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + plugin.getChairManager().clearFakeSeats(); + plugin.getChairManager().clearFakeSeatsFromFile(plugin); plugin.getLogger().info("Chairs Reset!"); sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); } @Override - public void onCommand(Player player, String[] args) { - if (!player.hasPermission("rfchairs.reset") && !player.hasPermission("rfchairs.manage")) return; - plugin.chairManager.clearFakeSeats(); - plugin.chairManager.clearFakeSeatsFromFile(plugin); - plugin.getLogger().info("Chairs Reset!"); - player.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + onCommand(player, args); } @Override - public String name() { - return plugin.commandManager.reset; + public @NotNull String name() { + return "reset"; } @Override - public String info() { + public @NotNull String info() { return "Resets all chairs"; } @Override - public String[] aliases() { + public @NotNull String @NotNull [] aliases() { return new String[0]; } + @Override + public boolean needsPlayer() { + return false; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return permissible.hasPermission("rfchairs.reset") || permissible.hasPermission("rfchairs.manage"); + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java index fd6c341..6056732 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java @@ -1,27 +1,26 @@ package com.rifledluffy.chairs.command.commands; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; -public abstract class SubCommand { +/** + * / args[0] args[1] + */ +public interface SubCommand { - /* - / args[0] args[1] - */ + void onCommand(@NotNull CommandSender sender, @NotNull String[] args); - public SubCommand() { - } + void onPlayerCommand(@NotNull Player player, @NotNull String[] args); - public abstract void onCommand(CommandSender sender, String[] args); + @NotNull String name(); - public abstract void onCommand(ConsoleCommandSender sender, String[] args); + @NotNull String info(); - public abstract void onCommand(Player player, String[] args); + @NotNull String @NotNull [] aliases(); - public abstract String name(); + boolean needsPlayer(); - public abstract String info(); - - public abstract String[] aliases(); + boolean checkPermission(@NotNull Permissible permissible); } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java index 770c39e..93c3750 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java @@ -4,37 +4,23 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.utility.Util; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permissible; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.UUID; -public class ToggleCommand extends SubCommand { +public class ToggleCommand implements SubCommand { - private final RFChairs plugin = RFChairs.getInstance(); - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (sender instanceof Player) { - onCommand((Player) sender, args); - } else if (sender instanceof ConsoleCommandSender) { - onCommand((ConsoleCommandSender) sender, args); - } else { - } - } - - @Override - public void onCommand(ConsoleCommandSender sender, String[] args) { - sender.sendMessage("�cOnly players can use commands for this plugin."); + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { } @Override - public void onCommand(Player player, String[] args) { - MessageManager messageManager = plugin.messageManager; - List toggled = plugin.chairManager.toggled; + public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + MessageManager messageManager = RFChairs.getInstance().getMessageManager(); + List toggled = RFChairs.getInstance().getChairManager().toggled; String message; - if (!player.hasPermission("rfchairs.toggle")) return; if (toggled.contains(player.getUniqueId())) { String string = messageManager.messages.getString("toggle-message-enabled", "&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!"); message = Util.replaceMessage(player, string); @@ -49,18 +35,27 @@ public void onCommand(Player player, String[] args) { } @Override - public String name() { - return plugin.commandManager.toggle; + public @NotNull String name() { + return "toggle"; } @Override - public String info() { + public @NotNull String info() { return ""; } @Override - public String[] aliases() { + public @NotNull String @NotNull [] aliases() { return new String[0]; } + @Override + public boolean needsPlayer() { + return true; + } + + @Override + public boolean checkPermission(@NotNull Permissible permissible) { + return permissible.hasPermission("rfchairs.toggle"); + } } diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index 97d6be9..ffce901 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -11,17 +11,16 @@ import java.io.IOException; public class ConfigManager { - private final JavaPlugin plugin = RFChairs.getPlugin(RFChairs.class); - FileConfiguration config; + private FileConfiguration config; /* * Configuration Files */ - File configFile; - FileConfiguration fake; - File fakeFile; - FileConfiguration message; - File messageFile; + private File configFile; + private FileConfiguration fake; + private File fakeFile; + private FileConfiguration message; + private File messageFile; public void setup() throws IOException { configFile = new File(plugin.getDataFolder(), "config.yml"); diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java index b53ffca..cbba584 100644 --- a/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java +++ b/src/main/java/com/rifledluffy/chairs/events/ChairCheckEvent.java @@ -5,42 +5,45 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ChairCheckEvent extends Event { + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @Nullable Chair chair; + private final @Nullable Block block; + private final @NotNull Player player; - private static final HandlerList handlers = new HandlerList(); - Chair chair; - Block block; - Player player; - - public ChairCheckEvent(Chair chair, Player player) { + public ChairCheckEvent(@NotNull Chair chair, @NotNull Player player) { this.chair = chair; + this.block = null; this.player = player; } - public ChairCheckEvent(Block block, Player player) { + public ChairCheckEvent(@NotNull Block block, @NotNull Player player) { + this.chair = null; this.block = block; this.player = player; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public Chair getChair() { + public @Nullable Chair getChair() { return this.chair; } - public Block getBlock() { + public @Nullable Block getBlock() { return this.block; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } } diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java index b68f7cf..623cb0b 100644 --- a/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java +++ b/src/main/java/com/rifledluffy/chairs/events/ChairLeaveEvent.java @@ -4,34 +4,34 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; public class ChairLeaveEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - private final Chair chair; - private final Player player; + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull Chair chair; + private final @NotNull Player player; private boolean exitWhereFacing = false; - public ChairLeaveEvent(Chair chair, Player player, boolean flag) { + public ChairLeaveEvent(@NotNull Chair chair, @NotNull Player player, boolean flag) { this.chair = chair; this.player = player; this.exitWhereFacing = flag; } - public ChairLeaveEvent(Chair chair, Player player) { + public ChairLeaveEvent(@NotNull Chair chair, @NotNull Player player) { this.chair = chair; this.player = player; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public Chair getChair() { + public @NotNull Chair getChair() { return this.chair; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } @@ -40,7 +40,7 @@ public boolean exitWhereFacing() { } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } } diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java index de66626..d88ea77 100644 --- a/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java +++ b/src/main/java/com/rifledluffy/chairs/events/ChairReplaceEvent.java @@ -4,38 +4,38 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; public class ChairReplaceEvent extends Event { + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull Chair chair; + private final @NotNull Player replaced; + private final @NotNull Player player; - private static final HandlerList handlers = new HandlerList(); - Chair chair; - Player replaced; - Player player; - - public ChairReplaceEvent(Chair chair, Player replaced, Player player) { + public ChairReplaceEvent(@NotNull Chair chair, @NotNull Player replaced, @NotNull Player player) { this.chair = chair; this.replaced = replaced; this.player = player; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public Chair getChair() { + public @NotNull Chair getChair() { return this.chair; } - public Player getReplaced() { + public @NotNull Player getReplaced() { return this.replaced; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } } diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java index 3032c70..4c14e34 100644 --- a/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java +++ b/src/main/java/com/rifledluffy/chairs/events/ChairSitEvent.java @@ -4,32 +4,32 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; public class ChairSitEvent extends Event { + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull Chair chair; + private final @NotNull Player player; - private static final HandlerList handlers = new HandlerList(); - Chair chair; - Player player; - - public ChairSitEvent(Chair chair, Player player) { + public ChairSitEvent(@NotNull Chair chair, @NotNull Player player) { this.chair = chair; this.player = player; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public Chair getChair() { + public @NotNull Chair getChair() { return this.chair; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } } diff --git a/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java b/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java index 50129c3..f647825 100644 --- a/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java +++ b/src/main/java/com/rifledluffy/chairs/events/ChairTossEvent.java @@ -6,17 +6,18 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ChairTossEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - Chair chair; - Player player; - Entity attacker; - TargetInfo info; - boolean silent; - - public ChairTossEvent(Chair chair, Player player, Entity attacker, TargetInfo info, boolean flag) { + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull Chair chair; + private final @NotNull Player player; + private final @NotNull Entity attacker; + private final @Nullable TargetInfo info; + private final boolean silent; + + public ChairTossEvent(@NotNull Chair chair, @NotNull Player player, @NotNull Entity attacker, @Nullable TargetInfo info, boolean flag) { this.chair = chair; this.player = player; this.attacker = attacker; @@ -24,23 +25,23 @@ public ChairTossEvent(Chair chair, Player player, Entity attacker, TargetInfo in this.silent = flag; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public Chair getChair() { + public @NotNull Chair getChair() { return this.chair; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } - public Entity getAttacker() { + public @NotNull Entity getAttacker() { return this.attacker; } - public TargetInfo getInfo() { + public @Nullable TargetInfo getInfo() { return this.info; } @@ -49,7 +50,7 @@ public boolean isSilent() { } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } } diff --git a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java index 933d256..188d2f9 100644 --- a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java +++ b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java @@ -16,16 +16,11 @@ import org.bukkit.plugin.Plugin; import java.util.List; -import java.util.stream.Collectors; public class WorldGuardManager { - - @SuppressWarnings("rawtypes") - public static Flag flag; + public static StateFlag flag; private final RFChairs plugin = RFChairs.getInstance(); public WorldGuard worldGuard; - public WorldGuardPlugin worldGuardPlugin; - public RegionContainer container; public WorldGuardManager() { } @@ -65,9 +60,9 @@ public boolean validateSeating(Chair chair, Player player) { List regionSetList = getContainer().getLoaded().stream() .map(manager -> manager.getApplicableRegions(vector3)) - .collect(Collectors.toList()); + .toList(); - if (regionSetList.size() == 0) return true; + if (regionSetList.isEmpty()) return true; return regionSetList.stream() .allMatch(set -> set.testState(localPlayer, (StateFlag) worldManager.getFlag())); diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java b/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java index 8588cc1..5ed5fa9 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java @@ -1,5 +1,7 @@ package com.rifledluffy.chairs.messages; public enum MessageConstruct { - SINGLE, OFFENSIVE, DEFENSIVE + DEFENSIVE, + OFFENSIVE, + SINGLE } diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java index 1ded62b..eaa1552 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java @@ -5,59 +5,60 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class MessageEvent extends Event implements Cancellable { + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull MessageType type; + private final @NotNull MessageConstruct construct; + private final @NotNull Player player; + private final @Nullable Entity other; + private boolean cancelled; - private static final HandlerList handlers = new HandlerList(); - boolean cancelled; - MessageType type; - MessageConstruct construct; - Player player; - Entity other; - - public MessageEvent(MessageType type, MessageConstruct construct, Player player, Player other) { + public MessageEvent(@NotNull MessageType type, @NotNull MessageConstruct construct, @NotNull Player player, @NotNull Player other) { this.type = type; this.construct = construct; this.player = player; this.other = other; } - public MessageEvent(MessageType type, Player player, Entity other) { + public MessageEvent(@NotNull MessageType type, @NotNull Player player, @NotNull Entity other) { this.type = type; this.construct = MessageConstruct.DEFENSIVE; this.player = player; this.other = other; } - public MessageEvent(MessageType type, Player player) { + public MessageEvent(@NotNull MessageType type, @NotNull Player player) { this.type = type; this.construct = MessageConstruct.SINGLE; this.player = player; this.other = null; } - static public HandlerList getHandlerList() { + static public @NotNull HandlerList getHandlerList() { return handlers; } - public MessageType getType() { + public @NotNull MessageType getType() { return this.type; } - public MessageConstruct getConstruct() { + public @NotNull MessageConstruct getConstruct() { return this.construct; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return this.player; } - public Entity getEntity() { + public @Nullable Entity getEntity() { return this.other; } @Override - public HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageType.java b/src/main/java/com/rifledluffy/chairs/messages/MessageType.java index 95fad42..24c44d0 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageType.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageType.java @@ -1,7 +1,15 @@ package com.rifledluffy.chairs.messages; public enum MessageType { - - OCCUPIED, TOOFAR, NOPERMS, TOOMANYITEMS, TOSSED, TOSSEDSPEED, TOSSING, TOSSINGSPEED, PRIORITYTOSS, NOSIGNS, WORLDGUARD, PLOTSQUARED - + NOPERMS, + NOSIGNS, + OCCUPIED, + PRIORITYTOSS, + TOOFAR, + TOOMANYITEMS, + TOSSED, + TOSSEDSPEED, + TOSSING, + TOSSINGSPEED, + WORLDGUARD } diff --git a/src/main/java/com/rifledluffy/chairs/messages/Messages.java b/src/main/java/com/rifledluffy/chairs/messages/Messages.java index f2e9db6..72bcefe 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/Messages.java +++ b/src/main/java/com/rifledluffy/chairs/messages/Messages.java @@ -1,7 +1,8 @@ package com.rifledluffy.chairs.messages; -public class Messages { +import org.jetbrains.annotations.NotNull; +public class Messages { private final static String occupied = "occupied-seat"; private final static String tooFar = "too-far-from-seat"; private final static String noPerms = "no-permission"; @@ -13,7 +14,6 @@ public class Messages { private final static String priority = "priority-replaced"; private final static String noSigns = "no-sign-at-ends"; private final static String worldGuard = "denied-by-worldguard"; - private final static String plotSquared = "denied-by-plotsquared"; private final static String defaultOccupied = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&a, my homie &7%seated%&c sits there."; private final static String defaultTooFar = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!"; @@ -26,67 +26,36 @@ public class Messages { private final static String defaultPriority = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%"; private final static String defaultNoSigns = "&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!"; private final static String defaultWorldGuard = "&8[&6Rifle's Chairs&8] &cYou may not sit in this region!"; - private final static String defaultPlotSquared = "&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!"; - public static String getDefault(MessageType type) { - switch (type) { - default: - return null; - case OCCUPIED: - return Messages.defaultOccupied; - case TOOFAR: - return Messages.defaultTooFar; - case NOPERMS: - return Messages.defaultNoPerms; - case TOOMANYITEMS: - return Messages.defaultTooMany; - case TOSSED: - return Messages.defaultTossed; - case TOSSEDSPEED: - return Messages.defaultTossedSpeed; - case TOSSING: - return Messages.defaultTossing; - case TOSSINGSPEED: - return Messages.defaultTossingSpeed; - case PRIORITYTOSS: - return Messages.defaultPriority; - case NOSIGNS: - return Messages.defaultNoSigns; - case WORLDGUARD: - return Messages.defaultWorldGuard; - case PLOTSQUARED: - return Messages.defaultPlotSquared; - } + public static @NotNull String getDefault(@NotNull MessageType type) { + return switch (type) { + case OCCUPIED -> Messages.defaultOccupied; + case TOOFAR -> Messages.defaultTooFar; + case NOPERMS -> Messages.defaultNoPerms; + case TOOMANYITEMS -> Messages.defaultTooMany; + case TOSSED -> Messages.defaultTossed; + case TOSSEDSPEED -> Messages.defaultTossedSpeed; + case TOSSING -> Messages.defaultTossing; + case TOSSINGSPEED -> Messages.defaultTossingSpeed; + case PRIORITYTOSS -> Messages.defaultPriority; + case NOSIGNS -> Messages.defaultNoSigns; + case WORLDGUARD -> Messages.defaultWorldGuard; + }; } - public static String getMessage(MessageType type) { - switch (type) { - default: - return null; - case OCCUPIED: - return Messages.occupied; - case TOOFAR: - return Messages.tooFar; - case NOPERMS: - return Messages.noPerms; - case TOOMANYITEMS: - return Messages.tooMany; - case TOSSED: - return Messages.tossed; - case TOSSEDSPEED: - return Messages.tossedSpeed; - case TOSSING: - return Messages.tossing; - case TOSSINGSPEED: - return Messages.tossingSpeed; - case PRIORITYTOSS: - return Messages.priority; - case NOSIGNS: - return Messages.noSigns; - case WORLDGUARD: - return Messages.worldGuard; - case PLOTSQUARED: - return Messages.plotSquared; - } + public static @NotNull String getMessage(@NotNull MessageType type) { + return switch (type) { + case OCCUPIED -> Messages.occupied; + case TOOFAR -> Messages.tooFar; + case NOPERMS -> Messages.noPerms; + case TOOMANYITEMS -> Messages.tooMany; + case TOSSED -> Messages.tossed; + case TOSSEDSPEED -> Messages.tossedSpeed; + case TOSSING -> Messages.tossing; + case TOSSINGSPEED -> Messages.tossingSpeed; + case PRIORITYTOSS -> Messages.priority; + case NOSIGNS -> Messages.noSigns; + case WORLDGUARD -> Messages.worldGuard; + }; } } diff --git a/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java b/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java index 2c02906..4cc8c23 100644 --- a/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java +++ b/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java @@ -1,11 +1,14 @@ package com.rifledluffy.chairs.metrics; +import com.rifledluffy.chairs.RFChairs; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.ServicePriority; -import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -18,24 +21,20 @@ import java.lang.reflect.Method; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; +import java.util.*; import java.util.logging.Level; import java.util.zip.GZIPOutputStream; /** * bStats collects some data for plugin authors. *

- * Check out https://bStats.org/ to learn more about bStats! + * Check out bStats.org to learn more about bStats! */ public class MetricsLite { - // The version of this bStats class public static final int B_STATS_VERSION = 1; // The url to which the data is sent - private static final String URL = "https://bStats.org/submitData/bukkit"; + private static final @NotNull String URL = "https://bStats.org/submitData/bukkit"; // Should failed requests be logged? private static boolean logFailedRequests; // The uuid of the server @@ -44,7 +43,7 @@ public class MetricsLite { static { // You can use the property to disable the check in your test environment if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) { - // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D + // Mavens Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D final String defaultPackage = new String( new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'}); final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); @@ -55,22 +54,9 @@ public class MetricsLite { } } - // The plugin - private final JavaPlugin plugin; - - /** - * Class constructor. - * - * @param plugin The plugin which stats should be submitted. - */ - public MetricsLite(JavaPlugin plugin) { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null!"); - } - this.plugin = plugin; - + public MetricsLite() { // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File bStatsFolder = new File(RFChairs.getInstance().getDataFolder().getParentFile(), "bStats"); File configFile = new File(bStatsFolder, "config.yml"); YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); @@ -85,11 +71,13 @@ public MetricsLite(JavaPlugin plugin) { config.addDefault("logFailedRequests", false); // Inform the server owners about bStats - config.options().header( - "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + - "To honor their work, you should not disable it.\n" + - "This has nearly no effect on the server performance!\n" + - "Check out https://bStats.org/ to learn more :)" + config.options().setHeader( + List.of( + "bStats collects some data for plugin authors like how many servers are using their plugins.", + "To honor their work, you should not disable it.", + "This has nearly no effect on the server performance!", + "Check out https://bStats.org/ to learn more :)") + ).copyDefaults(true); try { config.save(configFile); @@ -112,7 +100,7 @@ public MetricsLite(JavaPlugin plugin) { } } // Register our service - Bukkit.getServicesManager().register(MetricsLite.class, this, plugin, ServicePriority.Normal); + Bukkit.getServicesManager().register(MetricsLite.class, this, RFChairs.getInstance(), ServicePriority.Normal); if (!found) { // We are the first! startSubmitting(); @@ -126,10 +114,7 @@ public MetricsLite(JavaPlugin plugin) { * @param data The data to send. * @throws Exception If the request failed. */ - private static void sendData(JSONObject data) throws Exception { - if (data == null) { - throw new IllegalArgumentException("Data cannot be null!"); - } + private static void sendData(@NotNull JSONObject data) throws Exception { if (Bukkit.isPrimaryThread()) { throw new IllegalAccessException("This method must not be called from the main thread!"); } @@ -164,7 +149,8 @@ private static void sendData(JSONObject data) throws Exception { * @return The gzipped String. * @throws IOException If the compression failed. */ - private static byte[] compress(final String str) throws IOException { + @Contract("null -> null; !null -> !null") + private static byte @Nullable [] compress(final @Nullable String str) throws IOException { if (str == null) { return null; } @@ -183,18 +169,13 @@ private void startSubmitting() { timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - if (!plugin.isEnabled()) { // Plugin was disabled + if (!RFChairs.getInstance().isEnabled()) { // Plugin was disabled timer.cancel(); return; } // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) - Bukkit.getScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - submitData(); - } - }); + Bukkit.getScheduler().runTask(RFChairs.getInstance(), () -> submitData()); } }, 1000 * 60 * 5, 1000 * 60 * 30); // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start @@ -209,11 +190,11 @@ public void run() { * @return The plugin specific data. */ @SuppressWarnings("unchecked") - public JSONObject getPluginData() { + public @NotNull JSONObject getPluginData() { JSONObject data = new JSONObject(); - String pluginName = plugin.getDescription().getName(); - String pluginVersion = plugin.getDescription().getVersion(); + String pluginName = RFChairs.getInstance().getDescription().getName(); + String pluginVersion = RFChairs.getInstance().getDescription().getVersion(); data.put("pluginName", pluginName); // Append the name of the plugin data.put("pluginVersion", pluginVersion); // Append the version of the plugin @@ -229,7 +210,7 @@ public JSONObject getPluginData() { * @return The server specific data. */ @SuppressWarnings("unchecked") - private JSONObject getServerData() { + private @NotNull JSONObject getServerData() { // Minecraft specific data int playerAmount; try { @@ -297,20 +278,16 @@ private void submitData() { data.put("plugins", pluginData); // Create a new thread for the connection to the bStats server - new Thread(new Runnable() { - @Override - public void run() { - try { - // Send the data - sendData(data); - } catch (Exception e) { - // Something went wrong! :( - if (logFailedRequests) { - plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e); - } + new Thread(() -> { + try { + // Send the data + sendData(data); + } catch (Exception e) { + // Something went wrong! :( + if (logFailedRequests) { + RFChairs.getInstance().getLogger().log(Level.WARNING, "Could not submit plugin stats of " + RFChairs.getInstance().getName(), e); } } }).start(); } - } diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java index cdb2888..edb5816 100644 --- a/src/main/java/com/rifledluffy/chairs/utility/Util.java +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -3,7 +3,6 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.chairs.BlockFilter; import com.rifledluffy.chairs.chairs.Chair; -import com.rifledluffy.chairs.config.ConfigManager; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; @@ -20,39 +19,35 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.event.Event; import org.bukkit.util.Vector; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; public class Util { - - private static final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private static final ConfigManager configManager = plugin.getConfigManager(); - - public static ConfigManager getConfigManager() { - return configManager; - } - - public static void debug(String message) { - for (Player player : plugin.getServer().getOnlinePlayers()) player.sendMessage(message); + public static void debug(@NotNull String message) { + for (Player player : RFChairs.getInstance().getServer().getOnlinePlayers()) { + player.sendMessage(message); + } } - public static void debug(Object message) { + public static void debug(@NotNull Object message) { debug(message.toString()); } - public static void debug(List messages) { + public static void debug(@NotNull List<@NotNull Object> messages) { messages.forEach(Util::debug); } - public static String replaceMessage(Player player, String string) { + public static @NotNull String replaceMessage(@NotNull Player player, @NotNull String string) { string = ChatColor.translateAlternateColorCodes('&', string); string = string.replace("%user%", player.getDisplayName()); return string; } - public static String replaceMessage(Entity entity, Player target, String string) { + public static String replaceMessage(@NotNull Entity entity, @NotNull Player target, @NotNull String string) { if (entity instanceof LivingEntity) return replaceMessage((LivingEntity) entity, target, string); string = ChatColor.translateAlternateColorCodes('&', string); @@ -61,7 +56,7 @@ public static String replaceMessage(Entity entity, Player target, String string) return string; } - public static String replaceMessage(LivingEntity entity, Player target, String string) { + public static String replaceMessage(@NotNull LivingEntity entity, @NotNull Player target, @NotNull String string) { if (entity instanceof Player) return replaceMessage((Player) entity, target, string); string = ChatColor.translateAlternateColorCodes('&', string); @@ -70,68 +65,68 @@ public static String replaceMessage(LivingEntity entity, Player target, String s return string; } - public static String replaceMessage(Player player, Player target, String string) { + public static String replaceMessage(@NotNull Player player, @NotNull Player target, @NotNull String string) { string = ChatColor.translateAlternateColorCodes('&', string); string = string.replace("%user%", player.getDisplayName()); string = string.replace("%seated%", target.getName()); return string; } - public static boolean validStair(Block block) { + public static boolean validStair(@NotNull Block block) { if (!BlockFilter.validateStairs(block.getType())) return false; Stairs stair = (Stairs) block.getState().getBlockData(); return stair.getHalf() != Bisected.Half.TOP; } - public static boolean validSlab(Block block) { + public static boolean validSlab(@NotNull Block block) { if (!BlockFilter.validateSlab(block.getType())) return false; Slab slab = (Slab) block.getState().getBlockData(); return slab.getType() == Slab.Type.BOTTOM; } - public static boolean validCarpet(Block block) { + public static boolean validCarpet(@NotNull Block block) { return BlockFilter.validateCarpet(block.getType()); } - private static boolean validatedChair(Block block) { + private static boolean validatedChair(@NotNull Block block) { return BlockFilter.isStairsBlock(block.getType()) && validStair(block); } - public static boolean playerIsSeated(UUID uuid, Map chairMap) { + public static boolean playerIsSeated(@NotNull UUID uuid, @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap) { Chair chair = chairMap.get(uuid); return chair != null; } - public static boolean nearLiquid(Block block) { - return isLiqiudOrMagma(block.getRelative(BlockFace.NORTH)) - || isLiqiudOrMagma(block.getRelative(BlockFace.EAST)) - || isLiqiudOrMagma(block.getRelative(BlockFace.SOUTH)) - || isLiqiudOrMagma(block.getRelative(BlockFace.WEST)); + public static boolean nearLiquid(@NotNull Block block) { + return isLiquidOrMagma(block.getRelative(BlockFace.NORTH)) + || isLiquidOrMagma(block.getRelative(BlockFace.EAST)) + || isLiquidOrMagma(block.getRelative(BlockFace.SOUTH)) + || isLiquidOrMagma(block.getRelative(BlockFace.WEST)); } - public static boolean surroundedBlock(Block block) { + public static boolean surroundedBlock(@NotNull Block block) { return !validExit(block.getRelative(BlockFace.NORTH)) && !validExit(block.getRelative(BlockFace.EAST)) && !validExit(block.getRelative(BlockFace.SOUTH)) && !validExit(block.getRelative(BlockFace.WEST)); } - private static boolean validExit(Block block) { + private static boolean validExit(@NotNull Block block) { Material type = block.getType(); return type == Material.AIR || type.name().equals("WALL_SIGN") || type.name().endsWith("_WALL_SIGN"); } - public static boolean isLiqiudOrMagma(Block block) { + public static boolean isLiquidOrMagma(@NotNull Block block) { return block.getBlockData() instanceof Levelled || block.getRelative(BlockFace.DOWN).getType() == Material.MAGMA_BLOCK; } - public static boolean validCouch(Block block) { + public static boolean validCouch(@NotNull Block block) { int validSides = 0; if (!validatedChair(block)) return false; Stairs stair = (Stairs) block.getState().getBlockData(); Set blockFaces = stair.getFaces(); - List faces = new ArrayList(blockFaces); + List faces = new ArrayList<>(blockFaces); faces.remove(stair.getFacing()); faces.remove(stair.getFacing().getOppositeFace()); faces.remove(BlockFace.DOWN); @@ -151,7 +146,7 @@ public static boolean validCouch(Block block) { return validSides == 2; } - public static boolean validSeat(Block block, BlockFace side, Block original) { + public static boolean validSeat(@NotNull Block block, @NotNull BlockFace side, @NotNull Block original) { Stairs stair = (Stairs) block.getState().getBlockData(); Stairs first = (Stairs) original.getState().getBlockData(); if (stair.getFacing() != first.getFacing()) return false; @@ -162,17 +157,17 @@ public static boolean validSeat(Block block, BlockFace side, Block original) { return false; } - public static boolean sameSeat(Player player, Block block, Map chairMap) { + public static boolean sameSeat(@NotNull Player player, @NotNull Block block, @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap) { Chair chair = chairMap.get(player.getUniqueId()); if (chair == null) return false; return chair.getLocation().equals(block.getLocation()); } - public static boolean samePosition(Block block, Block target) { + public static boolean samePosition(@NotNull Block block, @NotNull Block target) { return block.getX() == target.getX() && block.getY() == target.getY() && block.getZ() == target.getZ(); } - public static boolean throneChair(Block block) { + public static boolean throneChair(@NotNull Block block) { if (!(block.getBlockData() instanceof Stairs)) return false; if (block.getRelative(BlockFace.UP).getBlockData() instanceof TrapDoor trapDoor) { if (!trapDoor.isOpen()) return false; @@ -181,25 +176,24 @@ public static boolean throneChair(Block block) { return false; } - public static boolean blockIsChair(Block block, List chairs) { + public static boolean blockIsChair(@NotNull Block block, @NotNull List<@Nullable Chair> chairs) { for (Chair chair : chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; + if (chair == null || chair.getLocation() == null) continue; if (samePosition(block, chair.getBlock())) return true; } return false; } - public static Chair getChairFromBlock(Block block, List chairs) { + public static @Nullable Chair getChairFromBlock(@NotNull Block block, @NotNull List<@Nullable Chair> chairs) { for (Chair chair : chairs) { - if (chair == null) continue; - if (chair.getLocation() == null) continue; + if (chair == null || chair.getLocation() == null) continue; if (samePosition(chair.getBlock(), block)) return chair; } return null; } - public static ArmorStand generateFakeSeat(Chair chair) { + @Contract("null -> null; !null -> !null") + public static @Nullable ArmorStand generateFakeSeat(@Nullable Chair chair) { if (chair == null) return null; Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); Location seat = chair.getLocation(); @@ -212,12 +206,15 @@ public static ArmorStand generateFakeSeat(Chair chair) { if (facing != null) vector = getVectorFromFace(chair.getBlock(), facing.getOppositeFace()); else vector = getVectorFromNearBlock(chair.getBlock(), playerLoc.getBlock()); - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.stairSeatingPosition; - if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.carpetSeatingPosition; - if (BlockFilter.isSlabBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.slabSeatingPosition; + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().stairSeatingPosition; + } + if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().carpetSeatingPosition; + } + if (BlockFilter.isSlabBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().slabSeatingPosition; + } //Thank you VicenteRD and carlpoole! return seat.getWorld().spawn( @@ -232,19 +229,23 @@ public static ArmorStand generateFakeSeat(Chair chair) { }); } - public static ArmorStand generateFakeSeatDir(Chair chair, Vector dir) { + @Contract("null, _ -> null; !null, _ -> !null") + public static @Nullable ArmorStand generateFakeSeatDir(@Nullable Chair chair, @NotNull Vector dir) { if (chair == null) return null; Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); Location seat = chair.getLocation(); Location playerLoc = chair.getPlayer().getEyeLocation(); playerLoc.setPitch(0); - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.stairSeatingPosition; - if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.carpetSeatingPosition; - if (BlockFilter.isSlabBlock(chair.getBlock().getType())) - seatingPosition = plugin.chairManager.slabSeatingPosition; + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().stairSeatingPosition; + } + if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().carpetSeatingPosition; + } + if (BlockFilter.isSlabBlock(chair.getBlock().getType())) { + seatingPosition = RFChairs.getInstance().getChairManager().slabSeatingPosition; + } //Thank you VicenteRD and carlpoole! return seat.getWorld().spawn( @@ -259,7 +260,7 @@ public static ArmorStand generateFakeSeatDir(Chair chair, Vector dir) { }); } - public static float getAbsoluteAngle(Location loc) { + public static float getAbsoluteAngle(@NotNull Location loc) { float y = loc.getYaw(); if (y < 0) y += 360; y %= 360; @@ -269,7 +270,7 @@ public static float getAbsoluteAngle(Location loc) { return 270; } - public static String getCardinalDirection(Location loc) { + public static @NotNull String getCardinalDirection(@NotNull Location loc) { float y = loc.getYaw(); if (y < 0) y += 360; y %= 360; @@ -279,40 +280,42 @@ public static String getCardinalDirection(Location loc) { return "east"; } - public static Block getBlockFromDirection(Block block, String direction) { - if (direction.equalsIgnoreCase("north")) return block.getRelative(BlockFace.NORTH); - else if (direction.equalsIgnoreCase("west")) return block.getRelative(BlockFace.WEST); - else if (direction.equalsIgnoreCase("east")) return block.getRelative(BlockFace.EAST); - else if (direction.equalsIgnoreCase("south")) return block.getRelative(BlockFace.SOUTH); - else if (direction.equalsIgnoreCase("down")) return block.getRelative(BlockFace.DOWN); - else if (direction.equalsIgnoreCase("up")) return block.getRelative(BlockFace.UP); + public static Block getBlockFromDirection(@NotNull Block block, @NotNull String direction) { + if (direction.equalsIgnoreCase("north")) { + return block.getRelative(BlockFace.NORTH); + } else if (direction.equalsIgnoreCase("west")) { + return block.getRelative(BlockFace.WEST); + } else if (direction.equalsIgnoreCase("east")) { + return block.getRelative(BlockFace.EAST); + } else if (direction.equalsIgnoreCase("south")) { + return block.getRelative(BlockFace.SOUTH); + } else if (direction.equalsIgnoreCase("down")) { + return block.getRelative(BlockFace.DOWN); + } else if (direction.equalsIgnoreCase("up")) { + return block.getRelative(BlockFace.UP); + } return block; } - public static boolean canFitPlayer(Block block) { + public static boolean canFitPlayer(@NotNull Block block) { return block.getType() == Material.AIR && block.getRelative(BlockFace.UP).getType() == Material.AIR; } - public static boolean safePlace(Block block) { + public static boolean safePlace(@NotNull Block block) { return block.getRelative(BlockFace.DOWN).getType() != Material.AIR; } - public static Vector getVectorDir(Location caster, Location target) { + public static Vector getVectorDir(@NotNull Location caster, @NotNull Location target) { return target.clone().subtract(caster.toVector()).toVector(); } - public static Vector getVectorFromFace(Block block, BlockFace face) { + public static Vector getVectorFromFace(@NotNull Block block, @NotNull BlockFace face) { Location blockLoc = block.getLocation(); Location faceLoc = block.getRelative(face).getLocation(); return getVectorDir(blockLoc, faceLoc); } - public static Vector getVectorFromNearBlock(Block block, Block target) { + public static Vector getVectorFromNearBlock(@NotNull Block block, @NotNull Block target) { return target.getLocation().toVector().subtract(block.getLocation().toVector()); } - - public static void callEvent(Event event) { - plugin.getServer().getPluginManager().callEvent(event); - } - } From f5352cfdec1d6eb2a9d3829fb46bd2942c63b5b0 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 00:57:49 +0100 Subject: [PATCH 03/18] removed doubled PluginPrefix in Logs Fixed surrounding quotation marks of messages Removed unused "defaultMessages" --- .../com/rifledluffy/chairs/ChairManager.java | 9 ++- .../rifledluffy/chairs/MessageManager.java | 60 ++++++++++--------- .../java/com/rifledluffy/chairs/RFChairs.java | 7 ++- .../com/rifledluffy/chairs/chairs/Chair.java | 8 ++- .../rifledluffy/chairs/messages/Messages.java | 51 ++++------------ src/main/resources/messages.properties | 33 +++++----- 6 files changed, 73 insertions(+), 95 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index 3e34295..a4f343e 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -544,14 +544,14 @@ void saveToggled() { List ids = new ArrayList<>(); if (toggled == null || toggled.isEmpty()) configManager.getData().set("Toggled", new ArrayList()); for (UUID id : toggled) ids.add(id.toString()); - plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had toggled off."); + plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had toggled off."); configManager.getData().set("Toggled", ids); } void loadToggled() { List toggled = configManager.getData().getStringList("Toggled"); if (toggled.isEmpty()) return; - plugin.getServer().getLogger().info("[RFChairs] " + toggled.size() + " Players had toggled off. Adding Them..."); + plugin.getServer().getLogger().info("" + toggled.size() + " Players had toggled off. Adding Them..."); toggled.stream() .map(UUID::fromString) @@ -591,7 +591,7 @@ public void clearFakeSeatsFromFile(JavaPlugin plugin) { List fakes = configManager.getData().getStringList("UUIDs"); int leftoverFakes = fakes.size(); if (leftoverFakes >= 1) { - plugin.getServer().getLogger().info("[RFChairs] Detected " + fakes.size() + " leftover seats! Removing..."); + plugin.getServer().getLogger().info("Detected " + fakes.size() + " leftover seats! Removing..."); for (String fake : fakes) { UUID id = UUID.fromString(fake); Entity armorStand = plugin.getServer().getEntity(id); @@ -600,8 +600,7 @@ public void clearFakeSeatsFromFile(JavaPlugin plugin) { } configManager.getData().set("UUIDs", new ArrayList()); } else { - plugin.getServer().getLogger().info("[RFChairs] No fake seats remaining! Proceeding"); + plugin.getServer().getLogger().info("No fake seats remaining! Proceeding"); } } - } diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java index a4b2c15..0ec85eb 100644 --- a/src/main/java/com/rifledluffy/chairs/MessageManager.java +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -6,11 +6,11 @@ import com.rifledluffy.chairs.messages.MessageType; import com.rifledluffy.chairs.messages.Messages; import com.rifledluffy.chairs.utility.Util; +import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -36,13 +36,12 @@ public void reload(@NotNull RFChairs plugin) { private void tempMute(@NotNull Player player) { int duration = tempMuteDuration; tempMute.add(player.getUniqueId()); - BukkitRunnable runnable = new BukkitRunnable() { - @Override - public void run() { - if (tempMuted(player)) tempMute.remove(player.getUniqueId()); + + Bukkit.getScheduler().runTaskLater(plugin, () -> { + if (tempMuted(player)) { + tempMute.remove(player.getUniqueId()); } - }; - runnable.runTaskLater(plugin, duration); + }, duration); } private boolean tempMuted(@NotNull Player player) { @@ -52,12 +51,20 @@ private boolean tempMuted(@NotNull Player player) { @EventHandler public void onMessage(@NotNull MessageEvent event) { Player player = event.getPlayer(); - if (tempMute.contains(player.getUniqueId())) event.setCancelled(true); - if (event.isCancelled()) return; - if (tempMuteDuration > 0) tempMute(player); + if (tempMute.contains(player.getUniqueId())) { + event.setCancelled(true); + } + if (event.isCancelled()) { + return; + } + if (tempMuteDuration > 0) { + tempMute(player); + } if (allowMessages && !muted.contains(player.getUniqueId())) { String string = processString(event); - if (!string.isEmpty()) player.sendMessage(string); + if (!string.isEmpty()) { + player.sendMessage(string); + } } } @@ -65,43 +72,38 @@ private String processString(@NotNull MessageEvent event) { MessageType type = event.getType(); MessageConstruct construct = event.getConstruct(); String string; - - String stringOutput = Messages.getMessage(type); - if (stringOutput == null) { - string = Messages.getDefault(type); - } else { - string = stringOutput; - } - - string = messages.getString(string); + string = messages.getString(Messages.getMessage(type)); String finalString = ""; - if (construct == MessageConstruct.SINGLE) finalString = Util.replaceMessage(event.getPlayer(), string); - else if (construct == MessageConstruct.DEFENSIVE) + if (construct == MessageConstruct.SINGLE) { + finalString = Util.replaceMessage(event.getPlayer(), string); + } else if (construct == MessageConstruct.DEFENSIVE) { finalString = Util.replaceMessage(event.getEntity(), event.getPlayer(), string); - else if (construct == MessageConstruct.OFFENSIVE && event.getEntity() instanceof Player) + } else if (construct == MessageConstruct.OFFENSIVE && event.getEntity() instanceof Player) { finalString = Util.replaceMessage(event.getPlayer(), (Player) event.getEntity(), string); + } return finalString; } void saveMuted() { - List ids = new ArrayList(); - if (muted == null || muted.size() == 0) configManager.getData().set("Muted", new ArrayList()); + List ids = new ArrayList<>(); + if (muted == null || muted.isEmpty()) configManager.getData().set("Muted", new ArrayList()); for (UUID id : muted) ids.add(id.toString()); - plugin.getServer().getLogger().info("[RFChairs] Saving " + ids.size() + " Players that had events muted."); + plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had events muted."); configManager.getData().set("Muted", ids); } void loadMuted() { List muted = configManager.getData().getStringList("Muted"); - if (muted == null || muted.size() == 0) return; - plugin.getServer().getLogger().info("[RFChairs] " + muted.size() + " Players had events muted off. Adding Them..."); + if (muted.isEmpty()) { + return; + } + plugin.getServer().getLogger().info(muted.size() + " Players had events muted off. Adding Them..."); for (String toggler : muted) { UUID id = UUID.fromString(toggler); this.muted.add(id); } configManager.getData().set("Muted", new ArrayList()); } - } diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 0bc00ea..bf58796 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -9,6 +9,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -24,7 +25,7 @@ public static RFChairs getInstance() { return instance; } - private static void setInstance(RFChairs instance) { + private static void setInstance(@NotNull RFChairs instance) { RFChairs.instance = instance; } @@ -47,7 +48,9 @@ private void loadWorldGuard() { getLogger().info("Latest WorldGuard/WorldEdit features could be missing. Please Update!"); } - if (worldGuardManager != null) worldGuardManager.register(); + if (worldGuardManager != null) { + worldGuardManager.register(); + } } @Override diff --git a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java index f4bb4e0..1ed49f6 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java @@ -7,9 +7,9 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Stairs; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Player; -import org.bukkit.material.Stairs; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; @@ -79,8 +79,10 @@ public void setPlayer(@NotNull Player player) { } public @Nullable BlockFace getFacing() { - if (!BlockFilter.isStairsBlock(chair.getType())) return null; - return ((Stairs) chair.getState().getData()).getFacing(); + if (BlockFilter.isStairsBlock(chair.getType())) { + return ((Stairs) chair.getState().getData()).getFacing(); + } + return null; } /* diff --git a/src/main/java/com/rifledluffy/chairs/messages/Messages.java b/src/main/java/com/rifledluffy/chairs/messages/Messages.java index 72bcefe..8554c16 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/Messages.java +++ b/src/main/java/com/rifledluffy/chairs/messages/Messages.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.NotNull; public class Messages { + private final static String prefix = "prefix"; private final static String occupied = "occupied-seat"; private final static String tooFar = "too-far-from-seat"; private final static String noPerms = "no-permission"; @@ -15,47 +16,19 @@ public class Messages { private final static String noSigns = "no-sign-at-ends"; private final static String worldGuard = "denied-by-worldguard"; - private final static String defaultOccupied = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&a, my homie &7%seated%&c sits there."; - private final static String defaultTooFar = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!"; - private final static String defaultNoPerms = "&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!"; - private final static String defaultTooMany = "&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!"; - private final static String defaultTossed = "&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%."; - private final static String defaultTossedSpeed = "&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%."; - private final static String defaultTossing = "&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!"; - private final static String defaultTossingSpeed = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!"; - private final static String defaultPriority = "&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%"; - private final static String defaultNoSigns = "&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!"; - private final static String defaultWorldGuard = "&8[&6Rifle's Chairs&8] &cYou may not sit in this region!"; - - public static @NotNull String getDefault(@NotNull MessageType type) { - return switch (type) { - case OCCUPIED -> Messages.defaultOccupied; - case TOOFAR -> Messages.defaultTooFar; - case NOPERMS -> Messages.defaultNoPerms; - case TOOMANYITEMS -> Messages.defaultTooMany; - case TOSSED -> Messages.defaultTossed; - case TOSSEDSPEED -> Messages.defaultTossedSpeed; - case TOSSING -> Messages.defaultTossing; - case TOSSINGSPEED -> Messages.defaultTossingSpeed; - case PRIORITYTOSS -> Messages.defaultPriority; - case NOSIGNS -> Messages.defaultNoSigns; - case WORLDGUARD -> Messages.defaultWorldGuard; - }; - } - public static @NotNull String getMessage(@NotNull MessageType type) { return switch (type) { - case OCCUPIED -> Messages.occupied; - case TOOFAR -> Messages.tooFar; - case NOPERMS -> Messages.noPerms; - case TOOMANYITEMS -> Messages.tooMany; - case TOSSED -> Messages.tossed; - case TOSSEDSPEED -> Messages.tossedSpeed; - case TOSSING -> Messages.tossing; - case TOSSINGSPEED -> Messages.tossingSpeed; - case PRIORITYTOSS -> Messages.priority; - case NOSIGNS -> Messages.noSigns; - case WORLDGUARD -> Messages.worldGuard; + case OCCUPIED -> Messages.prefix + Messages.occupied; + case TOOFAR -> Messages.prefix + Messages.tooFar; + case NOPERMS -> Messages.prefix + Messages.noPerms; + case TOOMANYITEMS -> Messages.prefix + Messages.tooMany; + case TOSSED -> Messages.prefix + Messages.tossed; + case TOSSEDSPEED -> Messages.prefix + Messages.tossedSpeed; + case TOSSING -> Messages.prefix + Messages.tossing; + case TOSSINGSPEED -> Messages.prefix + Messages.tossingSpeed; + case PRIORITYTOSS -> Messages.prefix + Messages.priority; + case NOSIGNS -> Messages.prefix + Messages.noSigns; + case WORLDGUARD -> Messages.prefix + Messages.worldGuard; }; } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 517fc8f..4e4f0bb 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -33,21 +33,20 @@ # denied-by-worldguard: called when worldguard blocks seating in a region. # WorldGuard and WorldEdit must be enabled for these features to work! temp-mute-duration=60 -mute-message-enabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!" -mute-message-disabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!" -toggle-message-enabled="&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!" -toggle-message-disabled="&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!" -occupied-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%, &amy homie &7%seated%&c sits there." -too-far-from-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!" -no-permission="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!" -too-many-items="&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!" -tossed-out-of-chair="&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%." -tossed-out-with-speed="&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%." -tossing-someone="&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!" -tossing-someone-with-speed="&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!" -priority-replaced="&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%" -no-sign-at-ends="&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!" -denied-by-worldguard="&8[&6Rifle's Chairs&8] &cYou may not sit in this region!" -denied-by-plotsquared="&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!" -denied-by-griefprevention="&8[&6Rifle's Chairs&8] &cYou may not sit in this claim!" +prefix=&8[&6Rifle's Chairs&8] +mute-message-enabled=&7Event Messaging is now &aEnabled! +mute-message-disabled=&7Event Messaging is now &cDisabled! +toggle-message-enabled=&7Seating is now &aEnabled! +toggle-message-disabled=&7Seating is now &cDisabled! +occupied-seat=&cCan't sit there &7%user%, &amy homie &7%seated%&c sits there. +too-far-from-seat=&cCan't sit there &7%user%&c. You are too far! +no-permission=&cCan't sit there &7%user%&c. I won't allow you! +too-many-items=&c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them! +tossed-out-of-chair=&cTossed!... by &7%user%. +tossed-out-with-speed=&cYou got chucked off your seat by &7%user%. +tossing-someone=&cYou tossed &7%seated%&c off their seat! +tossing-someone-with-speed=&cYou forcibly tossed &7%seated%&c off their seat! +priority-replaced=&cYou forcibly tossed to make space for &7%user%&c, &7%seated% +no-sign-at-ends=&cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends! +denied-by-worldguard=&cYou may not sit in this region! From 6b4f34069ef39710c603f29bb637c1c1d556e11f Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 04:40:16 +0100 Subject: [PATCH 04/18] Better Message handling (thanks Feuerreiter once again for Padlock!) some code messiness fixed --- build.gradle.kts | 1 + .../com/rifledluffy/chairs/ChairManager.java | 201 ++++++----- .../rifledluffy/chairs/MessageManager.java | 312 +++++++++++++++--- .../java/com/rifledluffy/chairs/RFChairs.java | 12 +- .../com/rifledluffy/chairs/TargetInfo.java | 36 +- .../com/rifledluffy/chairs/chairs/Chair.java | 26 +- .../chairs/command/CommandManager.java | 76 +++-- .../chairs/command/commands/HelpCommand.java | 45 ++- .../chairs/command/commands/InfoCommand.java | 11 +- .../chairs/command/commands/MuteCommand.java | 22 +- .../command/commands/ReloadCommand.java | 18 +- .../chairs/command/commands/ResetCommand.java | 16 +- .../chairs/command/commands/SubCommand.java | 11 +- .../command/commands/ToggleCommand.java | 27 +- .../chairs/config/ConfigManager.java | 28 +- .../chairs/managers/WorldGuardManager.java | 14 +- .../chairs/messages/MessageConstruct.java | 7 - .../chairs/messages/MessageEvent.java | 62 ++-- .../chairs/messages/MessagePath.java | 46 +++ .../chairs/messages/MessageType.java | 15 - .../rifledluffy/chairs/messages/Messages.java | 34 -- .../chairs/messages/PlaceHolder.java | 24 ++ .../com/rifledluffy/chairs/utility/Util.java | 152 ++++----- src/main/resources/config.yml | 4 +- src/main/resources/messages.properties | 59 ++-- src/main/resources/messages_en.properties | 60 ++-- src/main/resources/plugin.yml | 2 + 27 files changed, 813 insertions(+), 508 deletions(-) delete mode 100644 src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java create mode 100644 src/main/java/com/rifledluffy/chairs/messages/MessagePath.java delete mode 100644 src/main/java/com/rifledluffy/chairs/messages/MessageType.java delete mode 100644 src/main/java/com/rifledluffy/chairs/messages/Messages.java create mode 100644 src/main/java/com/rifledluffy/chairs/messages/PlaceHolder.java diff --git a/build.gradle.kts b/build.gradle.kts index d07a54c..f5964be 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { paperweight.paperDevBundle("$mainMCVersion.1-R0.1-SNAPSHOT") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") compileOnly("org.jetbrains:annotations:24.1.0") + implementation("com.github.ben-manes.caffeine:caffeine:3.1.8") // caches } tasks { diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index a4f343e..f96dee6 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -4,10 +4,12 @@ import com.rifledluffy.chairs.chairs.Chair; import com.rifledluffy.chairs.config.ConfigManager; import com.rifledluffy.chairs.events.*; -import com.rifledluffy.chairs.messages.MessageConstruct; import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; +import com.rifledluffy.chairs.messages.MessagePath; +import com.rifledluffy.chairs.messages.PlaceHolder; import com.rifledluffy.chairs.utility.Util; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -33,23 +35,24 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import org.spigotmc.event.entity.EntityDismountEvent; import java.util.*; import java.util.stream.Collectors; public class ChairManager implements Listener { - private final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private final Map chairMap = new HashMap<>(); - private final List fakeSeats = new ArrayList<>(); - private final List leaving = new ArrayList<>(); - private final List orienting = new ArrayList<>(); - private final Map tossed = new HashMap<>(); - public List chairs = new ArrayList<>(); - public List toggled = new ArrayList<>(); - public Vector stairSeatingPosition; - public Vector slabSeatingPosition; - public Vector carpetSeatingPosition; + private final @NotNull RFChairs plugin = RFChairs.getPlugin(RFChairs.class); + private final @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap = new HashMap<>(); + private final @NotNull List<@NotNull String> fakeSeats = new ArrayList<>(); + private final @NotNull List<@NotNull UUID> leaving = new ArrayList<>(); + private final @NotNull List<@NotNull UUID> orienting = new ArrayList<>(); + private final @NotNull Map<@NotNull UUID, @NotNull TargetInfo> tossed = new HashMap<>(); + private final @NotNull List<@NotNull Chair> chairs = new ArrayList<>(); + private final @NotNull List<@NotNull UUID> toggled = new ArrayList<>(); + private Vector stairSeatingPosition; + private Vector slabSeatingPosition; + private Vector carpetSeatingPosition; private ConfigManager configManager = plugin.getConfigManager(); private FileConfiguration config = configManager.getConfig(); private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); @@ -77,7 +80,7 @@ public class ChairManager implements Listener { private boolean requireEmptyHand; //Mostly buggy, probably going to remove soon. private boolean exitWhereFacing; - private List disabledWorlds = new ArrayList<>(); + private @NotNull List<@NotNull World> disabledWorlds = new ArrayList<>(); public void reload(RFChairs plugin) { configManager = plugin.getConfigManager(); @@ -132,14 +135,12 @@ public void reload(RFChairs plugin) { } @EventHandler - public void onChairSit(ChairSitEvent event) { + private void onChairSit(@NotNull ChairSitEvent event) { Chair chair = event.getChair(); - if (chair == null) return; if (chair.getLocation() == null) return; - if (event.getPlayer() == null) return; if (plugin.hasWorldGuard()) if (!plugin.getWorldGuardManager().validateSeating(chair, event.getPlayer())) { - new MessageEvent(MessageType.WORLDGUARD, event.getPlayer()).callEvent(); + new MessageEvent(MessagePath.WORLDGUARD, event.getPlayer()).callEvent(); return; } @@ -154,9 +155,8 @@ public void onChairSit(ChairSitEvent event) { } @EventHandler - public void onChairLeave(ChairLeaveEvent event) { + private void onChairLeave(@NotNull ChairLeaveEvent event) { Chair chair = event.getChair(); - if (chair == null) return; if (chair.getLocation() == null) return; Block block = chair.getLocation().getBlock(); @@ -183,9 +183,8 @@ public void onChairLeave(ChairLeaveEvent event) { } @EventHandler - public void onToss(ChairTossEvent event) { + private void onToss(@NotNull ChairTossEvent event) { Chair chair = event.getChair(); - if (chair == null) return; if (chair.getLocation() == null) return; Block block = chair.getBlock(); @@ -198,36 +197,45 @@ public void onToss(ChairTossEvent event) { leaveEvent.callEvent(); if (!silent) { - MessageEvent messageEvent; - MessageEvent otherEvent = null; + MessageEvent tossedMessageEvent; + MessageEvent tosserMessageEvent = null; if (attacker instanceof Player playerEntity) { if (info != null && !info.isSprinting()) { - messageEvent = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, player, playerEntity); - } else { - messageEvent = new MessageEvent(MessageType.TOSSEDSPEED, MessageConstruct.DEFENSIVE, player, playerEntity); - } + tossedMessageEvent = new MessageEvent(MessagePath.TOSSED, player, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), playerEntity.displayName())); - if (info != null && !info.isSprinting()) { - otherEvent = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, playerEntity, player); + tosserMessageEvent = new MessageEvent(MessagePath.TOSSING, playerEntity, + Placeholder.component(PlaceHolder.SEATED.getPlaceholder(), player.displayName())); } else { - otherEvent = new MessageEvent(MessageType.TOSSINGSPEED, MessageConstruct.OFFENSIVE, playerEntity, player); + tossedMessageEvent = new MessageEvent(MessagePath.TOSSEDSPEED, player, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), playerEntity.displayName())); + + tosserMessageEvent = new MessageEvent(MessagePath.TOSSINGSPEED, playerEntity, + Placeholder.component(PlaceHolder.SEATED.getPlaceholder(), player.displayName())); + } + } else { + Component attackerName = attacker.customName(); + if (attackerName == null) { + attackerName = Component.text(attacker.getName()); } - } else messageEvent = new MessageEvent(MessageType.TOSSED, player, attacker); - messageEvent.callEvent(); - if (otherEvent != null) { - otherEvent.callEvent(); + + tossedMessageEvent = new MessageEvent(MessagePath.TOSSED, player, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), attackerName)); + } + tossedMessageEvent.callEvent(); + if (tosserMessageEvent != null) { + tosserMessageEvent.callEvent(); } } - if (canToss) { + if (canToss) { // todo shouldn't this check be higher up? ejectPlayer(block, player, attacker); } } @EventHandler - public void onChairReplace(ChairReplaceEvent event) { + private void onChairReplace(@NotNull ChairReplaceEvent event) { Chair chair = event.getChair(); - if (chair == null) return; if (chair.getLocation() == null) return; Block block = chair.getBlock(); @@ -239,34 +247,36 @@ public void onChairReplace(ChairReplaceEvent event) { ChairTossEvent tossEvent = new ChairTossEvent(chair, seated, player, null, true); tossEvent.callEvent(); - MessageEvent tossed = new MessageEvent(MessageType.TOSSED, MessageConstruct.DEFENSIVE, seated, player); + MessageEvent tossed = new MessageEvent(MessagePath.TOSSED, seated, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), player.displayName())); tossed.callEvent(); ChairSitEvent sitEvent = new ChairSitEvent(new Chair(player, block.getLocation()), player); sitEvent.callEvent(); - MessageEvent tosser = new MessageEvent(MessageType.TOSSING, MessageConstruct.OFFENSIVE, player, seated); + MessageEvent tosser = new MessageEvent(MessagePath.TOSSING, player, + Placeholder.component(PlaceHolder.SEATED.getPlaceholder(), seated.displayName())); tosser.callEvent(); } @EventHandler - public void onChairCheck(ChairCheckEvent event) { + private void onChairCheck(@NotNull ChairCheckEvent event) { Player player = event.getPlayer(); ItemStack item = player.getInventory().getItemInMainHand(); Block block = event.getBlock(); if (!player.hasPermission("rfchairs.use")) { - new MessageEvent(MessageType.NOPERMS, player).callEvent(); + new MessageEvent(MessagePath.SEAT_NOPERMS, player).callEvent(); return; } if (player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) >= maxDistance) { - new MessageEvent(MessageType.TOOFAR, player).callEvent(); + new MessageEvent(MessagePath.TOOFAR, player).callEvent(); return; } if (maxItemSit > 0 && item.getAmount() > maxItemSit) { - new MessageEvent(MessageType.TOOMANYITEMS, player).callEvent(); + new MessageEvent(MessagePath.TOOMANYITEMS, player).callEvent(); return; } @@ -289,7 +299,9 @@ public void onChairCheck(ChairCheckEvent event) { replaceEvent.callEvent(); return; } - if (chair.getPlayer() == null) return; + if (chair.getPlayer() == null) { + return; + } if (player.getUniqueId().equals(chair.getPlayer().getUniqueId())) { orienting.add(player.getUniqueId()); Location loc = chair.getFakeSeat().getLocation(); @@ -299,14 +311,16 @@ public void onChairCheck(ChairCheckEvent event) { chair.setFakeSeat(newFakeSeat); chair.getFakeSeat().addPassenger(player); } else { - MessageEvent occupied = new MessageEvent(MessageType.OCCUPIED, MessageConstruct.OFFENSIVE, player, chair.getPlayer()); + MessageEvent occupied = new MessageEvent(MessagePath.OCCUPIED, player, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), player.displayName()), + Placeholder.component(PlaceHolder.SEATED.getPlaceholder(), chair.getPlayer().displayName())); occupied.callEvent(); } } } @EventHandler - public void onRightClick(PlayerInteractEvent event) { + private void onRightClick(@NotNull PlayerInteractEvent event) { if (!disabledWorlds.isEmpty() && disabledWorlds.contains(event.getPlayer().getWorld())) return; if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (event.getPlayer().isSneaking()) return; @@ -335,7 +349,7 @@ public void onRightClick(PlayerInteractEvent event) { if (!Util.validCouch(block)) { if (!trapSeats) return; if (!Util.throneChair(block)) { - new MessageEvent(MessageType.NOSIGNS, player).callEvent(); + new MessageEvent(MessagePath.NOSIGNS, player).callEvent(); return; } } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; @@ -353,7 +367,7 @@ public void onRightClick(PlayerInteractEvent event) { if (event.getBlockFace() == BlockFace.DOWN) return; if (!player.hasPermission("rfchairs.use")) { - new MessageEvent(MessageType.NOPERMS, player).callEvent(); + new MessageEvent(MessagePath.SEAT_NOPERMS, player).callEvent(); return; } @@ -361,7 +375,7 @@ public void onRightClick(PlayerInteractEvent event) { } @EventHandler - public void onChangeGameMode(PlayerGameModeChangeEvent event) { + private void onChangeGameMode(@NotNull PlayerGameModeChangeEvent event) { if (event.isCancelled()) return; GameMode gameMode = event.getNewGameMode(); Chair chair = chairMap.get(event.getPlayer().getUniqueId()); @@ -369,7 +383,7 @@ public void onChangeGameMode(PlayerGameModeChangeEvent event) { } @EventHandler - public void onDismount(EntityDismountEvent event) { + private void onDismount(@NotNull EntityDismountEvent event) { if (!(event.getEntity() instanceof Player player)) return; Chair chair = chairMap.get(player.getUniqueId()); event.getDismounted(); @@ -381,8 +395,10 @@ public void onDismount(EntityDismountEvent event) { } if (tossed.containsKey(player.getUniqueId())) { TargetInfo info = tossed.get(player.getUniqueId()); - Entity attacker = info.getEntity(); - if (info.hasSource() && info.livingSource()) attacker = info.getLivingSource(); + Entity attacker = info.getAttacker(); + if (info.hasSource() && info.livingSource()) { + attacker = info.getLivingSource(); + } ChairTossEvent tossEvent = new ChairTossEvent(chairMap.get(player.getUniqueId()), player, attacker, info, false); tossEvent.callEvent(); @@ -393,7 +409,7 @@ public void onDismount(EntityDismountEvent event) { } @EventHandler - public void onMove(PlayerMoveEvent event) { + private void onMove(@NotNull PlayerMoveEvent event) { Player player = event.getPlayer(); if (leaving.contains(player.getUniqueId())) { ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chairMap.get(player.getUniqueId()), player, exitWhereFacing); @@ -403,32 +419,38 @@ public void onMove(PlayerMoveEvent event) { } @EventHandler - public void takeDamage(EntityDamageByEntityEvent event) { + private void takeDamage(@NotNull EntityDamageByEntityEvent event) { if (event.isCancelled()) return; if (!(event.getEntity() instanceof Player player)) return; Entity attacker = event.getDamager(); ProjectileSource source = null; - if (attacker instanceof Projectile) source = ((Projectile) attacker).getShooter(); + if (attacker instanceof Projectile projectile) { + source = projectile.getShooter(); + } Chair chair = chairMap.get(player.getUniqueId()); - if (chair == null) return; + if (chair == null) { + return; + } if (event.getDamage() >= minDamage && canLaunch) { TargetInfo info; - if (source == null) info = new TargetInfo(attacker, event.getDamage()); - else info = new TargetInfo(source, attacker, event.getDamage()); + if (source == null) { + info = new TargetInfo(attacker, event.getDamage()); + } else { + info = new TargetInfo(source, attacker, event.getDamage()); + } tossed.put(player.getUniqueId(), info); if (chair.getFakeSeat() != null) chair.getFakeSeat().removePassenger(player); } } @EventHandler - public void onBlockBreak(BlockBreakEvent event) { + private void onBlockBreak(@NotNull BlockBreakEvent event) { if (event.isCancelled()) return; chairs.stream() - .filter(Objects::nonNull) .filter(c -> c.getLocation() != null) - .filter(c -> Util.samePosition(event.getBlock(), c.getBlock())) + .filter(c -> Util.samePosition(event.getBlock(), c.getLocation())) .findAny() .ifPresent(c -> { if (!event.getPlayer().hasPermission("rfchairs.break")) event.setCancelled(true); @@ -436,7 +458,7 @@ public void onBlockBreak(BlockBreakEvent event) { } @EventHandler(priority = EventPriority.LOWEST) - public void quit(PlayerQuitEvent event) { + private void quit(@NotNull PlayerQuitEvent event) { Player player = event.getPlayer(); Chair chair = chairMap.get(player.getUniqueId()); ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); @@ -444,12 +466,11 @@ public void quit(PlayerQuitEvent event) { } @EventHandler - public void pistonExtend(BlockPistonExtendEvent event) { + private void pistonExtend(@NotNull BlockPistonExtendEvent event) { for (Block block : event.getBlocks()) { for (Chair chair : chairs) { - if (chair == null) continue; if (chair.getLocation() == null) continue; - if (Util.samePosition(block, chair.getBlock())) { + if (Util.samePosition(block, chair.getLocation())) { event.setCancelled(true); break; } @@ -458,12 +479,11 @@ public void pistonExtend(BlockPistonExtendEvent event) { } @EventHandler - public void pistonRetract(BlockPistonRetractEvent event) { + private void pistonRetract(@NotNull BlockPistonRetractEvent event) { for (Block block : event.getBlocks()) { for (Chair chair : chairs) { - if (chair == null) continue; if (chair.getLocation() == null) continue; - if (Util.samePosition(block, chair.getBlock())) { + if (Util.samePosition(block, chair.getLocation())) { event.setCancelled(true); break; } @@ -472,7 +492,7 @@ public void pistonRetract(BlockPistonRetractEvent event) { } @EventHandler - public void onDeath(PlayerDeathEvent event) { + private void onDeath(@NotNull PlayerDeathEvent event) { Player player = event.getEntity(); Chair chair = chairMap.get(player.getUniqueId()); ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); @@ -483,9 +503,8 @@ public void onDeath(PlayerDeathEvent event) { * Sitting and Ejection Methods */ - private boolean sitPlayer(Chair chair, Player player) { - if (player == null) return false; - if (chair == null || chair.isOccupied()) return false; + private boolean sitPlayer(@NotNull Chair chair, @NotNull Player player) { + if (chair.isOccupied()) return false; ArmorStand fakeSeat = chair.getFakeSeat(); if (fakeSeat == null) fakeSeat = Util.generateFakeSeat(chair); @@ -500,11 +519,15 @@ private boolean sitPlayer(Chair chair, Player player) { private void ejectPlayer(Block block, Player player, Entity entity) { Block exit = block; - if (exitWhereFacing) exit = findExitPoint(entity.getLocation(), block); + if (exitWhereFacing) { + exit = findExitPoint(entity.getLocation(), block); + } Location exitLoc = exit.getLocation().add(0.5, 0.5, 0.5); - if (!canToss) return; + if (!canToss) { + return; + } if (!faceAttacker) { exitLoc.setPitch(player.getLocation().getPitch()); @@ -542,8 +565,12 @@ private Block findExitPoint(Location entity, Block block) { void saveToggled() { List ids = new ArrayList<>(); - if (toggled == null || toggled.isEmpty()) configManager.getData().set("Toggled", new ArrayList()); - for (UUID id : toggled) ids.add(id.toString()); + if (toggled.isEmpty()) { + configManager.getData().set("Toggled", new ArrayList()); + } + for (UUID id : toggled) { + ids.add(id.toString()); + } plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had toggled off."); configManager.getData().set("Toggled", ids); } @@ -551,11 +578,11 @@ void saveToggled() { void loadToggled() { List toggled = configManager.getData().getStringList("Toggled"); if (toggled.isEmpty()) return; - plugin.getServer().getLogger().info("" + toggled.size() + " Players had toggled off. Adding Them..."); + plugin.getServer().getLogger().info(toggled.size() + " Players had toggled off. Adding Them..."); toggled.stream() .map(UUID::fromString) - .forEach(id -> this.toggled.add(id)); + .forEach(this.toggled::add); configManager.getData().set("Toggled", new ArrayList()); } @@ -603,4 +630,20 @@ public void clearFakeSeatsFromFile(JavaPlugin plugin) { plugin.getServer().getLogger().info("No fake seats remaining! Proceeding"); } } + + public @NotNull List<@NotNull UUID> getToggled() { + return toggled; + } + + public Vector getStairSeatingPosition() { + return stairSeatingPosition; + } + + public Vector getSlabSeatingPosition() { + return slabSeatingPosition; + } + + public Vector getCarpetSeatingPosition() { + return carpetSeatingPosition; + } } diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java index 0ec85eb..bc32399 100644 --- a/src/main/java/com/rifledluffy/chairs/MessageManager.java +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -1,36 +1,223 @@ package com.rifledluffy.chairs; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; import com.rifledluffy.chairs.config.ConfigManager; -import com.rifledluffy.chairs.messages.MessageConstruct; import com.rifledluffy.chairs.messages.MessageEvent; -import com.rifledluffy.chairs.messages.MessageType; -import com.rifledluffy.chairs.messages.Messages; -import com.rifledluffy.chairs.utility.Util; +import com.rifledluffy.chairs.messages.MessagePath; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.util.UTF8ResourceBundleControl; +import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; +import java.security.CodeSource; +import java.util.*; +import java.util.logging.Level; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; public class MessageManager implements Listener { - private final RFChairs plugin = RFChairs.getPlugin(RFChairs.class); - private final List tempMute = new ArrayList<>(); - public List muted = new ArrayList<>(); + private final static @NotNull String BUNDLE_NAME = "messages"; + private final static @NotNull Pattern BUNDLE_FILE_NAME_PATTERN = Pattern.compile(BUNDLE_NAME + "(?:_.*)?.properties"); + private final @NotNull RFChairs plugin = RFChairs.getInstance(); + private final @NotNull List<@NotNull UUID> tempMute = new ArrayList<>(); + private final @NotNull List<@NotNull UUID> muted = new ArrayList<>(); private ConfigManager configManager = plugin.getConfigManager(); - public FileConfiguration messages = configManager.getMessages(); private boolean allowMessages; private int tempMuteDuration; + private ResourceBundle messages; + /** + * caches every component without placeholder for faster access in future and loads missing values automatically + */ + private final LoadingCache langCache = Caffeine.newBuilder().build( + path -> MiniMessage.miniMessage().deserialize(getStringFromLang(path))); - public void reload(@NotNull RFChairs plugin) { + private String saveConvert(@NotNull String theString, boolean escapeSpace) { + int len = theString.length(); + int bufLen = len * 2; + if (bufLen < 0) { + bufLen = Integer.MAX_VALUE; + } + StringBuilder convertedStrBuilder = new StringBuilder(bufLen); + + for (int i = 0; i < theString.length(); i++) { + char aChar = theString.charAt(i); + // Handle common case first + if ((aChar > 61) && (aChar < 127)) { + if (aChar == '\\') { + if (i + 1 < theString.length()) { + final char bChar = theString.charAt(i + 1); + if (bChar == ' ' || bChar == 't' || bChar == 'n' || bChar == 'r' || + bChar == 'f' || bChar == '\\' || bChar == 'u' || bChar == '=' || + bChar == ':' || bChar == '#' || bChar == '!') { + // don't double escape already escaped chars + convertedStrBuilder.append(aChar); + convertedStrBuilder.append(bChar); + i++; + continue; + } else { + // any other char following + convertedStrBuilder.append('\\'); + } + } else { + // last char was a backslash. escape! + convertedStrBuilder.append('\\'); + } + } + convertedStrBuilder.append(aChar); + continue; + } + + // escape non escaped chars that have to get escaped + switch (aChar) { + case ' ' -> { + if (escapeSpace) { + convertedStrBuilder.append('\\'); + } + convertedStrBuilder.append(' '); + } + case '\t' -> convertedStrBuilder.append("\\t"); + case '\n' -> convertedStrBuilder.append("\\n"); + case '\r' -> convertedStrBuilder.append("\\r"); + case '\f' -> convertedStrBuilder.append("\\f"); + case '=', ':', '#', '!' -> { + convertedStrBuilder.append('\\'); + convertedStrBuilder.append(aChar); + } + default -> convertedStrBuilder.append(aChar); + } + } + + return convertedStrBuilder.toString(); + } + + /** + * saves all missing lang files from resources to the plugins data folder + */ + private void initLangFiles() { + CodeSource src = this.getClass().getProtectionDomain().getCodeSource(); + if (src != null) { + URL jarUrl = src.getLocation(); + try (ZipInputStream zipStream = new ZipInputStream(jarUrl.openStream())) { + ZipEntry zipEntry; + while ((zipEntry = zipStream.getNextEntry()) != null) { + if (zipEntry.isDirectory()) { + // already done with topmost layer + break; + } + + String entryName = zipEntry.getName(); + + if (BUNDLE_FILE_NAME_PATTERN.matcher(entryName).matches()) { + File langFile = new File(new File(plugin.getDataFolder(), BUNDLE_NAME), entryName); + if (!langFile.exists()) { // don't overwrite existing files + FileUtils.copyToFile(zipStream, langFile); + } else { // add defaults to file to expand in case there are key-value pairs missing + Properties defaults = new Properties(); + // don't close reader, since we need the stream to be still open for the next entry! + defaults.load(new InputStreamReader(zipStream, StandardCharsets.UTF_8)); + + Properties current = new Properties(); + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(langFile), StandardCharsets.UTF_8)) { + current.load(reader); + } catch (Exception e) { + plugin.getLogger().log(Level.WARNING, "couldn't get current properties file for " + entryName + "!", e); + continue; + } + + try (FileWriter fw = new FileWriter(langFile, StandardCharsets.UTF_8, true); + // we are NOT using Properties#store since it gets rid of comments and doesn't guarantee ordering + BufferedWriter bw = new BufferedWriter(fw)) { + boolean updated = false; // only write comment once + for (Map.Entry translationPair : defaults.entrySet()) { + if (current.get(translationPair.getKey()) == null) { + if (!updated) { + bw.write("# New Values where added. Is everything else up to date? Time of update: " + new Date()); + bw.newLine(); + + plugin.getLogger().fine("Updated langfile \"" + entryName + "\". Might want to check the new translation strings out!"); + + updated = true; + } + + String key = saveConvert((String) translationPair.getKey(), true); + /* No need to escape embedded and trailing spaces for value, hence + * pass false to flag. + */ + String val = saveConvert((String) translationPair.getValue(), false); + bw.write((key + "=" + val)); + bw.newLine(); + } // current already knows the key + } // end of for + } // end of try + } // end of else (file exists) + } // doesn't match + } // end of elements + } catch (IOException e) { + plugin.getLogger().log(Level.WARNING, "Couldn't save lang files", e); + } + } else { + plugin.getLogger().warning("Couldn't save lang files: no CodeSource!"); + } + } + + public void reload() { configManager = plugin.getConfigManager(); - messages = configManager.getMessages(); allowMessages = configManager.getConfig().getBoolean("allow-custom-messages", true); - tempMuteDuration = messages.getInt("temp-mute-duration", 0); + tempMuteDuration = configManager.getConfig().getInt("temp-mute-duration", 0); + + // get LanguageTag + String localeTag = configManager.getConfig().getString("language", "en"); + messages = null; // reset last bundle + + // save all missing keys + initLangFiles(); + + Locale locale = Locale.forLanguageTag(localeTag); + plugin.getLogger().info("Locale set to language: " + locale.toLanguageTag()); + File langDictionary = new File(plugin.getDataFolder(), BUNDLE_NAME); + + URL[] urls; + try { + urls = new URL[]{langDictionary.toURI().toURL()}; + messages = ResourceBundle.getBundle(BUNDLE_NAME, locale, new URLClassLoader(urls), UTF8ResourceBundleControl.get()); + + } catch (SecurityException | MalformedURLException e) { + plugin.getLogger().log(Level.WARNING, "Exception while reading lang bundle. Using internal", e); + } catch (MissingResourceException ignored) { // how? missing write access? + plugin.getLogger().log(Level.WARNING, "No translation file for " + UTF8ResourceBundleControl.get().toBundleName(BUNDLE_NAME, locale) + " found on disc. Using internal"); + } + + if (messages == null) { // fallback, since we are always trying to save defaults this never should happen + try { + messages = PropertyResourceBundle.getBundle(BUNDLE_NAME, locale, plugin.getClass().getClassLoader(), new UTF8ResourceBundleControl()); + } catch (MissingResourceException e) { + plugin.getLogger().log(Level.SEVERE, "Couldn't get Ressource bundle \"lang\" for locale \"" + locale.toLanguageTag() + "\". Messages WILL be broken!", e); + } + } + } + + private @NotNull String getStringFromLang(@NotNull MessagePath path) { + try { + return messages.getString(path.getPath()); + } catch (MissingResourceException | ClassCastException e) { + plugin.getLogger().log(Level.WARNING, "couldn't find path: \"" + path.getPath() + "\" in lang files using fallback.", e); + return path.getPath(); + } } private void tempMute(@NotNull Player player) { @@ -48,48 +235,73 @@ private boolean tempMuted(@NotNull Player player) { return tempMute.contains(player.getUniqueId()); } - @EventHandler - public void onMessage(@NotNull MessageEvent event) { - Player player = event.getPlayer(); - if (tempMute.contains(player.getUniqueId())) { - event.setCancelled(true); - } - if (event.isCancelled()) { - return; - } - if (tempMuteDuration > 0) { - tempMute(player); - } - if (allowMessages && !muted.contains(player.getUniqueId())) { - String string = processString(event); - if (!string.isEmpty()) { - player.sendMessage(string); - } - } + /** + * prepend the message with the plugins prefix before sending it to the audience. + */ + public void sendMessageWithoutPrefix(@NotNull Audience audience, @NotNull ComponentLike message) { + audience.sendMessage(message); } - private String processString(@NotNull MessageEvent event) { - MessageType type = event.getType(); - MessageConstruct construct = event.getConstruct(); - String string; - string = messages.getString(Messages.getMessage(type)); + /** + * send a component from the lang file to the audience, prefixed with this plugins prefix. + */ + public void sendLang(@NotNull Audience audience, @NotNull MessagePath path) { + audience.sendMessage(Component.text().append(langCache.get(MessagePath.PLUGIN_PREFIX)).appendSpace(). + append(langCache.get(path))); + } - String finalString = ""; + /** + * send a component from the lang file to the audience, prefixed with this plugins prefix and applying the given tag resolver. + * Note: might be slightly slower than {@link #sendLang(Audience, MessagePath)} since this can not use cache. + */ + public void sendLang(@NotNull Audience audience, @NotNull MessagePath path, @NotNull TagResolver... resolvers) { + audience.sendMessage(Component.text().append(langCache.get(MessagePath.PLUGIN_PREFIX)).appendSpace().append( + MiniMessage.miniMessage().deserialize(getStringFromLang(path), resolvers))); + } - if (construct == MessageConstruct.SINGLE) { - finalString = Util.replaceMessage(event.getPlayer(), string); - } else if (construct == MessageConstruct.DEFENSIVE) { - finalString = Util.replaceMessage(event.getEntity(), event.getPlayer(), string); - } else if (construct == MessageConstruct.OFFENSIVE && event.getEntity() instanceof Player) { - finalString = Util.replaceMessage(event.getPlayer(), (Player) event.getEntity(), string); + /** + * get a component from lang file and apply the given tag resolver. + * Note: might be slightly slower than {@link #getLang(MessagePath)} since this can not use cache. + */ + public @NotNull Component getLang(@NotNull MessagePath path, @NotNull TagResolver resolver) { + return MiniMessage.miniMessage().deserialize(getStringFromLang(path), resolver); + } + + /** + * get a component from lang file + */ + public @NotNull Component getLang(@NotNull MessagePath path) { + return langCache.get(path); + } + + @EventHandler(ignoreCancelled = true) + private void onMessage(@NotNull MessageEvent event) { + if (event.getAudience() instanceof Player player) { + if (tempMute.contains(player.getUniqueId())) { + event.setCancelled(true); + return; + } + + if (tempMuteDuration > 0) { + tempMute(player); + } + if (allowMessages && !muted.contains(player.getUniqueId())) { + sendLang(event.getAudience(), event.getType(), event.getResolvers()); + } + } else { // only players can be muted + sendLang(event.getAudience(), event.getType(), event.getResolvers()); } - return finalString; } void saveMuted() { List ids = new ArrayList<>(); - if (muted == null || muted.isEmpty()) configManager.getData().set("Muted", new ArrayList()); - for (UUID id : muted) ids.add(id.toString()); + if (muted.isEmpty()) { + configManager.getData().set("Muted", new ArrayList()); + } + + for (UUID id : muted) { + ids.add(id.toString()); + } plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had events muted."); configManager.getData().set("Muted", ids); } @@ -106,4 +318,8 @@ void loadMuted() { } configManager.getData().set("Muted", new ArrayList()); } + + public @NotNull List<@NotNull UUID> getMuted() { + return muted; + } } diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index bf58796..0209f28 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -11,8 +11,6 @@ import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import java.io.IOException; - public class RFChairs extends JavaPlugin { private static RFChairs instance; private CommandManager commandManager; @@ -21,7 +19,7 @@ public class RFChairs extends JavaPlugin { private MessageManager messageManager; private WorldGuardManager worldGuardManager; - public static RFChairs getInstance() { + public static @NotNull RFChairs getInstance() { return instance; } @@ -72,7 +70,7 @@ public void onEnable() { BlockFilter.reload(); chairManager.reload(this); - messageManager.reload(this); + messageManager.reload(); getServer().getPluginManager().registerEvents(chairManager, this); getServer().getPluginManager().registerEvents(messageManager, this); @@ -100,11 +98,7 @@ public void onDisable() { public void loadConfigManager() { cfgManager = new ConfigManager(); - try { - cfgManager.setup(); - } catch (IOException e) { - getInstance().getComponentLogger().info("Could not setup ConfigManager", e); - } + cfgManager.setup(); cfgManager.reloadConfig(); } diff --git a/src/main/java/com/rifledluffy/chairs/TargetInfo.java b/src/main/java/com/rifledluffy/chairs/TargetInfo.java index af705d5..6079ee7 100644 --- a/src/main/java/com/rifledluffy/chairs/TargetInfo.java +++ b/src/main/java/com/rifledluffy/chairs/TargetInfo.java @@ -1,60 +1,54 @@ package com.rifledluffy.chairs; -import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.projectiles.BlockProjectileSource; import org.bukkit.projectiles.ProjectileSource; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class TargetInfo { - Player player; - Entity attacker; - ProjectileSource source; - Double damage; - boolean sprinting = false; + private final @NotNull Entity attacker; + private final @Nullable ProjectileSource source; + private final double damage; + private boolean sprinting = false; - TargetInfo(ProjectileSource source, Entity attacker, Double damage) { + protected TargetInfo(@NotNull ProjectileSource source, @NotNull Entity attacker, double damage) { this.source = source; this.attacker = attacker; this.damage = damage; } - TargetInfo(Entity attacker, Double damage) { + protected TargetInfo(@NotNull Entity attacker, double damage) { this.source = null; - if (attacker instanceof Player) { - player = (Player) attacker; + if (attacker instanceof Player player) { sprinting = player.isSprinting(); } this.attacker = attacker; this.damage = damage; } - Entity getEntity() { + protected @NotNull Entity getAttacker() { return attacker; } - LivingEntity getLivingSource() { + protected LivingEntity getLivingSource() { return (LivingEntity) source; } - Block getBlockSource() { - return ((BlockProjectileSource) source).getBlock(); - } - - Double getDamage() { + protected double getDamage() { return damage; } - boolean isSprinting() { + protected boolean isSprinting() { return this.sprinting; } - boolean hasSource() { + protected boolean hasSource() { return source != null; } - boolean livingSource() { + protected boolean livingSource() { return source != null && source instanceof LivingEntity; } } diff --git a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java index 1ed49f6..af93e8f 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java @@ -67,20 +67,32 @@ public void setPlayer(@NotNull Player player) { } public @Nullable Block getBlock() { - return location.getBlock(); + if (location == null) { + return null; + } else { + return location.getBlock(); + } } public @Nullable BlockState getBlockState() { + if (chair == null) { + return null; + } else { return chair.getState(); + } } public @Nullable BlockData getBlockData() { + if (chair == null) { + return null; + } else { return chair.getState().getBlockData(); + } } public @Nullable BlockFace getFacing() { - if (BlockFilter.isStairsBlock(chair.getType())) { - return ((Stairs) chair.getState().getData()).getFacing(); + if (chair != null && BlockFilter.isStairsBlock(chair.getType())) { + return ((Stairs) chair.getState().getBlockData()).getFacing(); } return null; } @@ -102,8 +114,12 @@ public boolean isOccupied() { } public void clear() { - if (fakeSeat != null) fakeSeat.remove(); - player.removePotionEffect(PotionEffectType.REGENERATION); + if (fakeSeat != null) { + fakeSeat.remove(); + } + if (player != null) { + player.removePotionEffect(PotionEffectType.REGENERATION); + } chair = null; location = null; fakeSeat = null; diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index 7f5d49f..85e8759 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -2,7 +2,9 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.command.commands.*; -import net.md_5.bungee.api.ChatColor; +import com.rifledluffy.chairs.messages.MessagePath; +import com.rifledluffy.chairs.messages.PlaceHolder; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -14,62 +16,60 @@ import java.util.Arrays; public class CommandManager implements CommandExecutor { - private final String main = "rfchairs"; - private final @NotNull ArrayList<@NotNull SubCommand> commands = new ArrayList<>(); + private static final String MAIN_COMMAND = "rfchairs"; + private final @NotNull ArrayList<@NotNull SubCommand> subCommands = new ArrayList<>(); public CommandManager() { } public void setup() { - RFChairs.getInstance().getCommand(main).setExecutor(this); + RFChairs.getInstance().getCommand(MAIN_COMMAND).setExecutor(this); - this.commands.add(new HelpCommand()); + this.subCommands.add(new HelpCommand()); //this.commands.add(new InfoCommand()); - this.commands.add(new ReloadCommand()); - this.commands.add(new ResetCommand()); - this.commands.add(new ToggleCommand()); - this.commands.add(new MuteCommand()); + this.subCommands.add(new ReloadCommand()); + this.subCommands.add(new ResetCommand()); + this.subCommands.add(new ToggleCommand()); + this.subCommands.add(new MuteCommand()); } public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - if (command.getName().equalsIgnoreCase(main)) { - if (args.length == 0) { - sender.sendMessage(ChatColor.RED + "Missing Arguments. Type /rfchairs help for info"); - return true; - } + if (args.length == 0) { + RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NOT_ENOUGH_ARGS); + return true; + } - SubCommand target = this.get(args[0]); + SubCommand target = this.getSubcommand(args[0]); - if (target == null) { - sender.sendMessage(ChatColor.RED + "Invalid subcommand"); - return true; - } - - ArrayList arrayList = new ArrayList<>(); + if (target == null) { + RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_INVALID_SUBCOMMAND, + Placeholder.unparsed(PlaceHolder.ARGUMENT.getPlaceholder(), args[0])); + return true; + } - arrayList.addAll(Arrays.asList(args)); - arrayList.remove(0); + // clear args from subcommand + ArrayList subcommandArgList = new ArrayList<>(Arrays.asList(args)); + subcommandArgList.remove(0); - if (target.checkPermission(sender)) { - if (target.needsPlayer()) { - if (sender instanceof Player player) { - target.onPlayerCommand(player, args); - } else { - sender.sendMessage("You need to be a player to use this command!"); - } + if (target.checkPermission(sender)) { + if (target.needsPlayer()) { + if (sender instanceof Player player) { + target.onPlayerCommand(player, subcommandArgList); } else { - target.onCommand(sender, args); + RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NOT_PLAYER); } } else { - sender.sendMessage("No permission!"); + target.onCommand(sender, subcommandArgList); } + } else { + RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NO_PERMISSION); } return true; } - private @Nullable SubCommand get(@NotNull String name) { - for (SubCommand sc : this.commands) { + private @Nullable SubCommand getSubcommand(@NotNull String name) { + for (SubCommand sc : this.subCommands) { if (sc.name().equalsIgnoreCase(name)) { return sc; } @@ -87,4 +87,12 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } return null; } + + public @NotNull ArrayList<@NotNull SubCommand> getSubCommands() { + return subCommands; + } + + public static @NotNull String getMainCommand() { + return MAIN_COMMAND; + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java index bb82971..e63c26d 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java @@ -1,26 +1,45 @@ package com.rifledluffy.chairs.command.commands; -import net.md_5.bungee.api.ChatColor; +import com.rifledluffy.chairs.MessageManager; +import com.rifledluffy.chairs.RFChairs; +import com.rifledluffy.chairs.command.CommandManager; +import com.rifledluffy.chairs.messages.MessagePath; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class HelpCommand implements SubCommand { - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { //todo check permissions! - sender.sendMessage(ChatColor.YELLOW + "--------------" + ChatColor.DARK_GRAY + "[" + ChatColor.DARK_GREEN + "Available Commands" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + "--------------"); - sender.sendMessage(ChatColor.GOLD + "/rfc or /rfchairs" + ChatColor.GRAY + " is the main command"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs reload" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Reloads the config and messages [Console Can Cast]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs reset" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Resets all chairs [Console Can Cast]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs toggle" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Disables seating on chairs for the executor [Player Only]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs mute" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Mutes event messages from the plugin for the executor [Player Only]"); - sender.sendMessage(ChatColor.GOLD + "/rfchairs update" + ChatColor.DARK_GRAY + " | " + ChatColor.GRAY + "Runs a check on their current version [Console Can Cast]"); - sender.sendMessage(ChatColor.YELLOW + "------------------------------------------------"); + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + TextComponent.Builder builder = Component.text(); + MessageManager messageManager = RFChairs.getInstance().getMessageManager(); + String rawCommand = "/" + CommandManager.getMainCommand() + " | "; + + builder.append(messageManager.getLang(MessagePath.COMMAND_HELP_HEADER)).appendNewline(); + builder.append(messageManager.getLang(MessagePath.COMMAND_HELP_MAIN)).appendNewline(); + + + for (SubCommand subCommand : RFChairs.getInstance().getCommandManager().getSubCommands()) { + if (subCommand.checkPermission(sender)) { + builder.append(MiniMessage.miniMessage().deserialize(rawCommand, Placeholder.unparsed("cmd", subCommand.name()))). + append(subCommand.info().color(NamedTextColor.GRAY)).appendNewline(); + } + } + builder.append(messageManager.getLang(MessagePath.COMMAND_HELP_FOOTER)); + + messageManager.sendMessageWithoutPrefix(sender, builder); } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { onCommand(player, args); } @@ -30,8 +49,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return ""; + public @NotNull Component info() { + return RFChairs.getInstance().getMessageManager().getLang(MessagePath.COMMAND_HELP_INFO); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java index d4aece3..1813c55 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java @@ -1,19 +1,22 @@ package com.rifledluffy.chairs.command.commands; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class InfoCommand implements SubCommand { //todo @Override - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { } @Override @@ -22,8 +25,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return ""; + public @NotNull Component info() { + return Component.empty(); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java index 2391258..3186821 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java @@ -2,7 +2,8 @@ import com.rifledluffy.chairs.MessageManager; import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.utility.Util; +import com.rifledluffy.chairs.messages.MessagePath; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; @@ -13,23 +14,18 @@ public class MuteCommand implements SubCommand { - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { MessageManager messageManager = RFChairs.getInstance().getMessageManager(); - List muted = messageManager.muted; - String message; + List muted = messageManager.getMuted(); if (muted.contains(player.getUniqueId())) { - String string = messageManager.messages.getString("mute-message-enabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); + messageManager.sendLang(player, MessagePath.COMMAND_MUTE_ENABLED); muted.remove(player.getUniqueId()); } else { - String string = messageManager.messages.getString("mute-message-disabled", "&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); + messageManager.sendLang(player, MessagePath.COMMAND_MUTE_DISABLED); muted.add(player.getUniqueId()); } } @@ -40,8 +36,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return ""; + public @NotNull Component info() { + return RFChairs.getInstance().getMessageManager().getLang(MessagePath.COMMAND_MUTE_INFO); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java index 89dd0ca..cbd7052 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java @@ -3,29 +3,31 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.chairs.BlockFilter; import com.rifledluffy.chairs.config.ConfigManager; -import net.md_5.bungee.api.ChatColor; +import com.rifledluffy.chairs.messages.MessagePath; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class ReloadCommand implements SubCommand { private final RFChairs plugin = RFChairs.getInstance(); @Override - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { ConfigManager newConfig = plugin.getConfigManager(); newConfig.reloadConfig(); - newConfig.reloadMessages(); plugin.setConfigManager(newConfig); BlockFilter.reload(); plugin.getChairManager().reload(plugin); - plugin.getMessageManager().reload(plugin); - sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Config Reloaded"); + plugin.getMessageManager().reload(); + plugin.getMessageManager().sendLang(sender, MessagePath.COMMAND_RELOAD_SUCCESS); } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { onCommand(player, args); } @@ -35,8 +37,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return "Reloads the config and messages"; + public @NotNull Component info() { + return RFChairs.getInstance().getMessageManager().getLang(MessagePath.COMMAND_RELOAD_INFO); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java index acbfb2b..1846604 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -1,24 +1,28 @@ package com.rifledluffy.chairs.command.commands; import com.rifledluffy.chairs.RFChairs; -import net.md_5.bungee.api.ChatColor; +import com.rifledluffy.chairs.messages.MessagePath; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class ResetCommand implements SubCommand { private final RFChairs plugin = RFChairs.getInstance(); - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { plugin.getChairManager().clearFakeSeats(); plugin.getChairManager().clearFakeSeatsFromFile(plugin); plugin.getLogger().info("Chairs Reset!"); - sender.sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Rifle's Chairs" + ChatColor.DARK_GRAY + "] " + ChatColor.GREEN + "Chairs Reset"); + + plugin.getMessageManager().sendLang(sender, MessagePath.COMMAND_RESET_SUCCESS); } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { onCommand(player, args); } @@ -28,8 +32,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return "Resets all chairs"; + public @NotNull Component info() { + return plugin.getMessageManager().getLang(MessagePath.COMMAND_RESET_INFO); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java index 6056732..0df9891 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java @@ -1,24 +1,27 @@ package com.rifledluffy.chairs.command.commands; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * / args[0] args[1] */ public interface SubCommand { - void onCommand(@NotNull CommandSender sender, @NotNull String[] args); + void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args); - void onPlayerCommand(@NotNull Player player, @NotNull String[] args); + void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args); @NotNull String name(); - @NotNull String info(); + @NotNull Component info(); - @NotNull String @NotNull [] aliases(); + @NotNull String @NotNull [] aliases(); // funny thing: No subcommand defines an alias at time of writing this boolean needsPlayer(); diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java index 93c3750..8d4770b 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java @@ -2,7 +2,10 @@ import com.rifledluffy.chairs.MessageManager; import com.rifledluffy.chairs.RFChairs; -import com.rifledluffy.chairs.utility.Util; +import com.rifledluffy.chairs.messages.MessagePath; +import com.rifledluffy.chairs.messages.PlaceHolder; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; @@ -13,23 +16,21 @@ public class ToggleCommand implements SubCommand { - public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { } @Override - public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { + public void onPlayerCommand(@NotNull Player player, @NotNull List<@NotNull String> args) { MessageManager messageManager = RFChairs.getInstance().getMessageManager(); - List toggled = RFChairs.getInstance().getChairManager().toggled; - String message; + List toggled = RFChairs.getInstance().getChairManager().getToggled(); + if (toggled.contains(player.getUniqueId())) { - String string = messageManager.messages.getString("toggle-message-enabled", "&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); + messageManager.sendLang(player, MessagePath.COMMAND_TOGGLE_ENABLED, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), player.displayName())); toggled.remove(player.getUniqueId()); } else { - String string = messageManager.messages.getString("toggle-message-disabled", "&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!"); - message = Util.replaceMessage(player, string); - player.sendMessage(message); + messageManager.sendLang(player, MessagePath.COMMAND_TOGGLE_DISABLED, + Placeholder.component(PlaceHolder.PLAYER.getPlaceholder(), player.displayName())); toggled.add(player.getUniqueId()); } } @@ -40,8 +41,8 @@ public void onPlayerCommand(@NotNull Player player, @NotNull String[] args) { } @Override - public @NotNull String info() { - return ""; + public @NotNull Component info() { + return RFChairs.getInstance().getMessageManager().getLang(MessagePath.COMMAND_TOGGLE_INFO); } @Override diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index ffce901..1cd51ae 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -19,10 +19,8 @@ public class ConfigManager { private File configFile; private FileConfiguration fake; private File fakeFile; - private FileConfiguration message; - private File messageFile; - public void setup() throws IOException { + public void setup() { configFile = new File(plugin.getDataFolder(), "config.yml"); config = plugin.getConfig(); config.options().copyDefaults(true); @@ -42,15 +40,7 @@ public void setup() throws IOException { } } - messageFile = new File(plugin.getDataFolder(), "messages.yml"); - - if (!messageFile.exists()) { - messageFile.getParentFile().mkdirs(); - plugin.saveResource("messages.yml", false); - } - fake = YamlConfiguration.loadConfiguration(fakeFile); - message = YamlConfiguration.loadConfiguration(messageFile); } public FileConfiguration getData() { @@ -69,22 +59,6 @@ public void reloadData() { fake = YamlConfiguration.loadConfiguration(fakeFile); } - public FileConfiguration getMessages() { - return message; - } - - public void saveMessages() { - try { - message.save(messageFile); - } catch (IOException e) { - plugin.getLogger().info("[Rifle's Chairs] Could not save messages.yml!"); - } - } - - public void reloadMessages() { - message = YamlConfiguration.loadConfiguration(messageFile); - } - public FileConfiguration getConfig() { return config; } diff --git a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java index 188d2f9..0adbc96 100644 --- a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java +++ b/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java @@ -14,6 +14,8 @@ import com.sk89q.worldguard.protection.regions.RegionContainer; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -40,14 +42,17 @@ public void register() { } } - public WorldGuardPlugin getWorldGuard() { + public @Nullable WorldGuardPlugin getWorldGuard() { // todo cache the plugin Plugin plugin = this.plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - if (!(plugin instanceof WorldGuardPlugin)) return null; - return (WorldGuardPlugin) plugin; + if (plugin instanceof WorldGuardPlugin worldGuardPlugin) { + return worldGuardPlugin; + } else { + return null; + } } - public boolean validateSeating(Chair chair, Player player) { + public boolean validateSeating(@NotNull Chair chair, @NotNull Player player) { double xPos = chair.getLocation().getX(); double yPos = chair.getLocation().getY(); double zPos = chair.getLocation().getZ(); @@ -75,5 +80,4 @@ public RegionContainer getContainer() { public Flag getFlag() { return flag; } - } diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java b/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java deleted file mode 100644 index 5ed5fa9..0000000 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageConstruct.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.rifledluffy.chairs.messages; - -public enum MessageConstruct { - DEFENSIVE, - OFFENSIVE, - SINGLE -} diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java index eaa1552..912e3f4 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java @@ -1,7 +1,7 @@ package com.rifledluffy.chairs.messages; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -10,53 +10,25 @@ public class MessageEvent extends Event implements Cancellable { private static final @NotNull HandlerList handlers = new HandlerList(); - private final @NotNull MessageType type; - private final @NotNull MessageConstruct construct; - private final @NotNull Player player; - private final @Nullable Entity other; + private final @NotNull MessagePath type; + private @NotNull TagResolver @Nullable [] resolvers; + private @NotNull Audience audience; private boolean cancelled; - public MessageEvent(@NotNull MessageType type, @NotNull MessageConstruct construct, @NotNull Player player, @NotNull Player other) { + public MessageEvent(@NotNull MessagePath type, @NotNull Audience audience, @NotNull TagResolver @Nullable ... resolvers) { this.type = type; - this.construct = construct; - this.player = player; - this.other = other; - } - - public MessageEvent(@NotNull MessageType type, @NotNull Player player, @NotNull Entity other) { - this.type = type; - this.construct = MessageConstruct.DEFENSIVE; - this.player = player; - this.other = other; - } - - public MessageEvent(@NotNull MessageType type, @NotNull Player player) { - this.type = type; - this.construct = MessageConstruct.SINGLE; - this.player = player; - this.other = null; + this.audience = audience; + this.resolvers = resolvers; } static public @NotNull HandlerList getHandlerList() { return handlers; } - public @NotNull MessageType getType() { + public @NotNull MessagePath getType() { return this.type; } - public @NotNull MessageConstruct getConstruct() { - return this.construct; - } - - public @NotNull Player getPlayer() { - return this.player; - } - - public @Nullable Entity getEntity() { - return this.other; - } - @Override public @NotNull HandlerList getHandlers() { return handlers; @@ -71,4 +43,20 @@ public boolean isCancelled() { public void setCancelled(boolean cancel) { this.cancelled = cancel; } + + public @NotNull Audience getAudience() { + return audience; + } + + public void setAudience(@NotNull Audience audience) { + this.audience = audience; + } + + public @NotNull TagResolver[] getResolvers() { + return resolvers; + } + + public void setResolvers(@NotNull TagResolver[] replacingResolvers) { + this.resolvers = replacingResolvers; + } } diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessagePath.java b/src/main/java/com/rifledluffy/chairs/messages/MessagePath.java new file mode 100644 index 0000000..82ae444 --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/messages/MessagePath.java @@ -0,0 +1,46 @@ +package com.rifledluffy.chairs.messages; + +import org.jetbrains.annotations.NotNull; + +public enum MessagePath { + COMMAND_HELP_FOOTER("command.help.footer"), + COMMAND_HELP_HEADER("command.help.header"), + COMMAND_HELP_MAIN("command.help.main"), + COMMAND_INVALID_SUBCOMMAND("command.invalid_subcommand"), + COMMAND_MUTE_DISABLED("command.mute-message.disabled"), + COMMAND_MUTE_ENABLED("command.mute-message.enabled"), + COMMAND_NOT_ENOUGH_ARGS("command.not_enough_args"), + COMMAND_NOT_PLAYER("command.not_player"), + COMMAND_NO_PERMISSION("command.no-permission"), + COMMAND_RELOAD_SUCCESS("command.reload.success"), + COMMAND_RELOAD_INFO("command.reload.info"), + COMMAND_RESET_SUCCESS("command.reset.success"), + COMMAND_TOGGLE_DISABLED("command.toggle-disabled"), + COMMAND_TOGGLE_ENABLED("command.toggle-enabled"), + NOSIGNS("no-sign-at-ends"), + // PRIORITYTOSS("priority-replaced"), // todo? + OCCUPIED("occupied-seat"), + PLUGIN_PREFIX("pluginPrefix"), + SEAT_NOPERMS("no-permission"), + TOOFAR("too-far-from-seat"), + TOOMANYITEMS("too-many-items"), + TOSSED("tossed-out-of-chair"), + TOSSEDSPEED("tossed-out-with-speed"), + TOSSING("tossing-someone"), + TOSSINGSPEED("tossing-someone-with-speed"), + WORLDGUARD("denied-by-worldguard"), + COMMAND_RESET_INFO("command.reset.info"), + COMMAND_TOGGLE_INFO("command.toggle.info"), + COMMAND_MUTE_INFO("command.mute.info"), + COMMAND_HELP_INFO("command.help.info"); + + private final @NotNull String path; + + MessagePath(@NotNull String path) { + this.path = path; + } + + public @NotNull String getPath() { + return path; + } +} diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageType.java b/src/main/java/com/rifledluffy/chairs/messages/MessageType.java deleted file mode 100644 index 24c44d0..0000000 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageType.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.rifledluffy.chairs.messages; - -public enum MessageType { - NOPERMS, - NOSIGNS, - OCCUPIED, - PRIORITYTOSS, - TOOFAR, - TOOMANYITEMS, - TOSSED, - TOSSEDSPEED, - TOSSING, - TOSSINGSPEED, - WORLDGUARD -} diff --git a/src/main/java/com/rifledluffy/chairs/messages/Messages.java b/src/main/java/com/rifledluffy/chairs/messages/Messages.java deleted file mode 100644 index 8554c16..0000000 --- a/src/main/java/com/rifledluffy/chairs/messages/Messages.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.rifledluffy.chairs.messages; - -import org.jetbrains.annotations.NotNull; - -public class Messages { - private final static String prefix = "prefix"; - private final static String occupied = "occupied-seat"; - private final static String tooFar = "too-far-from-seat"; - private final static String noPerms = "no-permission"; - private final static String tooMany = "too-many-items"; - private final static String tossed = "tossed-out-of-chair"; - private final static String tossedSpeed = "tossed-out-with-speed"; - private final static String tossing = "tossing-someone"; - private final static String tossingSpeed = "tossing-someone-with-speed"; - private final static String priority = "priority-replaced"; - private final static String noSigns = "no-sign-at-ends"; - private final static String worldGuard = "denied-by-worldguard"; - - public static @NotNull String getMessage(@NotNull MessageType type) { - return switch (type) { - case OCCUPIED -> Messages.prefix + Messages.occupied; - case TOOFAR -> Messages.prefix + Messages.tooFar; - case NOPERMS -> Messages.prefix + Messages.noPerms; - case TOOMANYITEMS -> Messages.prefix + Messages.tooMany; - case TOSSED -> Messages.prefix + Messages.tossed; - case TOSSEDSPEED -> Messages.prefix + Messages.tossedSpeed; - case TOSSING -> Messages.prefix + Messages.tossing; - case TOSSINGSPEED -> Messages.prefix + Messages.tossingSpeed; - case PRIORITYTOSS -> Messages.prefix + Messages.priority; - case NOSIGNS -> Messages.prefix + Messages.noSigns; - case WORLDGUARD -> Messages.prefix + Messages.worldGuard; - }; - } -} diff --git a/src/main/java/com/rifledluffy/chairs/messages/PlaceHolder.java b/src/main/java/com/rifledluffy/chairs/messages/PlaceHolder.java new file mode 100644 index 0000000..a22797a --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/messages/PlaceHolder.java @@ -0,0 +1,24 @@ +package com.rifledluffy.chairs.messages; + +import org.intellij.lang.annotations.Subst; + +public enum PlaceHolder { + ARGUMENT("argument"), + PLAYER("player"), + SEATED("seated"); + + private final String placeholder; + + PlaceHolder(String placeholder) { + this.placeholder = placeholder; + } + + /** + * Since this will be used in Mini-messages placeholder only the pattern "[!?#]?[a-z0-9_-]*" is valid. + * if used inside an unparsed text you have to add surrounding <> yourself. + */ + @Subst("name") // substitution; will be inserted if the IDE/compiler tests if input is valid. + public String getPlaceholder() { + return placeholder; + } +} \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java index edb5816..d683516 100644 --- a/src/main/java/com/rifledluffy/chairs/utility/Util.java +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -3,7 +3,6 @@ import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.chairs.BlockFilter; import com.rifledluffy.chairs.chairs.Chair; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -16,8 +15,6 @@ import org.bukkit.block.data.type.TrapDoor; import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import org.jetbrains.annotations.Contract; @@ -27,50 +24,6 @@ import java.util.*; public class Util { - public static void debug(@NotNull String message) { - for (Player player : RFChairs.getInstance().getServer().getOnlinePlayers()) { - player.sendMessage(message); - } - } - - public static void debug(@NotNull Object message) { - debug(message.toString()); - } - - public static void debug(@NotNull List<@NotNull Object> messages) { - messages.forEach(Util::debug); - } - - public static @NotNull String replaceMessage(@NotNull Player player, @NotNull String string) { - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("%user%", player.getDisplayName()); - return string; - } - - public static String replaceMessage(@NotNull Entity entity, @NotNull Player target, @NotNull String string) { - if (entity instanceof LivingEntity) return replaceMessage((LivingEntity) entity, target, string); - - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("%user%", entity.getName()); - string = string.replace("%seated%", target.getName()); - return string; - } - - public static String replaceMessage(@NotNull LivingEntity entity, @NotNull Player target, @NotNull String string) { - if (entity instanceof Player) return replaceMessage((Player) entity, target, string); - - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("%user%", entity.getName()); - string = string.replace("%seated%", target.getName()); - return string; - } - - public static String replaceMessage(@NotNull Player player, @NotNull Player target, @NotNull String string) { - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("%user%", player.getDisplayName()); - string = string.replace("%seated%", target.getName()); - return string; - } public static boolean validStair(@NotNull Block block) { if (!BlockFilter.validateStairs(block.getType())) return false; @@ -135,42 +88,69 @@ public static boolean validCouch(@NotNull Block block) { BlockFace side = faces.get(0); BlockFace otherSide = faces.get(1); - if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return false; + if (block.getRelative(BlockFace.UP).getType() != Material.AIR) { + return false; + } - if (validatedChair(block.getRelative(side))) if (validSeat(block.getRelative(side), side, block)) validSides++; - if (validatedChair(block.getRelative(otherSide))) - if (validSeat(block.getRelative(otherSide), otherSide, block)) validSides++; + if (validatedChair(block.getRelative(side))) { + if (validSeat(block.getRelative(side), side, block)) { + validSides++; + } + } + if (validatedChair(block.getRelative(otherSide))) { + if (validSeat(block.getRelative(otherSide), otherSide, block)) { + validSides++; + } + } - if (!validatedChair(block.getRelative(side))) if (validSeat(block, side, block)) validSides++; - if (!validatedChair(block.getRelative(otherSide))) if (validSeat(block, otherSide, block)) validSides++; + if (!validatedChair(block.getRelative(side))) { + if (validSeat(block, side, block)) { + validSides++; + } + } + if (!validatedChair(block.getRelative(otherSide))) { + if (validSeat(block, otherSide, block)) { + validSides++; + } + } return validSides == 2; } public static boolean validSeat(@NotNull Block block, @NotNull BlockFace side, @NotNull Block original) { Stairs stair = (Stairs) block.getState().getBlockData(); Stairs first = (Stairs) original.getState().getBlockData(); - if (stair.getFacing() != first.getFacing()) return false; + if (stair.getFacing() != first.getFacing()) { + return false; + } if (block.getRelative(side).getBlockData() instanceof WallSign || block.getRelative(side).getBlockData() instanceof TrapDoor) { Directional sign = ((Directional) block.getRelative(side).getBlockData()); return sign.getFacing() == side; - } else if (validatedChair(block.getRelative(side))) return validSeat(block.getRelative(side), side, original); + } else if (validatedChair(block.getRelative(side))) { + return validSeat(block.getRelative(side), side, original); + } return false; } public static boolean sameSeat(@NotNull Player player, @NotNull Block block, @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap) { Chair chair = chairMap.get(player.getUniqueId()); - if (chair == null) return false; + if (chair == null || chair.getLocation() == null) { + return false; + } return chair.getLocation().equals(block.getLocation()); } - public static boolean samePosition(@NotNull Block block, @NotNull Block target) { + public static boolean samePosition(@NotNull Block block, @NotNull Location target) { return block.getX() == target.getX() && block.getY() == target.getY() && block.getZ() == target.getZ(); } public static boolean throneChair(@NotNull Block block) { - if (!(block.getBlockData() instanceof Stairs)) return false; + if (!(block.getBlockData() instanceof Stairs)) { + return false; + } if (block.getRelative(BlockFace.UP).getBlockData() instanceof TrapDoor trapDoor) { - if (!trapDoor.isOpen()) return false; + if (!trapDoor.isOpen()) { + return false; + } return trapDoor.getFacing().getOppositeFace() == ((Stairs) block.getBlockData()).getFacing(); } return false; @@ -178,42 +158,56 @@ public static boolean throneChair(@NotNull Block block) { public static boolean blockIsChair(@NotNull Block block, @NotNull List<@Nullable Chair> chairs) { for (Chair chair : chairs) { - if (chair == null || chair.getLocation() == null) continue; - if (samePosition(block, chair.getBlock())) return true; + if (chair == null || chair.getLocation() == null) { + continue; + } + if (samePosition(block, chair.getLocation())) { + return true; + } } return false; } public static @Nullable Chair getChairFromBlock(@NotNull Block block, @NotNull List<@Nullable Chair> chairs) { for (Chair chair : chairs) { - if (chair == null || chair.getLocation() == null) continue; - if (samePosition(chair.getBlock(), block)) return chair; + if (chair == null || chair.getLocation() == null) { + continue; + } + if (samePosition(block, chair.getLocation())) { + return chair; + } } return null; } @Contract("null -> null; !null -> !null") public static @Nullable ArmorStand generateFakeSeat(@Nullable Chair chair) { - if (chair == null) return null; + if (chair == null) { + return null; + } Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); Location seat = chair.getLocation(); BlockFace facing = null; - if (BlockFilter.isStairsBlock(chair.getBlock().getType())) + if (BlockFilter.isStairsBlock(chair.getBlock().getType())) { facing = ((Stairs) chair.getBlock().getState().getBlockData()).getFacing(); + } Location playerLoc = chair.getPlayer().getEyeLocation(); playerLoc.setPitch(0); Vector vector; - if (facing != null) vector = getVectorFromFace(chair.getBlock(), facing.getOppositeFace()); - else vector = getVectorFromNearBlock(chair.getBlock(), playerLoc.getBlock()); + if (facing != null) { + vector = getVectorFromFace(chair.getBlock(), facing.getOppositeFace()); + } else { + vector = getVectorFromNearBlock(chair.getBlock(), playerLoc.getBlock()); + } if (BlockFilter.isStairsBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().stairSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getStairSeatingPosition(); } if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().carpetSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getCarpetSeatingPosition(); } if (BlockFilter.isSlabBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().slabSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getSlabSeatingPosition(); } //Thank you VicenteRD and carlpoole! @@ -231,20 +225,22 @@ public static boolean blockIsChair(@NotNull Block block, @NotNull List<@Nullable @Contract("null, _ -> null; !null, _ -> !null") public static @Nullable ArmorStand generateFakeSeatDir(@Nullable Chair chair, @NotNull Vector dir) { - if (chair == null) return null; + if (chair == null) { + return null; + } Vector seatingPosition = new Vector(0.5, 0.3D, 0.5); Location seat = chair.getLocation(); Location playerLoc = chair.getPlayer().getEyeLocation(); playerLoc.setPitch(0); if (BlockFilter.isStairsBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().stairSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getStairSeatingPosition(); } if (BlockFilter.isCarpetBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().carpetSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getCarpetSeatingPosition(); } if (BlockFilter.isSlabBlock(chair.getBlock().getType())) { - seatingPosition = RFChairs.getInstance().getChairManager().slabSeatingPosition; + seatingPosition = RFChairs.getInstance().getChairManager().getSlabSeatingPosition(); } //Thank you VicenteRD and carlpoole! @@ -262,7 +258,9 @@ public static boolean blockIsChair(@NotNull Block block, @NotNull List<@Nullable public static float getAbsoluteAngle(@NotNull Location loc) { float y = loc.getYaw(); - if (y < 0) y += 360; + if (y < 0) { + y += 360; + } y %= 360; if (y <= 45 || y >= 315) return 0; if (y >= 45 && y <= 135) return 90; @@ -272,7 +270,9 @@ public static float getAbsoluteAngle(@NotNull Location loc) { public static @NotNull String getCardinalDirection(@NotNull Location loc) { float y = loc.getYaw(); - if (y < 0) y += 360; + if (y < 0) { + y += 360; + } y %= 360; if (y <= 45 || y >= 315) return "south"; if (y >= 45 && y <= 135) return "west"; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5d1d6f1..181052e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -59,4 +59,6 @@ allowed-chairs: - SLAB* - CARPET* blacklisted-chairs: [ ] -disabled-worlds: [ ] \ No newline at end of file +disabled-worlds: [ ] +temp-mute-duration: 60 +language: 'en' \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 4e4f0bb..940b1d6 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,7 +1,7 @@ # Certain events occur when users use this plugin. Here you can define what messages might be said. # -# Use %user% to refer to the user's name -# Use %seated% to refer to the seated's name +# Use to refer to the user's name +# Use to refer to the seated's name # # General Events # @@ -13,40 +13,51 @@ # Combat # # tossed-out-of-chair: Sends a message to the tossed player when they get tossed off -# Example: %user% tossed you out of your seat! +# Example: tossed you out of your seat! # Output; if Rifle hit you: Rifle tossed you out of your seat! # # tossed-out-with-speed: Sends a message to the tossed player but the tosser was running -# Example: %user% really knocked you of your seat! +# Example: really knocked you of your seat! # Output; if Rifle hit you: Rifle really knocked you of your seat! # # tossing-someone: Sends a message to the player that tossed someone off their chair -# Example: You tossed %seated% out of their chair! +# Example: You tossed out of their chair! # Output; if Rifle was sitting: You tossed Rifle out of their chair! # # tossing-someone-with-speed: Sends a message to the player that tossed someone off their chair with speed! -# Example: You really knocked %seated% out of their chair! +# Example: You really knocked out of their chair! # Output; if Rifle was sitting: You really knocked Rifle out of their chair! # # Other Plugins # # denied-by-worldguard: called when worldguard blocks seating in a region. # WorldGuard and WorldEdit must be enabled for these features to work! -temp-mute-duration=60 -prefix=&8[&6Rifle's Chairs&8] -mute-message-enabled=&7Event Messaging is now &aEnabled! -mute-message-disabled=&7Event Messaging is now &cDisabled! -toggle-message-enabled=&7Seating is now &aEnabled! -toggle-message-disabled=&7Seating is now &cDisabled! -occupied-seat=&cCan't sit there &7%user%, &amy homie &7%seated%&c sits there. -too-far-from-seat=&cCan't sit there &7%user%&c. You are too far! -no-permission=&cCan't sit there &7%user%&c. I won't allow you! -too-many-items=&c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them! -tossed-out-of-chair=&cTossed!... by &7%user%. -tossed-out-with-speed=&cYou got chucked off your seat by &7%user%. -tossing-someone=&cYou tossed &7%seated%&c off their seat! -tossing-someone-with-speed=&cYou forcibly tossed &7%seated%&c off their seat! -priority-replaced=&cYou forcibly tossed to make space for &7%user%&c, &7%seated% -no-sign-at-ends=&cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends! -denied-by-worldguard=&cYou may not sit in this region! - +command.help.footer=------------------------------------------------ +command.help.header=--------------[Available Commands]-------------- +command.help.info=Displays a list of all commands. +command.help.main=/rfc or /rfchairs is the main command +command.invalid_subcommand="" is not a valid subcommand. Type /rfchairs help for a list of them! +command.mute-message.disabled=Event Messaging is now Disabled! +command.mute-message.enabled=Event Messaging is now Enabled! +command.mute.info=Mutes event messages from the plugin for the executor [Player Only] +command.no-permission=You are not allowed to do that! +command.not_enough_args=Missing Arguments. Type /rfchairs help for info +command.not_player=You need to be a player to use this command! +command.reload.info=Reloads the config and messages [Console Can Cast] +command.reload.success=Config Reloaded +command.reset.info=Resets all chairs [Console Can Cast] +command.reset.success=Chairs Reset +command.toggle-disabled=Seating is now Disabled! +command.toggle-enabled=Seating is now Enabled! +command.toggle.info=Disables seating on chairs for the executor [Player Only] +denied-by-worldguard=You may not sit in this region! +no-permission=Can't sit there . I won't allow you! +no-sign-at-ends=This seat [which is a stair] doesn't have signs on both its ends! +occupied-seat=Can't sit there , my homie sits there. +pluginPrefix=[Rifle's Chairs] +too-far-from-seat=Can't sit there . You are too far! +too-many-items=! You have quite a hefty stack of items on your hand. Remove them! +tossed-out-of-chair=Tossed!... by . +tossed-out-with-speed=You got chucked off your seat by . +tossing-someone=You tossed off their seat! +tossing-someone-with-speed=You forcibly tossed off their seat! diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 517fc8f..940b1d6 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -1,7 +1,7 @@ # Certain events occur when users use this plugin. Here you can define what messages might be said. # -# Use %user% to refer to the user's name -# Use %seated% to refer to the seated's name +# Use to refer to the user's name +# Use to refer to the seated's name # # General Events # @@ -13,41 +13,51 @@ # Combat # # tossed-out-of-chair: Sends a message to the tossed player when they get tossed off -# Example: %user% tossed you out of your seat! +# Example: tossed you out of your seat! # Output; if Rifle hit you: Rifle tossed you out of your seat! # # tossed-out-with-speed: Sends a message to the tossed player but the tosser was running -# Example: %user% really knocked you of your seat! +# Example: really knocked you of your seat! # Output; if Rifle hit you: Rifle really knocked you of your seat! # # tossing-someone: Sends a message to the player that tossed someone off their chair -# Example: You tossed %seated% out of their chair! +# Example: You tossed out of their chair! # Output; if Rifle was sitting: You tossed Rifle out of their chair! # # tossing-someone-with-speed: Sends a message to the player that tossed someone off their chair with speed! -# Example: You really knocked %seated% out of their chair! +# Example: You really knocked out of their chair! # Output; if Rifle was sitting: You really knocked Rifle out of their chair! # # Other Plugins # # denied-by-worldguard: called when worldguard blocks seating in a region. # WorldGuard and WorldEdit must be enabled for these features to work! -temp-mute-duration=60 -mute-message-enabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &aEnabled!" -mute-message-disabled="&8[&6Rifle's Chairs&8] &7Event Messaging is now &cDisabled!" -toggle-message-enabled="&8[&6Rifle's Chairs&8] &7Seating is now &aEnabled!" -toggle-message-disabled="&8[&6Rifle's Chairs&8] &7Seating is now &cDisabled!" -occupied-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%, &amy homie &7%seated%&c sits there." -too-far-from-seat="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. You are too far!" -no-permission="&8[&6Rifle's Chairs&8] &cCan't sit there &7%user%&c. I won't allow you!" -too-many-items="&8[&6Rifle's Chairs&8] &c&7%user%&c! You have quite a hefty stack of items on your hand. Remove them!" -tossed-out-of-chair="&8[&6Rifle's Chairs&8] &cTossed!... by &7%user%." -tossed-out-with-speed="&8[&6Rifle's Chairs&8] &cYou got chucked off your seat by &7%user%." -tossing-someone="&8[&6Rifle's Chairs&8] &cYou tossed &7%seated%&c off their seat!" -tossing-someone-with-speed="&8[&6Rifle's Chairs&8] &cYou forcibly tossed &7%seated%&c off their seat!" -priority-replaced="&8[&6Rifle's Chairs&8] &cYou forcibly tossed to make space for &7%user%&c, &7%seated%" -no-sign-at-ends="&8[&6Rifle's Chairs&8] &cThis seat &8[&7which is a stair&8]&c doesn't have signs on both its ends!" -denied-by-worldguard="&8[&6Rifle's Chairs&8] &cYou may not sit in this region!" -denied-by-plotsquared="&8[&6Rifle's Chairs&8] &cYou may not sit in this plot!" -denied-by-griefprevention="&8[&6Rifle's Chairs&8] &cYou may not sit in this claim!" - +command.help.footer=------------------------------------------------ +command.help.header=--------------[Available Commands]-------------- +command.help.info=Displays a list of all commands. +command.help.main=/rfc or /rfchairs is the main command +command.invalid_subcommand="" is not a valid subcommand. Type /rfchairs help for a list of them! +command.mute-message.disabled=Event Messaging is now Disabled! +command.mute-message.enabled=Event Messaging is now Enabled! +command.mute.info=Mutes event messages from the plugin for the executor [Player Only] +command.no-permission=You are not allowed to do that! +command.not_enough_args=Missing Arguments. Type /rfchairs help for info +command.not_player=You need to be a player to use this command! +command.reload.info=Reloads the config and messages [Console Can Cast] +command.reload.success=Config Reloaded +command.reset.info=Resets all chairs [Console Can Cast] +command.reset.success=Chairs Reset +command.toggle-disabled=Seating is now Disabled! +command.toggle-enabled=Seating is now Enabled! +command.toggle.info=Disables seating on chairs for the executor [Player Only] +denied-by-worldguard=You may not sit in this region! +no-permission=Can't sit there . I won't allow you! +no-sign-at-ends=This seat [which is a stair] doesn't have signs on both its ends! +occupied-seat=Can't sit there , my homie sits there. +pluginPrefix=[Rifle's Chairs] +too-far-from-seat=Can't sit there . You are too far! +too-many-items=! You have quite a hefty stack of items on your hand. Remove them! +tossed-out-of-chair=Tossed!... by . +tossed-out-with-speed=You got chucked off your seat by . +tossing-someone=You tossed off their seat! +tossing-someone-with-speed=You forcibly tossed off their seat! diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 9d43323..e8c71f0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,6 +5,8 @@ version: ${version} description: ${description} authors: [ Rifle D. Luffy, VicenteRD, carlpoole, i0xHeX, GreensurvivorsTeam ] softdepend: [ WorldGuard, WorldEdit ] +libraries: + - com.github.ben-manes.caffeine:caffeine:3.1.8 commands: rfchairs: usage: / From 664c76db3577c48cac8b931677ed8bc8cf33c6e5 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 04:59:09 +0100 Subject: [PATCH 05/18] Fix white/blacklist not using correct categories --- .../com/rifledluffy/chairs/ChairManager.java | 58 +++++++++++-------- .../chairs/chairs/BlockFilter.java | 34 +++++++---- .../com/rifledluffy/chairs/utility/Util.java | 4 +- src/main/resources/config.yml | 10 ++-- 4 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index f96dee6..db1ab4d 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -338,40 +338,50 @@ private void onRightClick(@NotNull PlayerInteractEvent event) { if (item.getType().isBlock()) return; } - if (!BlockFilter.isStairsBlock(block.getType()) - && !BlockFilter.isCarpetBlock(block.getType()) - && !BlockFilter.isSlabBlock(block.getType())) return; - - if (BlockFilter.isStairsBlock(block.getType())) { - if (!Util.validStair(block)) return; - else { - if (checkForSigns) { - if (!Util.validCouch(block)) { - if (!trapSeats) return; - if (!Util.throneChair(block)) { - new MessageEvent(MessagePath.NOSIGNS, player).callEvent(); + if (BlockFilter.isStairsBlock(block.getType()) + || BlockFilter.isCarpetBlock(block.getType()) + || BlockFilter.isSlabBlock(block.getType())) { + if (BlockFilter.isStairsBlock(block.getType())) { + if (!Util.validStair(block)) return; + else { + if (checkForSigns) { + if (!Util.validCouch(block)) { + if (!trapSeats) return; + if (!Util.throneChair(block)) { + new MessageEvent(MessagePath.NOSIGNS, player).callEvent(); + return; + } + } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) { return; } - } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; + } + if (trapSeats && block.getRelative(BlockFace.UP).getType() != Material.AIR) { + if (!Util.throneChair(block)) return; + } } - if (trapSeats && block.getRelative(BlockFace.UP).getType() != Material.AIR) { - if (!Util.throneChair(block)) return; + } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; + + if (BlockFilter.isSlabBlock(block.getType())) { + if (!Util.validSlab(block)) { + return; } } - } else if (block.getRelative(BlockFace.UP).getType() != Material.AIR) return; - if (BlockFilter.isSlabBlock(block.getType())) if (!Util.validSlab(block)) return; + if (BlockFilter.isCarpetBlock(block.getType())) { + if (!Util.validCarpet(block)) { + return; + } + } - if (BlockFilter.isCarpetBlock(block.getType())) if (!Util.validCarpet(block)) return; + if (event.getBlockFace() == BlockFace.DOWN) return; - if (event.getBlockFace() == BlockFace.DOWN) return; + if (!player.hasPermission("rfchairs.use")) { + new MessageEvent(MessagePath.SEAT_NOPERMS, player).callEvent(); + return; + } - if (!player.hasPermission("rfchairs.use")) { - new MessageEvent(MessagePath.SEAT_NOPERMS, player).callEvent(); - return; + new ChairCheckEvent(block, player).callEvent(); } - - new ChairCheckEvent(block, player).callEvent(); } @EventHandler diff --git a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java index 47dfa7c..6fd4e05 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java @@ -14,32 +14,30 @@ public class BlockFilter { public static void reload() { FileConfiguration config = RFChairs.getInstance().getConfig(); - whitelist = new HashSet<>(config.getStringList("allowed-chairs")); + whitelist = new HashSet<>(config.getStringList("whitelisted-chairs")); blacklist = new HashSet<>(config.getStringList("blacklisted-chairs")); } - public static boolean isWhitelisted(@NotNull Material type, @NotNull String category) { - if (whitelist.contains("ALL_" + category)) return true; - return whitelist.contains(type.name()); + public static boolean isWhitelisted(@NotNull Material type, @NotNull ChairCategory category) { + return whitelist.contains(category.getConfigName()) || whitelist.contains(type.name()); } - public static boolean isBlacklisted(@NotNull Material type, @NotNull String category) { - if (blacklist.contains("ALL_" + category)) return true; - return blacklist.contains(type.name()); + public static boolean isBlacklisted(@NotNull Material type, @NotNull ChairCategory category) { + return blacklist.contains(category.getConfigName()) || blacklist.contains(type.name()); } // validate public static boolean validateCarpet(@NotNull Material type) { - return isWhitelisted(type, "CARPETS") && !isBlacklisted(type, "CARPET"); + return isWhitelisted(type, ChairCategory.CARPETS) && !isBlacklisted(type, ChairCategory.CARPETS); } public static boolean validateSlab(@NotNull Material type) { - return isWhitelisted(type, "SLABS") && !isBlacklisted(type, "SLAB"); + return isWhitelisted(type, ChairCategory.SLABS) && !isBlacklisted(type, ChairCategory.SLABS); } public static boolean validateStairs(@NotNull Material type) { - return isWhitelisted(type, "STAIRS") && !isBlacklisted(type, "STAIRS"); + return isWhitelisted(type, ChairCategory.STAIRS) && !isBlacklisted(type, ChairCategory.STAIRS); } // check @@ -55,4 +53,20 @@ public static boolean isSlabBlock(@NotNull Material type) { public static boolean isStairsBlock(@NotNull Material type) { return Tag.STAIRS.isTagged(type); } + + public enum ChairCategory { + SLABS("ALL_SLABS"), + STAIRS("ALL_STAIRS"), + CARPETS("ALL_CARPETS"); + + private final String configName; + + ChairCategory(String configName) { + this.configName = configName; + } + + public String getConfigName() { + return configName; + } + } } diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java index d683516..14c306f 100644 --- a/src/main/java/com/rifledluffy/chairs/utility/Util.java +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -144,14 +144,14 @@ public static boolean samePosition(@NotNull Block block, @NotNull Location targe } public static boolean throneChair(@NotNull Block block) { - if (!(block.getBlockData() instanceof Stairs)) { + if (!(block.getBlockData() instanceof Stairs stairs)) { return false; } if (block.getRelative(BlockFace.UP).getBlockData() instanceof TrapDoor trapDoor) { if (!trapDoor.isOpen()) { return false; } - return trapDoor.getFacing().getOppositeFace() == ((Stairs) block.getBlockData()).getFacing(); + return trapDoor.getFacing().getOppositeFace() == stairs.getFacing(); } return false; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 181052e..f0d60ce 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -31,7 +31,7 @@ # regen-when-sitting: players regenerate when sitting on chairs # regen-potency: the regen potion effect level where 0 is level 1 # allow-custom-messages: allow the use of custom messages when events are triggered -# allowed-chairs: The chairs that people are allowed to sit on +# whitelisted-chairs: The chairs that people are allowed to sit on stair-seating-position: 0.5,0.3,0.5 slab-seating-positiong: 0.5,0.3,0.5 carpet-seating-position: 0.5,-0.15,0.5 @@ -54,10 +54,10 @@ regen-when-sitting: true regen-potency: 0 allow-custom-messages: false priority-on-if-has-perm: true -allowed-chairs: - - STAIRS* - - SLAB* - - CARPET* +whitelisted-chairs: + - ALL_STAIRS + - ALL_SLABS + - ALL_CARPETS blacklisted-chairs: [ ] disabled-worlds: [ ] temp-mute-duration: 60 From b3eeb02d6abe9fd2125627240814bfc02e3eca2c Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 05:17:36 +0100 Subject: [PATCH 06/18] * Fix region checking code. It was picking up all regions in all worlds at specified coordinates. Now only regions applicable to the current world at the specified location are checked. * Treat all air material types equivalently. Commit taken from: totemo/RFChairs author: totemo --- .../java/com/rifledluffy/chairs/RFChairs.java | 6 +-- .../com/rifledluffy/chairs/chairs/Chair.java | 4 +- .../chairs/command/CommandManager.java | 8 +-- .../WorldGuardManager.java | 49 ++++++++----------- .../com/rifledluffy/chairs/utility/Util.java | 13 +++-- 5 files changed, 37 insertions(+), 43 deletions(-) rename src/main/java/com/rifledluffy/chairs/{managers => dependencymanagers}/WorldGuardManager.java (60%) diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 0209f28..5e49448 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -3,7 +3,7 @@ import com.rifledluffy.chairs.chairs.BlockFilter; import com.rifledluffy.chairs.command.CommandManager; import com.rifledluffy.chairs.config.ConfigManager; -import com.rifledluffy.chairs.managers.WorldGuardManager; +import com.rifledluffy.chairs.dependencymanagers.WorldGuardManager; import com.rifledluffy.chairs.metrics.MetricsLite; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; @@ -126,10 +126,6 @@ public WorldGuardManager getWorldGuardManager() { return this.worldGuardManager; } - public void log(String string) { - getLogger().info(string); - } - boolean hasWorldGuard() { return worldGuardManager != null; } diff --git a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java index af93e8f..8646fb8 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/Chair.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/Chair.java @@ -78,7 +78,7 @@ public void setPlayer(@NotNull Player player) { if (chair == null) { return null; } else { - return chair.getState(); + return chair.getState(); } } @@ -86,7 +86,7 @@ public void setPlayer(@NotNull Player player) { if (chair == null) { return null; } else { - return chair.getState().getBlockData(); + return chair.getState().getBlockData(); } } diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index 85e8759..8b26360 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -22,6 +22,10 @@ public class CommandManager implements CommandExecutor { public CommandManager() { } + public static @NotNull String getMainCommand() { + return MAIN_COMMAND; + } + public void setup() { RFChairs.getInstance().getCommand(MAIN_COMMAND).setExecutor(this); @@ -91,8 +95,4 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command public @NotNull ArrayList<@NotNull SubCommand> getSubCommands() { return subCommands; } - - public static @NotNull String getMainCommand() { - return MAIN_COMMAND; - } } diff --git a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java similarity index 60% rename from src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java rename to src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java index 0adbc96..88adc48 100644 --- a/src/main/java/com/rifledluffy/chairs/managers/WorldGuardManager.java +++ b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java @@ -1,28 +1,27 @@ -package com.rifledluffy.chairs.managers; +package com.rifledluffy.chairs.dependencymanagers; import com.rifledluffy.chairs.RFChairs; import com.rifledluffy.chairs.chairs.Chair; -import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.Flag; import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; +import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.RegionContainer; +import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class WorldGuardManager { - public static StateFlag flag; + private static StateFlag flag; private final RFChairs plugin = RFChairs.getInstance(); - public WorldGuard worldGuard; + private WorldGuard worldGuard; public WorldGuardManager() { } @@ -36,9 +35,9 @@ public void register() { FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry(); try { registry.register(flag); - plugin.log("Custom Flag Registered!"); + plugin.getComponentLogger().info("Custom Flag Registered!"); } catch (FlagConflictException e) { - plugin.log("Unable to register custom worldguard flag!"); + plugin.getComponentLogger().warn("Unable to register custom worldguard flag!", e); } } @@ -53,31 +52,25 @@ public void register() { } public boolean validateSeating(@NotNull Chair chair, @NotNull Player player) { - double xPos = chair.getLocation().getX(); - double yPos = chair.getLocation().getY(); - double zPos = chair.getLocation().getZ(); - - WorldGuardManager worldManager = plugin.getWorldGuardManager(); - - LocalPlayer localPlayer = worldManager.getWorldGuard().wrapPlayer(player); - - BlockVector3 vector3 = BlockVector3.at(xPos, yPos, zPos); - - List regionSetList = getContainer().getLoaded().stream() - .map(manager -> manager.getApplicableRegions(vector3)) - .toList(); - - if (regionSetList.isEmpty()) return true; - - return regionSetList.stream() - .allMatch(set -> set.testState(localPlayer, (StateFlag) worldManager.getFlag())); + RegionContainer container = getContainer(); + Location chairLocation = chair.getLocation(); + RegionManager regionManager = container.get(BukkitAdapter.adapt(chairLocation.getWorld())); + + if (regionManager != null) { + com.sk89q.worldedit.util.Location weLoc = BukkitAdapter.adapt(chairLocation); + LocalPlayer wgPlayer = getWorldGuard().wrapPlayer(player); + ApplicableRegionSet applicableRegions = regionManager.getApplicableRegions(weLoc.toVector().toBlockPoint()); + return applicableRegions.testState(wgPlayer, getFlag()); + } else { + return true; + } } public RegionContainer getContainer() { return worldGuard.getPlatform().getRegionContainer(); } - public Flag getFlag() { + public @NotNull StateFlag getFlag() { return flag; } } diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java index 14c306f..23f7448 100644 --- a/src/main/java/com/rifledluffy/chairs/utility/Util.java +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -5,6 +5,7 @@ import com.rifledluffy.chairs.chairs.Chair; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Bisected; @@ -45,6 +46,10 @@ private static boolean validatedChair(@NotNull Block block) { return BlockFilter.isStairsBlock(block.getType()) && validStair(block); } + private static boolean isAir(Material type) { + return type == Material.AIR || type == Material.CAVE_AIR || type == Material.VOID_AIR; + } + public static boolean playerIsSeated(@NotNull UUID uuid, @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap) { Chair chair = chairMap.get(uuid); return chair != null; @@ -66,7 +71,7 @@ public static boolean surroundedBlock(@NotNull Block block) { private static boolean validExit(@NotNull Block block) { Material type = block.getType(); - return type == Material.AIR || type.name().equals("WALL_SIGN") || type.name().endsWith("_WALL_SIGN"); + return isAir(type) || Tag.WALL_SIGNS.isTagged(type); } public static boolean isLiquidOrMagma(@NotNull Block block) { @@ -88,7 +93,7 @@ public static boolean validCouch(@NotNull Block block) { BlockFace side = faces.get(0); BlockFace otherSide = faces.get(1); - if (block.getRelative(BlockFace.UP).getType() != Material.AIR) { + if (!isAir(block.getRelative(BlockFace.UP).getType())) { return false; } @@ -298,11 +303,11 @@ public static Block getBlockFromDirection(@NotNull Block block, @NotNull String } public static boolean canFitPlayer(@NotNull Block block) { - return block.getType() == Material.AIR && block.getRelative(BlockFace.UP).getType() == Material.AIR; + return isAir(block.getType()) && isAir(block.getRelative(BlockFace.UP).getType()); } public static boolean safePlace(@NotNull Block block) { - return block.getRelative(BlockFace.DOWN).getType() != Material.AIR; + return !isAir(block.getRelative(BlockFace.DOWN).getType()); } public static Vector getVectorDir(@NotNull Location caster, @NotNull Location target) { From e76de21b50dbcf31ca66e0174cdda1ac60b081d9 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 05:49:18 +0100 Subject: [PATCH 07/18] proper relocate bstats --- build.gradle.kts | 7 + .../java/com/rifledluffy/chairs/RFChairs.java | 4 +- .../chairs/metrics/MetricsLite.java | 293 ------------------ 3 files changed, 9 insertions(+), 295 deletions(-) delete mode 100644 src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java diff --git a/build.gradle.kts b/build.gradle.kts index f5964be..06cf36f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ plugins { //java id("io.papermc.paperweight.userdev") version "1.5.11" id("xyz.jpenilla.run-paper") version "2.2.3" // Adds runServer and runMojangMappedServer tasks for testing + id("com.github.johnrengelman.shadow") version "8.1.1" // shades bstats } group = "com.rifledluffy.chairs" @@ -35,6 +36,7 @@ dependencies { compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") compileOnly("org.jetbrains:annotations:24.1.0") implementation("com.github.ben-manes.caffeine:caffeine:3.1.8") // caches + implementation("org.bstats:bstats-bukkit:3.0.2") } tasks { @@ -43,6 +45,11 @@ tasks { dependsOn(reobfJar) } + shadowJar { + // Relocates the packages of bstats so they don't conflict with other plugins + relocate("org.bstats", "com.rifledluffy.chairs.dependencies.bstats") + } + compileJava { options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 5e49448..f5c864a 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -4,7 +4,7 @@ import com.rifledluffy.chairs.command.CommandManager; import com.rifledluffy.chairs.config.ConfigManager; import com.rifledluffy.chairs.dependencymanagers.WorldGuardManager; -import com.rifledluffy.chairs.metrics.MetricsLite; +import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; @@ -54,7 +54,7 @@ private void loadWorldGuard() { @Override public void onEnable() { @SuppressWarnings("unused") - MetricsLite metrics = new MetricsLite(); + Metrics metrics = new Metrics(this, 2979); commandManager = new CommandManager(); commandManager.setup(); diff --git a/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java b/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java deleted file mode 100644 index 4cc8c23..0000000 --- a/src/main/java/com/rifledluffy/chairs/metrics/MetricsLite.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.rifledluffy.chairs.metrics; - -import com.rifledluffy.chairs.RFChairs; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.ServicePriority; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -import javax.net.ssl.HttpsURLConnection; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.logging.Level; -import java.util.zip.GZIPOutputStream; - -/** - * bStats collects some data for plugin authors. - *

- * Check out bStats.org to learn more about bStats! - */ -public class MetricsLite { - // The version of this bStats class - public static final int B_STATS_VERSION = 1; - // The url to which the data is sent - private static final @NotNull String URL = "https://bStats.org/submitData/bukkit"; - // Should failed requests be logged? - private static boolean logFailedRequests; - // The uuid of the server - private static String serverUUID; - - static { - // You can use the property to disable the check in your test environment - if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) { - // Mavens Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D - final String defaultPackage = new String( - new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'}); - final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); - // We want to make sure nobody just copy & pastes the example and use the wrong package names - if (MetricsLite.class.getPackage().getName().equals(defaultPackage) || MetricsLite.class.getPackage().getName().equals(examplePackage)) { - throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } - } - } - - public MetricsLite() { - // Get the config file - File bStatsFolder = new File(RFChairs.getInstance().getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - - // Check if the config file exists - if (!config.isSet("serverUuid")) { - - // Add default values - config.addDefault("enabled", true); - // Every server gets it's unique random id. - config.addDefault("serverUuid", UUID.randomUUID().toString()); - // Should failed request be logged? - config.addDefault("logFailedRequests", false); - - // Inform the server owners about bStats - config.options().setHeader( - List.of( - "bStats collects some data for plugin authors like how many servers are using their plugins.", - "To honor their work, you should not disable it.", - "This has nearly no effect on the server performance!", - "Check out https://bStats.org/ to learn more :)") - - ).copyDefaults(true); - try { - config.save(configFile); - } catch (IOException ignored) { - } - } - - // Load the data - serverUUID = config.getString("serverUuid"); - logFailedRequests = config.getBoolean("logFailedRequests", false); - if (config.getBoolean("enabled", true)) { - boolean found = false; - // Search for all other bStats Metrics classes to see if we are the first one - for (Class service : Bukkit.getServicesManager().getKnownServices()) { - try { - service.getField("B_STATS_VERSION"); // Our identifier :) - found = true; // We aren't the first - break; - } catch (NoSuchFieldException ignored) { - } - } - // Register our service - Bukkit.getServicesManager().register(MetricsLite.class, this, RFChairs.getInstance(), ServicePriority.Normal); - if (!found) { - // We are the first! - startSubmitting(); - } - } - } - - /** - * Sends the data to the bStats server. - * - * @param data The data to send. - * @throws Exception If the request failed. - */ - private static void sendData(@NotNull JSONObject data) throws Exception { - if (Bukkit.isPrimaryThread()) { - throw new IllegalAccessException("This method must not be called from the main thread!"); - } - HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); - - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - - // Add headers - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format - connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); - - // Send data - connection.setDoOutput(true); - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - outputStream.write(compressedData); - outputStream.flush(); - outputStream.close(); - - connection.getInputStream().close(); // We don't care about the response - Just send our data :) - } - - /** - * Gzips the given String. - * - * @param str The string to gzip. - * @return The gzipped String. - * @throws IOException If the compression failed. - */ - @Contract("null -> null; !null -> !null") - private static byte @Nullable [] compress(final @Nullable String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - GZIPOutputStream gzip = new GZIPOutputStream(outputStream); - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - gzip.close(); - return outputStream.toByteArray(); - } - - /** - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { - final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - if (!RFChairs.getInstance().isEnabled()) { // Plugin was disabled - timer.cancel(); - return; - } - // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler - // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) - Bukkit.getScheduler().runTask(RFChairs.getInstance(), () -> submitData()); - } - }, 1000 * 60 * 5, 1000 * 60 * 30); - // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start - // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! - // WARNING: Just don't do it! - } - - /** - * Gets the plugin specific data. - * This method is called using Reflection. - * - * @return The plugin specific data. - */ - @SuppressWarnings("unchecked") - public @NotNull JSONObject getPluginData() { - JSONObject data = new JSONObject(); - - String pluginName = RFChairs.getInstance().getDescription().getName(); - String pluginVersion = RFChairs.getInstance().getDescription().getVersion(); - - data.put("pluginName", pluginName); // Append the name of the plugin - data.put("pluginVersion", pluginVersion); // Append the version of the plugin - JSONArray customCharts = new JSONArray(); - data.put("customCharts", customCharts); - - return data; - } - - /** - * Gets the server specific data. - * - * @return The server specific data. - */ - @SuppressWarnings("unchecked") - private @NotNull JSONObject getServerData() { - // Minecraft specific data - int playerAmount; - try { - // Around MC 1.8 the return type was changed to a collection from an array, - // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); - playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class) - ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { - playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed - } - int onlineMode = Bukkit.getOnlineMode() ? 1 : 0; - String bukkitVersion = Bukkit.getVersion(); - bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1); - - // OS/Java specific data - String javaVersion = System.getProperty("java.version"); - String osName = System.getProperty("os.name"); - String osArch = System.getProperty("os.arch"); - String osVersion = System.getProperty("os.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - JSONObject data = new JSONObject(); - - data.put("serverUUID", serverUUID); - - data.put("playerAmount", playerAmount); - data.put("onlineMode", onlineMode); - data.put("bukkitVersion", bukkitVersion); - - data.put("javaVersion", javaVersion); - data.put("osName", osName); - data.put("osArch", osArch); - data.put("osVersion", osVersion); - data.put("coreCount", coreCount); - - return data; - } - - /** - * Collects the data and sends it afterwards. - */ - @SuppressWarnings("unchecked") - private void submitData() { - final JSONObject data = getServerData(); - - JSONArray pluginData = new JSONArray(); - // Search for all other bStats Metrics classes to get their plugin data - for (Class service : Bukkit.getServicesManager().getKnownServices()) { - try { - service.getField("B_STATS_VERSION"); // Our identifier :) - - for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) { - try { - pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider())); - } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | - InvocationTargetException ignored) { - } - } - } catch (NoSuchFieldException ignored) { - } - } - - data.put("plugins", pluginData); - - // Create a new thread for the connection to the bStats server - new Thread(() -> { - try { - // Send the data - sendData(data); - } catch (Exception e) { - // Something went wrong! :( - if (logFailedRequests) { - RFChairs.getInstance().getLogger().log(Level.WARNING, "Could not submit plugin stats of " + RFChairs.getInstance().getName(), e); - } - } - }).start(); - } -} From ec91a410cbbc40ef5b551a7d35feb16a64fd5875 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 06:06:56 +0100 Subject: [PATCH 08/18] some clean up --- src/main/java/com/rifledluffy/chairs/ChairManager.java | 8 ++++---- src/main/java/com/rifledluffy/chairs/RFChairs.java | 2 +- src/main/java/com/rifledluffy/chairs/TargetInfo.java | 2 +- .../com/rifledluffy/chairs/command/CommandManager.java | 7 ++----- .../chairs/dependencymanagers/WorldGuardManager.java | 2 +- src/main/resources/config.yml | 2 -- 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index db1ab4d..2111168 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -58,8 +58,8 @@ public class ChairManager implements Listener { private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); private boolean regenWhenSitting; //Update related - private boolean disableCurrentUpdate; //todo - private boolean disableUpdates; //todo + //private boolean disableCurrentUpdate; //todo + //private boolean disableUpdates; //todo //Kick them off their seat if they take damage private boolean canLaunch; //Toss them off their seat if they take damage @@ -89,8 +89,8 @@ public void reload(RFChairs plugin) { regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); regenWhenSitting = config.getBoolean("regen-when-sitting", true); - disableCurrentUpdate = config.getBoolean("disable-update-message-if-on-latest", false); - disableUpdates = config.getBoolean("disable-update-messages", false); + //disableCurrentUpdate = config.getBoolean("disable-update-message-if-on-latest", false); + //disableUpdates = config.getBoolean("disable-update-messages", false); faceAttacker = config.getBoolean("face-attacker-when-ejected", false); canToss = config.getBoolean("toss-player", false); diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index f5c864a..7d534dd 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -87,7 +87,7 @@ public void onDisable() { getLogger().info("Saving Configuration Files!"); cfgManager.saveData(); - Bukkit.getOnlinePlayers().forEach(p -> { + Bukkit.getOnlinePlayers().forEach(p -> { // todo just clearing regen from everyone is NOT right. should only clear sitting players PotionEffect regen = p.getPotionEffect(PotionEffectType.REGENERATION); if (regen == null) return; if (regen.getDuration() > 1000) p.removePotionEffect(PotionEffectType.REGENERATION); diff --git a/src/main/java/com/rifledluffy/chairs/TargetInfo.java b/src/main/java/com/rifledluffy/chairs/TargetInfo.java index 6079ee7..6dd86df 100644 --- a/src/main/java/com/rifledluffy/chairs/TargetInfo.java +++ b/src/main/java/com/rifledluffy/chairs/TargetInfo.java @@ -49,6 +49,6 @@ protected boolean hasSource() { } protected boolean livingSource() { - return source != null && source instanceof LivingEntity; + return source instanceof LivingEntity; } } diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index 8b26360..14a9173 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -78,11 +78,8 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return sc; } - String[] aliases; - int length = (aliases = sc.aliases()).length; - - for (int var5 = 0; var5 < length; ++var5) { - String alias = aliases[var5]; + String[] aliases = sc.aliases(); + for (String alias : aliases) { if (name.equalsIgnoreCase(alias)) { return sc; } diff --git a/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java index 88adc48..0e7293a 100644 --- a/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java +++ b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java @@ -36,7 +36,7 @@ public void register() { try { registry.register(flag); plugin.getComponentLogger().info("Custom Flag Registered!"); - } catch (FlagConflictException e) { + } catch (FlagConflictException | IllegalStateException e) { plugin.getComponentLogger().warn("Unable to register custom worldguard flag!", e); } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f0d60ce..002c2b6 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -35,8 +35,6 @@ stair-seating-position: 0.5,0.3,0.5 slab-seating-positiong: 0.5,0.3,0.5 carpet-seating-position: 0.5,-0.15,0.5 -disable-update-message-if-on-latest: false -disable-update-messages: false exit-seat-where-facing: false allow-trap-door-chairs: true require-empty-hand: false From 7899e0982cb8f582d87d8b0ffd0c451005224a9a Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 06:29:22 +0100 Subject: [PATCH 09/18] load legacy named whitelist --- src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java index 6fd4e05..a08a990 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java @@ -15,6 +15,7 @@ public class BlockFilter { public static void reload() { FileConfiguration config = RFChairs.getInstance().getConfig(); whitelist = new HashSet<>(config.getStringList("whitelisted-chairs")); + whitelist.addAll(config.getStringList("allowed-chairs")); // dataFixerUpper blacklist = new HashSet<>(config.getStringList("blacklisted-chairs")); } From 6fdd93560a6a0fd755bc1bfd1af45f3e3171e4b4 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 06:49:26 +0100 Subject: [PATCH 10/18] Fix flying players if block was broken --- .../com/rifledluffy/chairs/ChairManager.java | 49 ++++++++++++------- .../chairs/config/ConfigManager.java | 5 -- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index 2111168..cac392f 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -229,7 +229,7 @@ private void onToss(@NotNull ChairTossEvent event) { } if (canToss) { // todo shouldn't this check be higher up? - ejectPlayer(block, player, attacker); + tossPlayer(block, player, attacker); } } @@ -389,20 +389,23 @@ private void onChangeGameMode(@NotNull PlayerGameModeChangeEvent event) { if (event.isCancelled()) return; GameMode gameMode = event.getNewGameMode(); Chair chair = chairMap.get(event.getPlayer().getUniqueId()); - if (gameMode == GameMode.SPECTATOR && chair != null) clearChair(chair); + if (gameMode == GameMode.SPECTATOR && chair != null) { + clearChair(chair); + } } @EventHandler private void onDismount(@NotNull EntityDismountEvent event) { if (!(event.getEntity() instanceof Player player)) return; Chair chair = chairMap.get(player.getUniqueId()); - event.getDismounted(); + if (chair == null || event.getDismounted().getType() != EntityType.ARMOR_STAND) return; if (leaving.contains(player.getUniqueId())) return; if (orienting.contains(player.getUniqueId())) { orienting.remove(player.getUniqueId()); return; } + if (tossed.containsKey(player.getUniqueId())) { TargetInfo info = tossed.get(player.getUniqueId()); Entity attacker = info.getAttacker(); @@ -410,7 +413,7 @@ private void onDismount(@NotNull EntityDismountEvent event) { attacker = info.getLivingSource(); } - ChairTossEvent tossEvent = new ChairTossEvent(chairMap.get(player.getUniqueId()), player, attacker, info, false); + ChairTossEvent tossEvent = new ChairTossEvent(chair, player, attacker, info, false); tossEvent.callEvent(); tossed.remove(player.getUniqueId()); return; @@ -451,19 +454,27 @@ private void takeDamage(@NotNull EntityDamageByEntityEvent event) { info = new TargetInfo(source, attacker, event.getDamage()); } tossed.put(player.getUniqueId(), info); - if (chair.getFakeSeat() != null) chair.getFakeSeat().removePassenger(player); + if (chair.getFakeSeat() != null) { + chair.getFakeSeat().removePassenger(player); + } } } - @EventHandler + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + // we want to act after the event may was canceled by protection plugins private void onBlockBreak(@NotNull BlockBreakEvent event) { - if (event.isCancelled()) return; chairs.stream() - .filter(c -> c.getLocation() != null) - .filter(c -> Util.samePosition(event.getBlock(), c.getLocation())) + .filter(chair -> chair.getLocation() != null) + .filter(chair -> Util.samePosition(event.getBlock(), chair.getLocation())) .findAny() - .ifPresent(c -> { - if (!event.getPlayer().hasPermission("rfchairs.break")) event.setCancelled(true); + .ifPresent(chair -> { + if (!event.getPlayer().hasPermission("rfchairs.break")) { + event.setCancelled(true); + } else { // eject player if block was broken. Note: the dismount event will handle the rest. + if (chair.getFakeSeat() != null) { + chair.getFakeSeat().removePassenger(event.getPlayer()); + } + } }); } @@ -471,8 +482,10 @@ private void onBlockBreak(@NotNull BlockBreakEvent event) { private void quit(@NotNull PlayerQuitEvent event) { Player player = event.getPlayer(); Chair chair = chairMap.get(player.getUniqueId()); - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); - leaveEvent.callEvent(); + if (chair != null) { + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player, exitWhereFacing); + leaveEvent.callEvent(); + } } @EventHandler @@ -505,8 +518,10 @@ private void pistonRetract(@NotNull BlockPistonRetractEvent event) { private void onDeath(@NotNull PlayerDeathEvent event) { Player player = event.getEntity(); Chair chair = chairMap.get(player.getUniqueId()); - ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); - leaveEvent.callEvent(); + if (chair != null) { + ChairLeaveEvent leaveEvent = new ChairLeaveEvent(chair, player); + leaveEvent.callEvent(); + } } /* @@ -526,7 +541,7 @@ private boolean sitPlayer(@NotNull Chair chair, @NotNull Player player) { return true; } - private void ejectPlayer(Block block, Player player, Entity entity) { + private void tossPlayer(@NotNull Block block, @NotNull Player player, @NotNull Entity entity) { Block exit = block; if (exitWhereFacing) { @@ -612,7 +627,7 @@ private void clearChairs() { for (Chair chair : chairs) clearChair(chair); } - private void clearPlayer(Player player) { + private void clearPlayer(@NotNull Player player) { Chair chair = chairMap.get(player.getUniqueId()); if (chair == null) return; chairMap.remove(player.getUniqueId()); diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index 1cd51ae..73f8a22 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -4,7 +4,6 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -74,8 +73,4 @@ public void saveConfig() { public void reloadConfig() { config = YamlConfiguration.loadConfiguration(configFile); } - - public PluginDescriptionFile getDesc() { - return plugin.getDescription(); - } } \ No newline at end of file From 54ddc2f121483b79ce51c44eaa3329878dba6c5d Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 07:09:29 +0100 Subject: [PATCH 11/18] forgot to change the description --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 06cf36f..3febb61 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { group = "com.rifledluffy.chairs" version = "7.0.0-SNAPSHOT" -description = "A Greensurvivors Plugin " +description = "Chairs but Rifle's way." // this is the minecraft major version. If you need a subversion like 1.20.1, // change it in the dependencies section as this is also used as the api version of the plugin.yml val mainMCVersion by extra("1.20") @@ -46,7 +46,7 @@ tasks { } shadowJar { - // Relocates the packages of bstats so they don't conflict with other plugins + // Relocates the packages of bstats, so they don't conflict with other plugins relocate("org.bstats", "com.rifledluffy.chairs.dependencies.bstats") } From 800ad48175a3efc65d65ccd515505e9426ce5e40 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 27 Mar 2024 07:36:46 +0100 Subject: [PATCH 12/18] added tabCompletion --- .../chairs/command/CommandManager.java | 44 ++++++++++++++++--- .../chairs/command/commands/HelpCommand.java | 6 +++ .../chairs/command/commands/InfoCommand.java | 6 +++ .../chairs/command/commands/MuteCommand.java | 6 +++ .../command/commands/ReloadCommand.java | 6 +++ .../chairs/command/commands/ResetCommand.java | 6 +++ .../chairs/command/commands/SubCommand.java | 3 ++ .../command/commands/ToggleCommand.java | 6 +++ 8 files changed, 77 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index 14a9173..67a3bed 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -5,17 +5,16 @@ import com.rifledluffy.chairs.messages.MessagePath; import com.rifledluffy.chairs.messages.PlaceHolder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; +import org.bukkit.command.*; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -public class CommandManager implements CommandExecutor { +public class CommandManager implements CommandExecutor, TabCompleter { private static final String MAIN_COMMAND = "rfchairs"; private final @NotNull ArrayList<@NotNull SubCommand> subCommands = new ArrayList<>(); @@ -27,7 +26,13 @@ public CommandManager() { } public void setup() { - RFChairs.getInstance().getCommand(MAIN_COMMAND).setExecutor(this); + PluginCommand mainCmd = RFChairs.getInstance().getCommand(MAIN_COMMAND); + if (mainCmd != null) { + mainCmd.setExecutor(this); + mainCmd.setTabCompleter(this); + } else { + RFChairs.getInstance().getComponentLogger().error("Could not get main command! Commands WILL be broken!"); + } this.subCommands.add(new HelpCommand()); //this.commands.add(new InfoCommand()); @@ -37,7 +42,7 @@ public void setup() { this.subCommands.add(new MuteCommand()); } - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (args.length == 0) { RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NOT_ENOUGH_ARGS); return true; @@ -92,4 +97,31 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command public @NotNull ArrayList<@NotNull SubCommand> getSubCommands() { return subCommands; } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length == 1) { + List result = new ArrayList<>(); + + for (SubCommand subCommand : subCommands) { + if (subCommand.checkPermission(sender)) { + result.add(subCommand.name()); + } + } + + return result; + } else if (args.length > 1) { + SubCommand subCommand = this.getSubcommand(args[0]); + + if (subCommand != null && subCommand.checkPermission(sender)) { + // clear args from subcommand + ArrayList subcommandArgList = new ArrayList<>(Arrays.asList(args)); + subcommandArgList.remove(0); + + return subCommand.onTabComplete(sender, subcommandArgList); + } + } + + return null; + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java index e63c26d..d644598 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java @@ -13,6 +13,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -67,4 +68,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return true; } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java index 1813c55..d00edad 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -43,4 +44,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return permissible.hasPermission("rfchairs.info"); } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java index 3186821..f8cae3d 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.UUID; @@ -54,4 +55,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return permissible.hasPermission("rfchairs.mute"); } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java index cbd7052..8779f69 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java @@ -9,6 +9,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -55,4 +56,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return permissible.hasPermission("rfchairs.reload") || permissible.hasPermission("rfchairs.manage"); } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java index 1846604..9857a60 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -7,6 +7,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -50,4 +51,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return permissible.hasPermission("rfchairs.reset") || permissible.hasPermission("rfchairs.manage"); } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java index 0df9891..2858fe6 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -26,4 +27,6 @@ public interface SubCommand { boolean needsPlayer(); boolean checkPermission(@NotNull Permissible permissible); + + @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args); } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java index 8d4770b..588abd2 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java @@ -10,6 +10,7 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.UUID; @@ -59,4 +60,9 @@ public boolean needsPlayer() { public boolean checkPermission(@NotNull Permissible permissible) { return permissible.hasPermission("rfchairs.toggle"); } + + @Override + public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return null; + } } From 711188bca1e84fa02f32253ed78770762c83d7e0 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Sun, 4 Aug 2024 15:15:21 +0200 Subject: [PATCH 13/18] better logging paper plugin 1.21 --- build.gradle.kts | 36 ++++----------- .../com/rifledluffy/chairs/ChairManager.java | 44 +++++++++---------- .../rifledluffy/chairs/MessageManager.java | 2 +- .../java/com/rifledluffy/chairs/RFChairs.java | 6 +-- .../rifledluffy/chairs/RFChairsLoader.java | 27 ++++++++++++ .../chairs/command/CommandManager.java | 21 ++++----- .../chairs/command/commands/HelpCommand.java | 5 +-- .../chairs/command/commands/InfoCommand.java | 5 +-- .../chairs/command/commands/MuteCommand.java | 5 +-- .../command/commands/ReloadCommand.java | 7 ++- .../chairs/command/commands/ResetCommand.java | 7 ++- .../chairs/command/commands/SubCommand.java | 3 +- .../command/commands/ToggleCommand.java | 5 +-- .../chairs/config/ConfigManager.java | 4 +- .../{plugin.yml => paper-plugin.yml} | 12 ++--- 15 files changed, 91 insertions(+), 98 deletions(-) create mode 100644 src/main/java/com/rifledluffy/chairs/RFChairsLoader.java rename src/main/resources/{plugin.yml => paper-plugin.yml} (81%) diff --git a/build.gradle.kts b/build.gradle.kts index 3febb61..86c9363 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,7 @@ plugins { `java-library` - //java - id("io.papermc.paperweight.userdev") version "1.5.11" + id("io.papermc.paperweight.userdev") version "1.7.1" id("xyz.jpenilla.run-paper") version "2.2.3" // Adds runServer and runMojangMappedServer tasks for testing - id("com.github.johnrengelman.shadow") version "8.1.1" // shades bstats } group = "com.rifledluffy.chairs" @@ -11,11 +9,12 @@ version = "7.0.0-SNAPSHOT" description = "Chairs but Rifle's way." // this is the minecraft major version. If you need a subversion like 1.20.1, // change it in the dependencies section as this is also used as the api version of the plugin.yml -val mainMCVersion by extra("1.20") +val mcVersion by extra("1.21") +paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION java { // Configure the java toolchain. This allows gradle to auto-provision JDK 17 on systems that only have JDK 8 installed for example. - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } repositories { @@ -32,30 +31,20 @@ repositories { } dependencies { - paperweight.paperDevBundle("$mainMCVersion.1-R0.1-SNAPSHOT") - compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + paperweight.paperDevBundle("$mcVersion-R0.1-SNAPSHOT") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT") compileOnly("org.jetbrains:annotations:24.1.0") implementation("com.github.ben-manes.caffeine:caffeine:3.1.8") // caches implementation("org.bstats:bstats-bukkit:3.0.2") } tasks { - // Configure reobfJar to run when invoking the build task - assemble { - dependsOn(reobfJar) - } - - shadowJar { - // Relocates the packages of bstats, so they don't conflict with other plugins - relocate("org.bstats", "com.rifledluffy.chairs.dependencies.bstats") - } - compileJava { options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. // See https://openjdk.java.net/jeps/247 for more information. - options.release.set(17) + options.release.set(21) } processResources { @@ -63,15 +52,6 @@ tasks { expand("version" to project.version, "description" to project.description, - "apiVersion" to mainMCVersion) - } - - /* - reobfJar { - // This is an example of how you might change the output location for reobfJar. It's recommended not to do this - // for a variety of reasons, however it's asked frequently enough that an example of how to do it is included here. - outputJar.set(layout.buildDirectory.file("libs/PaperweightTestPlugin-${project.version}.jar")) + "apiVersion" to mcVersion) } - */ - } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index cac392f..80a62d6 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -2,7 +2,6 @@ import com.rifledluffy.chairs.chairs.BlockFilter; import com.rifledluffy.chairs.chairs.Chair; -import com.rifledluffy.chairs.config.ConfigManager; import com.rifledluffy.chairs.events.*; import com.rifledluffy.chairs.messages.MessageEvent; import com.rifledluffy.chairs.messages.MessagePath; @@ -23,6 +22,7 @@ import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDismountEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -30,19 +30,17 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.spigotmc.event.entity.EntityDismountEvent; import java.util.*; import java.util.stream.Collectors; public class ChairManager implements Listener { - private final @NotNull RFChairs plugin = RFChairs.getPlugin(RFChairs.class); + private final @NotNull RFChairs plugin; private final @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap = new HashMap<>(); private final @NotNull List<@NotNull String> fakeSeats = new ArrayList<>(); private final @NotNull List<@NotNull UUID> leaving = new ArrayList<>(); @@ -53,9 +51,7 @@ public class ChairManager implements Listener { private Vector stairSeatingPosition; private Vector slabSeatingPosition; private Vector carpetSeatingPosition; - private ConfigManager configManager = plugin.getConfigManager(); - private FileConfiguration config = configManager.getConfig(); - private PotionEffect regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); + private PotionEffect regenEffect; private boolean regenWhenSitting; //Update related //private boolean disableCurrentUpdate; //todo @@ -82,9 +78,13 @@ public class ChairManager implements Listener { private boolean exitWhereFacing; private @NotNull List<@NotNull World> disabledWorlds = new ArrayList<>(); - public void reload(RFChairs plugin) { - configManager = plugin.getConfigManager(); - config = configManager.getConfig(); + public ChairManager(@NotNull RFChairs plugin) { + this.plugin = plugin; + this.regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, plugin.getConfigManager().getConfig().getInt("regen-potency", 0), false, false); + } + + public void reload() { + FileConfiguration config = plugin.getConfigManager().getConfig(); regenEffect = new PotionEffect(PotionEffectType.REGENERATION, 655200, config.getInt("regen-potency", 0), false, false); regenWhenSitting = config.getBoolean("regen-when-sitting", true); @@ -537,7 +537,7 @@ private boolean sitPlayer(@NotNull Chair chair, @NotNull Player player) { fakeSeat.addPassenger(player); chair.setFakeSeat(fakeSeat); fakeSeats.add(fakeSeat.getUniqueId().toString()); - configManager.getData().set("UUIDs", fakeSeats); + plugin.getConfigManager().getData().set("UUIDs", fakeSeats); return true; } @@ -591,25 +591,25 @@ private Block findExitPoint(Location entity, Block block) { void saveToggled() { List ids = new ArrayList<>(); if (toggled.isEmpty()) { - configManager.getData().set("Toggled", new ArrayList()); + plugin.getConfigManager().getData().set("Toggled", new ArrayList()); } for (UUID id : toggled) { ids.add(id.toString()); } - plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had toggled off."); - configManager.getData().set("Toggled", ids); + plugin.getLogger().info("Saving " + ids.size() + " Players that had toggled off."); + plugin.getConfigManager().getData().set("Toggled", ids); } void loadToggled() { - List toggled = configManager.getData().getStringList("Toggled"); + List toggled = plugin.getConfigManager().getData().getStringList("Toggled"); if (toggled.isEmpty()) return; - plugin.getServer().getLogger().info(toggled.size() + " Players had toggled off. Adding Them..."); + plugin.getLogger().info(toggled.size() + " Players had toggled off. Adding Them..."); toggled.stream() .map(UUID::fromString) .forEach(this.toggled::add); - configManager.getData().set("Toggled", new ArrayList()); + plugin.getConfigManager().getData().set("Toggled", new ArrayList()); } void shutdown() { @@ -639,20 +639,20 @@ public void clearFakeSeats() { for (Chair chair : chairs) clearChair(chair); } - public void clearFakeSeatsFromFile(JavaPlugin plugin) { - List fakes = configManager.getData().getStringList("UUIDs"); + public void clearFakeSeatsFromFile() { + List fakes = plugin.getConfigManager().getData().getStringList("UUIDs"); int leftoverFakes = fakes.size(); if (leftoverFakes >= 1) { - plugin.getServer().getLogger().info("Detected " + fakes.size() + " leftover seats! Removing..."); + plugin.getLogger().info("Detected " + fakes.size() + " leftover seats! Removing..."); for (String fake : fakes) { UUID id = UUID.fromString(fake); Entity armorStand = plugin.getServer().getEntity(id); if (armorStand == null) continue; armorStand.remove(); } - configManager.getData().set("UUIDs", new ArrayList()); + plugin.getConfigManager().getData().set("UUIDs", new ArrayList()); } else { - plugin.getServer().getLogger().info("No fake seats remaining! Proceeding"); + plugin.getLogger().info("No fake seats remaining! Proceeding"); } } diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java index bc32399..684ee28 100644 --- a/src/main/java/com/rifledluffy/chairs/MessageManager.java +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -302,7 +302,7 @@ void saveMuted() { for (UUID id : muted) { ids.add(id.toString()); } - plugin.getServer().getLogger().info("Saving " + ids.size() + " Players that had events muted."); + plugin.getLogger().info("Saving " + ids.size() + " Players that had events muted."); configManager.getData().set("Muted", ids); } diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 7d534dd..85abf61 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -61,15 +61,15 @@ public void onEnable() { loadConfigManager(); - chairManager = new ChairManager(); - chairManager.clearFakeSeatsFromFile(this); + chairManager = new ChairManager(this); + chairManager.clearFakeSeatsFromFile(); chairManager.loadToggled(); messageManager = new MessageManager(); messageManager.loadMuted(); BlockFilter.reload(); - chairManager.reload(this); + chairManager.reload(); messageManager.reload(); getServer().getPluginManager().registerEvents(chairManager, this); getServer().getPluginManager().registerEvents(messageManager, this); diff --git a/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java b/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java new file mode 100644 index 0000000..c79335b --- /dev/null +++ b/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java @@ -0,0 +1,27 @@ +package com.rifledluffy.chairs; + +import io.papermc.paper.plugin.loader.PluginClasspathBuilder; +import io.papermc.paper.plugin.loader.PluginLoader; +import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.repository.RemoteRepository; +import org.jetbrains.annotations.NotNull; + +@SuppressWarnings("UnstableApiUsage") +public class RFChairsLoader implements PluginLoader { + @Override + public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { + classpathBuilder.getContext().getLogger().info("loading RFChairs libraries!"); + + MavenLibraryResolver resolver = new MavenLibraryResolver(); + resolver.addRepository(new RemoteRepository.Builder("central", "default", "https://repo1.maven.org/maven2/").build()); + resolver.addRepository(new RemoteRepository.Builder("bstats", "default", "https://repo.codemc.org/repository/maven-public").build()); + + resolver.addDependency(new Dependency(new DefaultArtifact("org.bstats:bstats-bukkit:3.0.2"), null)); // todo insert versions + resolver.addDependency(new Dependency(new DefaultArtifact("com.github.ben-manes.caffeine:caffeine:3.1.8"), null)); + System.setProperty("bstats.relocatecheck", "false"); // bstats author is stubborn and only allows the use via relocation. + + classpathBuilder.addLibrary(resolver); + } +} diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index 67a3bed..c42994b 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -5,6 +5,7 @@ import com.rifledluffy.chairs.messages.MessagePath; import com.rifledluffy.chairs.messages.PlaceHolder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Location; import org.bukkit.command.*; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -14,11 +15,12 @@ import java.util.Arrays; import java.util.List; -public class CommandManager implements CommandExecutor, TabCompleter { +public class CommandManager extends Command { private static final String MAIN_COMMAND = "rfchairs"; private final @NotNull ArrayList<@NotNull SubCommand> subCommands = new ArrayList<>(); public CommandManager() { + super(MAIN_COMMAND, "The main prefix for other commands. Type /rfchairs help for more info", "/", List.of("rfc")); } public static @NotNull String getMainCommand() { @@ -26,13 +28,7 @@ public CommandManager() { } public void setup() { - PluginCommand mainCmd = RFChairs.getInstance().getCommand(MAIN_COMMAND); - if (mainCmd != null) { - mainCmd.setExecutor(this); - mainCmd.setTabCompleter(this); - } else { - RFChairs.getInstance().getComponentLogger().error("Could not get main command! Commands WILL be broken!"); - } + RFChairs.getInstance().getServer().getCommandMap().register("rfchairs", this); this.subCommands.add(new HelpCommand()); //this.commands.add(new InfoCommand()); @@ -42,7 +38,8 @@ public void setup() { this.subCommands.add(new MuteCommand()); } - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + @Override + public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) { if (args.length == 0) { RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NOT_ENOUGH_ARGS); return true; @@ -58,7 +55,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command // clear args from subcommand ArrayList subcommandArgList = new ArrayList<>(Arrays.asList(args)); - subcommandArgList.remove(0); + subcommandArgList.removeFirst(); if (target.checkPermission(sender)) { if (target.needsPlayer()) { @@ -99,7 +96,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) { if (args.length == 1) { List result = new ArrayList<>(); @@ -122,6 +119,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } } - return null; + return List.of(); } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java index d644598..6975e26 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/HelpCommand.java @@ -13,7 +13,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -70,7 +69,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java index d00edad..e86bd28 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/InfoCommand.java @@ -5,7 +5,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -46,7 +45,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java index f8cae3d..9d17477 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/MuteCommand.java @@ -8,7 +8,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.UUID; @@ -57,7 +56,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java index 8779f69..83e4d26 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ReloadCommand.java @@ -9,7 +9,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -22,7 +21,7 @@ public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull Stri newConfig.reloadConfig(); plugin.setConfigManager(newConfig); BlockFilter.reload(); - plugin.getChairManager().reload(plugin); + plugin.getChairManager().reload(); plugin.getMessageManager().reload(); plugin.getMessageManager().sendLang(sender, MessagePath.COMMAND_RELOAD_SUCCESS); } @@ -58,7 +57,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java index 9857a60..985bfa3 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -16,7 +15,7 @@ public class ResetCommand implements SubCommand { public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { plugin.getChairManager().clearFakeSeats(); - plugin.getChairManager().clearFakeSeatsFromFile(plugin); + plugin.getChairManager().clearFakeSeatsFromFile(); plugin.getLogger().info("Chairs Reset!"); plugin.getMessageManager().sendLang(sender, MessagePath.COMMAND_RESET_SUCCESS); @@ -53,7 +52,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } \ No newline at end of file diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java index 2858fe6..58c7967 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/SubCommand.java @@ -5,7 +5,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -28,5 +27,5 @@ public interface SubCommand { boolean checkPermission(@NotNull Permissible permissible); - @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args); + @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args); } diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java index 588abd2..84e6e6d 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ToggleCommand.java @@ -10,7 +10,6 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.UUID; @@ -62,7 +61,7 @@ public boolean checkPermission(@NotNull Permissible permissible) { } @Override - public @Nullable List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { - return null; + public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { + return List.of(); } } diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index 73f8a22..edc1253 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -35,7 +35,7 @@ public void setup() { try { fakeFile.createNewFile(); } catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not create fakes.yml!"); + plugin.getLogger().info("Could not create fakes.yml!"); } } @@ -50,7 +50,7 @@ public void saveData() { try { fake.save(fakeFile); } catch (IOException e) { - Bukkit.getServer().getLogger().info("[Rifle's Chairs] Could not save fakes.yml!"); + plugin.getLogger().info("Could not save fakes.yml!"); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/paper-plugin.yml similarity index 81% rename from src/main/resources/plugin.yml rename to src/main/resources/paper-plugin.yml index e8c71f0..469de16 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -1,17 +1,13 @@ main: com.rifledluffy.chairs.RFChairs +loader: com.rifledluffy.chairs.RFChairsLoader name: RFChairs api-version: '${apiVersion}' version: ${version} description: ${description} authors: [ Rifle D. Luffy, VicenteRD, carlpoole, i0xHeX, GreensurvivorsTeam ] -softdepend: [ WorldGuard, WorldEdit ] -libraries: - - com.github.ben-manes.caffeine:caffeine:3.1.8 -commands: - rfchairs: - usage: / - description: The main prefix for other commands. Type /rfchairs help for more info - aliases: [ rfc ] +softdepend: + - WorldGuard + - WorldEdit permissions: rfchairs.use: description: Use of chairs From f275f41013791944e6f4fbce490baf46ddf5f011 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Fri, 20 Dec 2024 02:55:00 +0100 Subject: [PATCH 14/18] update gradle and its plugins update dependencies update minecraft to the latest stable paper build (1.21.4 does not work currently, probably do to the hard fork restructure) fix config key "slab-seating-position" having a tailing "g", thanks @seema84 moved the default values up, as the old ones looked wrong and resulted in glitching through blocks in case of carpets (some minecraft update changed the point of seating on armor stands down) removed helper method to check if a Material is air, as Material already has a method for this. --- build.gradle.kts | 12 +++++----- gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 ++++-- gradlew.bat | 22 ++++++++++-------- .../rifledluffy/chairs/RFChairsLoader.java | 2 +- .../chairs/command/CommandManager.java | 2 +- .../chairs/config/ConfigManager.java | 1 - .../chairs/messages/MessageEvent.java | 4 ++-- .../com/rifledluffy/chairs/utility/Util.java | 12 ++++------ src/main/resources/config.yml | 12 +++++----- 11 files changed, 38 insertions(+), 38 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 86c9363..334bf78 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,15 +1,15 @@ plugins { `java-library` - id("io.papermc.paperweight.userdev") version "1.7.1" - id("xyz.jpenilla.run-paper") version "2.2.3" // Adds runServer and runMojangMappedServer tasks for testing + id("io.papermc.paperweight.userdev") version "1.7.7" + id("xyz.jpenilla.run-paper") version "2.3.1" // Adds runServer and runMojangMappedServer tasks for testing } group = "com.rifledluffy.chairs" -version = "7.0.0-SNAPSHOT" +version = "7.0.1-SNAPSHOT" description = "Chairs but Rifle's way." // this is the minecraft major version. If you need a subversion like 1.20.1, // change it in the dependencies section as this is also used as the api version of the plugin.yml -val mcVersion by extra("1.21") +val mcVersion by extra("1.21.3") paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION java { @@ -33,9 +33,9 @@ repositories { dependencies { paperweight.paperDevBundle("$mcVersion-R0.1-SNAPSHOT") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT") - compileOnly("org.jetbrains:annotations:24.1.0") + compileOnly("org.jetbrains:annotations:26.0.1") implementation("com.github.ben-manes.caffeine:caffeine:3.1.8") // caches - implementation("org.bstats:bstats-bukkit:3.0.2") + implementation("org.bstats:bstats-bukkit:3.1.0") } tasks { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22c..e2847c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4..f5feea6 100644 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..9d21a21 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 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. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ 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. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java b/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java index c79335b..9d81f2e 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairsLoader.java @@ -18,7 +18,7 @@ public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { resolver.addRepository(new RemoteRepository.Builder("central", "default", "https://repo1.maven.org/maven2/").build()); resolver.addRepository(new RemoteRepository.Builder("bstats", "default", "https://repo.codemc.org/repository/maven-public").build()); - resolver.addDependency(new Dependency(new DefaultArtifact("org.bstats:bstats-bukkit:3.0.2"), null)); // todo insert versions + resolver.addDependency(new Dependency(new DefaultArtifact("org.bstats:bstats-bukkit:3.1.0"), null)); // todo insert versions resolver.addDependency(new Dependency(new DefaultArtifact("com.github.ben-manes.caffeine:caffeine:3.1.8"), null)); System.setProperty("bstats.relocatecheck", "false"); // bstats author is stubborn and only allows the use via relocation. diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index c42994b..e6f5471 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -113,7 +113,7 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLab if (subCommand != null && subCommand.checkPermission(sender)) { // clear args from subcommand ArrayList subcommandArgList = new ArrayList<>(Arrays.asList(args)); - subcommandArgList.remove(0); + subcommandArgList.removeFirst(); return subCommand.onTabComplete(sender, subcommandArgList); } diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index edc1253..92818e8 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -1,7 +1,6 @@ package com.rifledluffy.chairs.config; import com.rifledluffy.chairs.RFChairs; -import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; diff --git a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java index 912e3f4..5866247 100644 --- a/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java +++ b/src/main/java/com/rifledluffy/chairs/messages/MessageEvent.java @@ -52,11 +52,11 @@ public void setAudience(@NotNull Audience audience) { this.audience = audience; } - public @NotNull TagResolver[] getResolvers() { + public @NotNull TagResolver @Nullable [] getResolvers() { return resolvers; } - public void setResolvers(@NotNull TagResolver[] replacingResolvers) { + public void setResolvers(@NotNull TagResolver @Nullable [] replacingResolvers) { this.resolvers = replacingResolvers; } } diff --git a/src/main/java/com/rifledluffy/chairs/utility/Util.java b/src/main/java/com/rifledluffy/chairs/utility/Util.java index 23f7448..bc7ead3 100644 --- a/src/main/java/com/rifledluffy/chairs/utility/Util.java +++ b/src/main/java/com/rifledluffy/chairs/utility/Util.java @@ -46,10 +46,6 @@ private static boolean validatedChair(@NotNull Block block) { return BlockFilter.isStairsBlock(block.getType()) && validStair(block); } - private static boolean isAir(Material type) { - return type == Material.AIR || type == Material.CAVE_AIR || type == Material.VOID_AIR; - } - public static boolean playerIsSeated(@NotNull UUID uuid, @NotNull Map<@NotNull UUID, @NotNull Chair> chairMap) { Chair chair = chairMap.get(uuid); return chair != null; @@ -71,7 +67,7 @@ public static boolean surroundedBlock(@NotNull Block block) { private static boolean validExit(@NotNull Block block) { Material type = block.getType(); - return isAir(type) || Tag.WALL_SIGNS.isTagged(type); + return type.isAir() || Tag.WALL_SIGNS.isTagged(type); } public static boolean isLiquidOrMagma(@NotNull Block block) { @@ -93,7 +89,7 @@ public static boolean validCouch(@NotNull Block block) { BlockFace side = faces.get(0); BlockFace otherSide = faces.get(1); - if (!isAir(block.getRelative(BlockFace.UP).getType())) { + if (!block.getRelative(BlockFace.UP).getType().isAir()) { return false; } @@ -303,11 +299,11 @@ public static Block getBlockFromDirection(@NotNull Block block, @NotNull String } public static boolean canFitPlayer(@NotNull Block block) { - return isAir(block.getType()) && isAir(block.getRelative(BlockFace.UP).getType()); + return block.getType().isAir() && block.getRelative(BlockFace.UP).getType().isAir(); } public static boolean safePlace(@NotNull Block block) { - return !isAir(block.getRelative(BlockFace.DOWN).getType()); + return !block.getRelative(BlockFace.DOWN).getType().isAir(); } public static Vector getVectorDir(@NotNull Location caster, @NotNull Location target) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 002c2b6..6f9accb 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,9 +1,9 @@ # Rifle's Chair plugin by Rifle D. Luffy # Version 6.0 # #=============[Seat Configuration]=============## -# stair-seating-position: The exact positions of where the armorstand spawns on a stair; default 0.35,0.3,0.5 -# slab-seating-position: The exact positions of where the armorstand spawns on a slab; default 0.5,0.3,0.5 -# carpet-seating-position: The exact positions of where the armorstand spawns on a carpet; default 0.5,-0.15,0.5 +# stair-seating-position: The exact positions of where the armorstand spawns on a stair; default 0.5,0.5,0.5 +# slab-seating-position: The exact positions of where the armorstand spawns on a slab; default 0.5,0.5,0.5 +# carpet-seating-position: The exact positions of where the armorstand spawns on a carpet; default 0.5,0.1,0.5 # be careful when playing around with this feature! # in the format x,y,z where... # x is forward @@ -32,9 +32,9 @@ # regen-potency: the regen potion effect level where 0 is level 1 # allow-custom-messages: allow the use of custom messages when events are triggered # whitelisted-chairs: The chairs that people are allowed to sit on -stair-seating-position: 0.5,0.3,0.5 -slab-seating-positiong: 0.5,0.3,0.5 -carpet-seating-position: 0.5,-0.15,0.5 +stair-seating-position: 0.5,0.5,0.5 +slab-seating-position: 0.5,0.5,0.5 +carpet-seating-position: 0.5,0.1,0.5 exit-seat-where-facing: false allow-trap-door-chairs: true require-empty-hand: false From c5ee19f185f66f6c239ee3c7c101d6e592ea32f9 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Fri, 20 Dec 2024 03:55:08 +0100 Subject: [PATCH 15/18] Added download plugins to runServer task, to test with worldguard without having to download it manually. Removed wrong comment --- build.gradle.kts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 334bf78..eda991d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,13 +7,11 @@ plugins { group = "com.rifledluffy.chairs" version = "7.0.1-SNAPSHOT" description = "Chairs but Rifle's way." -// this is the minecraft major version. If you need a subversion like 1.20.1, -// change it in the dependencies section as this is also used as the api version of the plugin.yml val mcVersion by extra("1.21.3") paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION java { - // Configure the java toolchain. This allows gradle to auto-provision JDK 17 on systems that only have JDK 8 installed for example. + // Configure the java toolchain. This allows gradle to auto-provision JDK 21 on systems that only have JDK 8 installed for example. toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } @@ -54,4 +52,11 @@ tasks { "description" to project.description, "apiVersion" to mcVersion) } + + runServer { + downloadPlugins { + modrinth("worldguard", "7.0.13-beta-1") + modrinth("worldedit", "Bu1zaaoc") + } + } } \ No newline at end of file From 75616ccd68c93fd02ef0049786263473f2504d7b Mon Sep 17 00:00:00 2001 From: FireInstall Date: Fri, 20 Dec 2024 15:08:12 +0100 Subject: [PATCH 16/18] remove legacy "allowed-chairs" from config to not confuse users with old configs --- .../java/com/rifledluffy/chairs/ChairManager.java | 5 +++-- .../com/rifledluffy/chairs/chairs/BlockFilter.java | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index 80a62d6..ed6efa4 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -647,8 +647,9 @@ public void clearFakeSeatsFromFile() { for (String fake : fakes) { UUID id = UUID.fromString(fake); Entity armorStand = plugin.getServer().getEntity(id); - if (armorStand == null) continue; - armorStand.remove(); + if (armorStand != null) { + armorStand.remove(); + } } plugin.getConfigManager().getData().set("UUIDs", new ArrayList()); } else { diff --git a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java index a08a990..c37a6a7 100644 --- a/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java +++ b/src/main/java/com/rifledluffy/chairs/chairs/BlockFilter.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import java.util.HashSet; +import java.util.List; import java.util.Set; public class BlockFilter { @@ -15,7 +16,15 @@ public class BlockFilter { public static void reload() { FileConfiguration config = RFChairs.getInstance().getConfig(); whitelist = new HashSet<>(config.getStringList("whitelisted-chairs")); - whitelist.addAll(config.getStringList("allowed-chairs")); // dataFixerUpper + + // dataFixerUpper + if (config.contains("allowed-chairs")) { + whitelist.addAll(config.getStringList("allowed-chairs")); + config.set("allowed-chairs", null); + config.set("whitelisted-chairs", List.copyOf(whitelist)); + RFChairs.getInstance().saveConfig(); + } + blacklist = new HashSet<>(config.getStringList("blacklisted-chairs")); } From 1383f8cc54aea1af6eb9197ef13de8e1ccf25f94 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Wed, 22 Apr 2026 19:05:18 +0200 Subject: [PATCH 17/18] use ComponentLogger Drop deprecated UTF8BundleControl bump gradle Didn't update to newer minecraft version to wait on PR #3 --- build.gradle.kts | 39 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- .../com/rifledluffy/chairs/ChairManager.java | 8 ++-- .../rifledluffy/chairs/MessageManager.java | 28 +++++++------ .../java/com/rifledluffy/chairs/RFChairs.java | 29 +++++--------- .../chairs/command/CommandManager.java | 8 ++-- .../chairs/command/commands/ResetCommand.java | 2 +- .../chairs/config/ConfigManager.java | 6 +-- .../dependencymanagers/WorldGuardManager.java | 31 ++++++--------- 9 files changed, 67 insertions(+), 86 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index eda991d..2375a9c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `java-library` - id("io.papermc.paperweight.userdev") version "1.7.7" - id("xyz.jpenilla.run-paper") version "2.3.1" // Adds runServer and runMojangMappedServer tasks for testing + id("io.papermc.paperweight.userdev") version "2.0.0-beta.19" + id("xyz.jpenilla.run-paper") version "2.3.1" // Adds runServer and runMojangMappedServer tasks for testing } group = "com.rifledluffy.chairs" @@ -11,8 +11,8 @@ val mcVersion by extra("1.21.3") paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION java { - // Configure the java toolchain. This allows gradle to auto-provision JDK 21 on systems that only have JDK 8 installed for example. - toolchain.languageVersion.set(JavaLanguageVersion.of(21)) + // Configure the java toolchain. This allows gradle to auto-provision JDK 21 on systems that only have JDK 8 installed for example. + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } repositories { @@ -31,27 +31,26 @@ repositories { dependencies { paperweight.paperDevBundle("$mcVersion-R0.1-SNAPSHOT") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT") - compileOnly("org.jetbrains:annotations:26.0.1") implementation("com.github.ben-manes.caffeine:caffeine:3.1.8") // caches implementation("org.bstats:bstats-bukkit:3.1.0") } tasks { - compileJava { - options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything - - // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. - // See https://openjdk.java.net/jeps/247 for more information. - options.release.set(21) - } - - processResources { - filteringCharset = Charsets.UTF_8.name() // We want UTF-8 for everything - - expand("version" to project.version, - "description" to project.description, - "apiVersion" to mcVersion) - } + compileJava { + options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything + + // Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable. + // See https://openjdk.java.net/jeps/247 for more information. + options.release.set(21) + } + + processResources { + filteringCharset = Charsets.UTF_8.name() // We want UTF-8 for everything + + expand("version" to project.version, + "description" to project.description!!, + "apiVersion" to mcVersion) + } runServer { downloadPlugins { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2847c8..c61a118 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/rifledluffy/chairs/ChairManager.java b/src/main/java/com/rifledluffy/chairs/ChairManager.java index ed6efa4..ae9e637 100644 --- a/src/main/java/com/rifledluffy/chairs/ChairManager.java +++ b/src/main/java/com/rifledluffy/chairs/ChairManager.java @@ -596,14 +596,14 @@ void saveToggled() { for (UUID id : toggled) { ids.add(id.toString()); } - plugin.getLogger().info("Saving " + ids.size() + " Players that had toggled off."); + plugin.getComponentLogger().info("Saving " + ids.size() + " Players that had toggled off."); plugin.getConfigManager().getData().set("Toggled", ids); } void loadToggled() { List toggled = plugin.getConfigManager().getData().getStringList("Toggled"); if (toggled.isEmpty()) return; - plugin.getLogger().info(toggled.size() + " Players had toggled off. Adding Them..."); + plugin.getComponentLogger().info(toggled.size() + " Players had toggled off. Adding Them..."); toggled.stream() .map(UUID::fromString) @@ -643,7 +643,7 @@ public void clearFakeSeatsFromFile() { List fakes = plugin.getConfigManager().getData().getStringList("UUIDs"); int leftoverFakes = fakes.size(); if (leftoverFakes >= 1) { - plugin.getLogger().info("Detected " + fakes.size() + " leftover seats! Removing..."); + plugin.getComponentLogger().info("Detected " + fakes.size() + " leftover seats! Removing..."); for (String fake : fakes) { UUID id = UUID.fromString(fake); Entity armorStand = plugin.getServer().getEntity(id); @@ -653,7 +653,7 @@ public void clearFakeSeatsFromFile() { } plugin.getConfigManager().getData().set("UUIDs", new ArrayList()); } else { - plugin.getLogger().info("No fake seats remaining! Proceeding"); + plugin.getComponentLogger().info("No fake seats remaining! Proceeding"); } } diff --git a/src/main/java/com/rifledluffy/chairs/MessageManager.java b/src/main/java/com/rifledluffy/chairs/MessageManager.java index 684ee28..e078500 100644 --- a/src/main/java/com/rifledluffy/chairs/MessageManager.java +++ b/src/main/java/com/rifledluffy/chairs/MessageManager.java @@ -10,7 +10,6 @@ import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import net.kyori.adventure.util.UTF8ResourceBundleControl; import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -25,7 +24,6 @@ import java.nio.charset.StandardCharsets; import java.security.CodeSource; import java.util.*; -import java.util.logging.Level; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -135,7 +133,7 @@ private void initLangFiles() { try (InputStreamReader reader = new InputStreamReader(new FileInputStream(langFile), StandardCharsets.UTF_8)) { current.load(reader); } catch (Exception e) { - plugin.getLogger().log(Level.WARNING, "couldn't get current properties file for " + entryName + "!", e); + plugin.getComponentLogger().warn("couldn't get current properties file for " + entryName + "!", e); continue; } @@ -149,7 +147,7 @@ private void initLangFiles() { bw.write("# New Values where added. Is everything else up to date? Time of update: " + new Date()); bw.newLine(); - plugin.getLogger().fine("Updated langfile \"" + entryName + "\". Might want to check the new translation strings out!"); + plugin.getComponentLogger().debug("Updated langfile \"" + entryName + "\". Might want to check the new translation strings out!"); updated = true; } @@ -168,10 +166,10 @@ private void initLangFiles() { } // doesn't match } // end of elements } catch (IOException e) { - plugin.getLogger().log(Level.WARNING, "Couldn't save lang files", e); + plugin.getComponentLogger().warn("Couldn't save lang files", e); } } else { - plugin.getLogger().warning("Couldn't save lang files: no CodeSource!"); + plugin.getComponentLogger().warn("Couldn't save lang files: no CodeSource!"); } } @@ -188,25 +186,25 @@ public void reload() { initLangFiles(); Locale locale = Locale.forLanguageTag(localeTag); - plugin.getLogger().info("Locale set to language: " + locale.toLanguageTag()); + plugin.getComponentLogger().info("Locale set to language: " + locale.toLanguageTag()); File langDictionary = new File(plugin.getDataFolder(), BUNDLE_NAME); URL[] urls; try { urls = new URL[]{langDictionary.toURI().toURL()}; - messages = ResourceBundle.getBundle(BUNDLE_NAME, locale, new URLClassLoader(urls), UTF8ResourceBundleControl.get()); + messages = ResourceBundle.getBundle(BUNDLE_NAME, locale, new URLClassLoader(urls)); } catch (SecurityException | MalformedURLException e) { - plugin.getLogger().log(Level.WARNING, "Exception while reading lang bundle. Using internal", e); + plugin.getComponentLogger().warn("Exception while reading lang bundle. Using internal", e); } catch (MissingResourceException ignored) { // how? missing write access? - plugin.getLogger().log(Level.WARNING, "No translation file for " + UTF8ResourceBundleControl.get().toBundleName(BUNDLE_NAME, locale) + " found on disc. Using internal"); + plugin.getComponentLogger().warn("No translation file for " + localeTag + " found on disc. Using internal"); } if (messages == null) { // fallback, since we are always trying to save defaults this never should happen try { - messages = PropertyResourceBundle.getBundle(BUNDLE_NAME, locale, plugin.getClass().getClassLoader(), new UTF8ResourceBundleControl()); + messages = PropertyResourceBundle.getBundle(BUNDLE_NAME, locale, plugin.getClass().getClassLoader()); } catch (MissingResourceException e) { - plugin.getLogger().log(Level.SEVERE, "Couldn't get Ressource bundle \"lang\" for locale \"" + locale.toLanguageTag() + "\". Messages WILL be broken!", e); + plugin.getComponentLogger().error("Couldn't get Ressource bundle \"lang\" for locale \"" + locale.toLanguageTag() + "\". Messages WILL be broken!", e); } } } @@ -215,7 +213,7 @@ public void reload() { try { return messages.getString(path.getPath()); } catch (MissingResourceException | ClassCastException e) { - plugin.getLogger().log(Level.WARNING, "couldn't find path: \"" + path.getPath() + "\" in lang files using fallback.", e); + plugin.getComponentLogger().warn("couldn't find path: \"" + path.getPath() + "\" in lang files using fallback.", e); return path.getPath(); } } @@ -302,7 +300,7 @@ void saveMuted() { for (UUID id : muted) { ids.add(id.toString()); } - plugin.getLogger().info("Saving " + ids.size() + " Players that had events muted."); + plugin.getComponentLogger().info("Saving " + ids.size() + " Players that had events muted."); configManager.getData().set("Muted", ids); } @@ -311,7 +309,7 @@ void loadMuted() { if (muted.isEmpty()) { return; } - plugin.getServer().getLogger().info(muted.size() + " Players had events muted off. Adding Them..."); + plugin.getComponentLogger().info(muted.size() + " Players had events muted off. Adding Them..."); for (String toggler : muted) { UUID id = UUID.fromString(toggler); this.muted.add(id); diff --git a/src/main/java/com/rifledluffy/chairs/RFChairs.java b/src/main/java/com/rifledluffy/chairs/RFChairs.java index 85abf61..d92e09b 100644 --- a/src/main/java/com/rifledluffy/chairs/RFChairs.java +++ b/src/main/java/com/rifledluffy/chairs/RFChairs.java @@ -23,27 +23,19 @@ public class RFChairs extends JavaPlugin { return instance; } - private static void setInstance(@NotNull RFChairs instance) { - RFChairs.instance = instance; - } - @Override public void onLoad() { - setInstance(this); + instance = this; loadWorldGuard(); } private void loadWorldGuard() { try { - Class.forName("com.sk89q.worldguard.WorldGuard"); - Class.forName("com.sk89q.worldedit.WorldEdit"); - Class.forName("com.sk89q.worldedit.math.BlockVector3"); - worldGuardManager = new WorldGuardManager(); - worldGuardManager.setup(); - getLogger().info("Found WorldGuard && WorldEdit! Applying Custom Flag..."); - } catch (ClassNotFoundException e) { - getLogger().info("Missing either WorldGuard or WorldEdit! Disabling Custom Flag Features..."); - getLogger().info("Latest WorldGuard/WorldEdit features could be missing. Please Update!"); + worldGuardManager = new WorldGuardManager(this); + getComponentLogger().info("Found WorldGuard & WorldEdit! Applying Custom Flag..."); + } catch (NoClassDefFoundError e) { + getComponentLogger().info("Missing either WorldGuard or WorldEdit! Disabling Custom Flag Features..."); + getComponentLogger().info("Latest WorldGuard features could be missing. Please Update!", e); } if (worldGuardManager != null) { @@ -53,8 +45,7 @@ private void loadWorldGuard() { @Override public void onEnable() { - @SuppressWarnings("unused") - Metrics metrics = new Metrics(this, 2979); + new Metrics(this, 2979); commandManager = new CommandManager(); commandManager.setup(); @@ -74,7 +65,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(chairManager, this); getServer().getPluginManager().registerEvents(messageManager, this); - getLogger().info("Rifle's Chairs has been enabled!"); + getComponentLogger().info("Rifle's Chairs has been enabled!"); } @Override @@ -84,7 +75,7 @@ public void onDisable() { chairManager.shutdown(); - getLogger().info("Saving Configuration Files!"); + getComponentLogger().info("Saving Configuration Files!"); cfgManager.saveData(); Bukkit.getOnlinePlayers().forEach(p -> { // todo just clearing regen from everyone is NOT right. should only clear sitting players @@ -93,7 +84,7 @@ public void onDisable() { if (regen.getDuration() > 1000) p.removePotionEffect(PotionEffectType.REGENERATION); }); - getLogger().info("Rifle's Chairs has been disabled!"); + getComponentLogger().info("Rifle's Chairs has been disabled!"); } public void loadConfigManager() { diff --git a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java index e6f5471..21e760b 100644 --- a/src/main/java/com/rifledluffy/chairs/command/CommandManager.java +++ b/src/main/java/com/rifledluffy/chairs/command/CommandManager.java @@ -6,7 +6,8 @@ import com.rifledluffy.chairs.messages.PlaceHolder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.Location; -import org.bukkit.command.*; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,7 +40,7 @@ public void setup() { } @Override - public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) { + public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String @NotNull [] args) { if (args.length == 0) { RFChairs.getInstance().getMessageManager().sendLang(sender, MessagePath.COMMAND_NOT_ENOUGH_ARGS); return true; @@ -96,7 +97,8 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLab } @Override - public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) { + public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, + @Nullable Location location) { if (args.length == 1) { List result = new ArrayList<>(); diff --git a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java index 985bfa3..5aad2a3 100644 --- a/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java +++ b/src/main/java/com/rifledluffy/chairs/command/commands/ResetCommand.java @@ -16,7 +16,7 @@ public class ResetCommand implements SubCommand { public void onCommand(@NotNull CommandSender sender, @NotNull List<@NotNull String> args) { plugin.getChairManager().clearFakeSeats(); plugin.getChairManager().clearFakeSeatsFromFile(); - plugin.getLogger().info("Chairs Reset!"); + plugin.getComponentLogger().info("Chairs Reset!"); plugin.getMessageManager().sendLang(sender, MessagePath.COMMAND_RESET_SUCCESS); } diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index 92818e8..1f18929 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -34,7 +34,7 @@ public void setup() { try { fakeFile.createNewFile(); } catch (IOException e) { - plugin.getLogger().info("Could not create fakes.yml!"); + plugin.getComponentLogger().info("Could not create fakes.yml!"); } } @@ -49,7 +49,7 @@ public void saveData() { try { fake.save(fakeFile); } catch (IOException e) { - plugin.getLogger().info("Could not save fakes.yml!"); + plugin.getComponentLogger().info("Could not save fakes.yml!"); } } @@ -65,7 +65,7 @@ public void saveConfig() { try { config.save(configFile); } catch (IOException e) { - plugin.getLogger().info("[Rifle's Chairs] Could not save config.yml!"); + plugin.getComponentLogger().info("[Rifle's Chairs] Could not save config.yml!"); } } diff --git a/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java index 0e7293a..cfeaadf 100644 --- a/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java +++ b/src/main/java/com/rifledluffy/chairs/dependencymanagers/WorldGuardManager.java @@ -14,20 +14,21 @@ import com.sk89q.worldguard.protection.regions.RegionContainer; import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class WorldGuardManager { private static StateFlag flag; - private final RFChairs plugin = RFChairs.getInstance(); - private WorldGuard worldGuard; + private final RFChairs plugin; + private final @NotNull WorldGuardPlugin worldGuard; - public WorldGuardManager() { - } + public WorldGuardManager(final @NotNull RFChairs plugin) { + this.plugin = plugin; - public void setup() { - worldGuard = WorldGuard.getInstance(); + if (plugin.getServer().getPluginManager().getPlugin("WorldGuard") instanceof WorldGuardPlugin worldGuardPlugin) { + worldGuard = worldGuardPlugin; + } else { + throw new IllegalStateException("WorldGuard plugin is not found!"); + } } public void register() { @@ -41,16 +42,6 @@ public void register() { } } - public @Nullable WorldGuardPlugin getWorldGuard() { // todo cache the plugin - Plugin plugin = this.plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - - if (plugin instanceof WorldGuardPlugin worldGuardPlugin) { - return worldGuardPlugin; - } else { - return null; - } - } - public boolean validateSeating(@NotNull Chair chair, @NotNull Player player) { RegionContainer container = getContainer(); Location chairLocation = chair.getLocation(); @@ -58,7 +49,7 @@ public boolean validateSeating(@NotNull Chair chair, @NotNull Player player) { if (regionManager != null) { com.sk89q.worldedit.util.Location weLoc = BukkitAdapter.adapt(chairLocation); - LocalPlayer wgPlayer = getWorldGuard().wrapPlayer(player); + LocalPlayer wgPlayer = worldGuard.wrapPlayer(player); ApplicableRegionSet applicableRegions = regionManager.getApplicableRegions(weLoc.toVector().toBlockPoint()); return applicableRegions.testState(wgPlayer, getFlag()); } else { @@ -67,7 +58,7 @@ public boolean validateSeating(@NotNull Chair chair, @NotNull Player player) { } public RegionContainer getContainer() { - return worldGuard.getPlatform().getRegionContainer(); + return WorldGuard.getInstance().getPlatform().getRegionContainer(); } public @NotNull StateFlag getFlag() { From 8a082bbc1a4ff7c06a712551fc09ea12461cca98 Mon Sep 17 00:00:00 2001 From: FireInstall Date: Sun, 14 Jun 2026 00:49:45 +0200 Subject: [PATCH 18/18] Fix double plugin prefix in logger --- src/main/java/com/rifledluffy/chairs/config/ConfigManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java index 1f18929..92269f3 100644 --- a/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java +++ b/src/main/java/com/rifledluffy/chairs/config/ConfigManager.java @@ -65,7 +65,7 @@ public void saveConfig() { try { config.save(configFile); } catch (IOException e) { - plugin.getComponentLogger().info("[Rifle's Chairs] Could not save config.yml!"); + plugin.getComponentLogger().info("Could not save config.yml!"); } }