79 Commits
Author SHA1 Message Date
iGabyTM 2822ceba27 build: read version from MANIFEST 2024-08-26 03:19:43 +03:00
iGabyTM efcd61fcf1 misc: change version in PlayerExpansion.java 2024-08-26 03:10:01 +03:00
iGabyTM 05b48ac91c feat: add blitz's requested changes 2024-08-26 02:42:36 +03:00
iGabyTM 781c8fb287 build: add mavenCentral() 2024-08-24 18:12:54 +03:00
iGabyTM ee42c83c58 misc: change version to 2.1.0 2024-08-24 18:06:48 +03:00
iGabyTM 86f5ad6e10 add: is_gliding (close #87)
from javadoc: Checks to see if an entity is gliding, such as using an Elytra.
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/LivingEntity.html#isGliding()
2024-08-24 18:02:14 +03:00
iGabyTM 3ab412f79f Merge branch 'master' into feature/rewrite 2024-08-24 17:53:36 +03:00
iGabyTM 1174efe3b9 misc: delete old files 2024-08-24 17:43:26 +03:00
iGabyTM b4f88c831c feat: move some things around and switch to spigot-api 2024-08-24 17:42:24 +03:00
iGabyTM d3924df5ba feat: add world_time_(12|24) 2024-06-24 15:52:17 +03:00
iGabyTM 43da98e619 feat: add has_unlocked_recipe (close #37) 2024-06-24 14:01:27 +03:00
iGabyTM 1f2ab8e2f3 feat: add potion_effect_level (close #66) 2024-06-24 13:49:39 +03:00
iGabyTM de9307cea0 feat: add ping formatting rules (closes #85) 2024-01-25 21:37:47 +02:00
cj89898 56613e2539 Fixed locale for 1.20.2+ 2024-01-18 22:02:28 -06:00
iGabyTM 0e3405bb9c feat: add most of the placeholders 2023-12-31 15:40:33 +02:00
iGabyTM 658a76873c feat: add some *base* placeholders and util classes 2023-12-31 12:43:33 +02:00
iGabyTM 7a85f43bb6 build: switch to gradle 2023-12-31 12:26:08 +02:00
iGabyTM 5f97897647 release: 2.0.7
I've fetched the latest changes after I've released 2.0.6 =/
2023-10-14 20:15:52 +03:00
iGabyTM 2525959a52 release: 2.0.6 2023-10-09 22:58:29 +03:00
Gabriel Dumitru 66bc5ae67f Merge pull request #83 from PlaceholderAPI/feature/use_ping_method
feat: use `Player#getPing` for 1.17+
2023-08-27 15:46:02 +03:00
iGabyTM 9c063f57e2 feat: include VersionHelper
I somehow forgot to commit this 🤦‍♂️
2023-06-19 01:00:01 +03:00
iGabyTM 7bd64a9d88 feat: use Player#getPing for 1.17+
By doing this we won't need to update the expansion on every release that changes the name of the ping field
2023-06-19 00:52:44 +03:00
cj89898 99f128fa66 Merge pull request #81 from PlaceholderAPI/feat/1.20
feat: add support for player ping in 1.20
2023-06-16 11:40:13 -05:00
darbyjack b516ac0d4e fix: update version in main class as well 2023-06-10 09:50:00 -05:00
darbyjack 60bc8fabed feat: add support for player ping in 1.20 2023-06-10 08:27:34 -05:00
darbyjack 0ffb15aeb7 Bump to 2.0.4 2023-02-19 12:24:45 -06:00
Glare a2f5da710d Merge pull request #72 from kforbro/master 2023-02-19 12:20:32 -06:00
Glare 86b860e3ff Merge pull request #74 from WildTooth/master 2023-02-19 12:19:34 -06:00
WildTooth bbdb93199b Added %has_health_boost% and %health_boost% placeholders 2023-01-31 20:24:12 +01:00
kforbro b870442d19 fix %player_colored_ping_{name}% 2023-01-24 04:20:20 +03:00
Glare dabc840d90 Update PlayerExpansion.java 2022-07-07 09:33:51 -05:00
Gabriel Dumitru f8c4afbe4a Merge pull request #38 from stonar96/feature/player-list-name
Add %player_list_name% placeholder
2021-10-04 18:12:09 +03:00
Gabriel Dumitru cd6b0e368a Merge branch 'master' into feature/player-list-name 2021-10-04 18:11:52 +03:00
iGabyTM be1998ced3 increase version to 2.0.3 2021-10-01 13:22:16 +03:00
Gabriel Dumitru ab4bc1fa2f Merge pull request #62 from PlaceholderAPI/001-gaby-add-absorption-placeholder
add %player_absorption%
2021-10-01 12:41:41 +03:00
iGabyTM 1499333583 add %player_absorption% (closes #35) 2021-10-01 12:37:52 +03:00
iGabyTM 9b2c4b9cd8 add Matt's VersionHelper util 2021-10-01 12:37:12 +03:00
BlitzOffline 642c6fd755 Merge pull request #60 from BlitzOffline/master
Made direction output configurable
2021-09-05 23:48:06 +03:00
BlitzOffline 2133751f82 Made direction output configurable 2021-09-05 23:44:10 +03:00
BlitzOffline eb47b359d1 Merge pull request #58 from eDexiam/master
Ability to change "high" and "medium" ping values
2021-09-05 15:06:08 +03:00
BlitzOffline 9fcb92271f Merge pull request #45 from Wesley51/patch-1
Add new Placeholder block_underneath
2021-09-05 15:02:26 +03:00
BlitzOffline c00f74e758 Use p instead of player. 2021-09-05 15:00:38 +03:00
BlitzOffline 671a1f3159 Merge pull request #41 from RobinDeBaets/master 2021-09-05 14:57:15 +03:00
BlitzOffline 513b29a28a Merge pull request #59 from BlitzOffline/master 2021-09-05 14:56:40 +03:00
BlitzOffline c0a1780fba Added durability placeholders. 2021-09-05 14:43:44 +03:00
eDexiam 6772d34776 Restored default values from the official repo. 2021-08-03 21:48:52 +02:00
eDexiam a5b1a0dc10 Added ability to configure which ping threshold triggers what color. 2021-08-03 21:46:51 +02:00
darbyjack 473f637e0c Push to 2.0.2 to fix versioning issue. 2021-07-12 09:48:05 -05:00
Gabriel Dumitru 4e659ede76 Version 2.0.1 2021-07-12 05:36:29 +03:00
Gabriel Dumitru a95eb4a3a0 Add %player_(x/y/z)_long%
Unlike `%player_(x/y/z)%`, this placeholder will show player's exact location, including decimals
2021-07-12 05:35:24 +03:00
Glare 6782ea8c20 Merge pull request #54 from PlaceholderAPI/1.17 2021-06-20 18:29:48 -05:00
darbyjack e178109ecd Initial 1.17 support 2021-06-12 14:35:50 -05:00
Glare 51e2b7cab2 Merge pull request #51 from Maximvdw/master 2021-06-12 14:33:09 -05:00
Maxim Van de Wynckel fc6314ad59 fix: player ping on 1.17 2021-06-12 20:49:25 +02:00
Glare 62af0e19f2 Merge pull request #48 from Maximvdw/master
feat: added extra locale placeholders and online player flags for com…
2021-06-09 08:37:24 -05:00
Maxim Van de Wynckel bb3c3d1263 feat: added extra locale placeholders and online player flags for common actions 2021-06-09 15:09:20 +02:00
AliveSteve d249df9ba2 Add new Placeholder block_underneath
block_underneath will return the block the player that is directly underneath the player. May add one in later update that adds an extra placeholder that will not return blocks like lava, air. water, etc.
2021-03-28 21:29:10 -04:00
darbyjack 73cc29bc13 Manually set the expansion version 2021-03-28 13:55:33 -05:00
RobinDeBaets 81f5e8a846 Fixes #40 2020-12-12 13:29:02 +01:00
stonar96 55a9110683 Add %player_list_name% placeholder 2020-11-24 01:40:45 +01:00
darbyjack e2972eca90 Push to 1.8.0 2020-10-03 11:36:25 -05:00
Glare 8abf652099 Merge pull request #29 from PegasisForever/master 2020-09-28 10:45:44 -05:00
pegasis bda11eb9ac Merge remote-tracking branch 'upstream/master' into master
# Conflicts:
#	src/main/java/com/extendedclip/papi/expansion/player/PlayerExpansion.java
#	src/main/java/com/extendedclip/papi/expansion/player/PlayerUtil.java
2020-09-25 22:34:50 -04:00
darbyjack 6f3fc09c88 Implemented PRed pom changes
Closes #31
2020-09-25 19:26:23 -05:00
Glare 5ce42d7769 Merge pull request #34 from Frcsty/master
Added %player_yaw% and %player_pitch% placeholders
2020-09-25 19:22:14 -05:00
Glare 70d0b26591 Merge pull request #32 from PlaceholderAPI/fixes 2020-09-25 19:21:12 -05:00
pegasis 134e21af64 fix biome_capitalized again 2020-08-25 10:25:12 -04:00
pegasis 4c3982f872 solve some warnings 2020-08-25 10:00:53 -04:00
pegasis f27e675ce1 fix underscore in biome_capitalized 2020-08-25 09:37:55 -04:00
Frosty 9f1e5740ba Added %player_yaw% and %player_pitch% placeholders 2020-07-27 12:40:25 +02:00
Sxtanna 48842a7f9d updated player ping resolution to use cached reflection, and to color properly 2020-07-22 16:32:45 -04:00
Sxtanna d088649a1c added override annotation to onRequest :/ 2020-07-22 15:56:13 -04:00
Sxtanna 219833eb00 made classes final, made playerutil non instantiable 2020-07-22 15:54:54 -04:00
Sxtanna 1a59b183c8 updated gitignore to match papi's 2020-07-22 15:53:29 -04:00
pegasis fc4fe06fd5 use world environment to get world type instead of world name (thanks discord Illusion... Maybe?#2824) 2020-06-02 09:51:30 -04:00
pegasis c227977470 change biome_capitalize to biome_capitalized 2020-05-31 21:12:05 -04:00
pegasis 763f4f08cf fix getXZDirection 2020-05-31 20:57:00 -04:00
pegasis 0cf0b6aea5 add "world_type" 2020-05-31 20:56:51 -04:00
pegasis d8d639bbab add "direction_xz", "biome_capitalize", "light_level" 2020-05-31 20:35:56 -04:00
20 changed files with 1520 additions and 694 deletions

No files matched your search

+4 -145
View File
@@ -1,146 +1,5 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
### Eclipse Patch ###
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Ruby plugin and RubyMine
/.rakeTasks
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### 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
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
!/.mvn/wrapper/maven-wrapper.jar
### NetBeans ###
nbproject/private/
.idea/
.gradle/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
nbactions.xml
*.iml
+36
View File
@@ -0,0 +1,36 @@
plugins {
java
id("com.github.johnrengelman.shadow") version ("7.0.0")
}
group = "at.helpch.placeholderapi.expansion"
version = "2.1.0"
repositories {
mavenCentral()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
}
dependencies {
compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.3")
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
jar {
manifest {
attributes["Implementation-Title"] = "player"
attributes["Implementation-Version"] = project.version
}
}
shadowJar {
archiveFileName.set("PAPI-Expansion-Player-${project.version}.jar")
}
}
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+249
View File
@@ -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" "$@"
Vendored
+92
View File
@@ -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
-63
View File
@@ -1,63 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.extendedclip.papi.expansion.player</groupId>
<artifactId>player-expansion</artifactId>
<version>1.7.3</version>
<name>PAPI-Expansion-Player</name>
<description>PlaceholderAPI expansion for player placeholders</description>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>placeholderapi</id>
<url>http://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12-R0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.10.9</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<finalName>${name}</finalName>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
<encoding>UTF-8</encoding>
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1
View File
@@ -0,0 +1 @@
rootProject.name = 'player-expansion'
@@ -0,0 +1,526 @@
package at.helpch.placeholderapi.expansion.player;
import at.helpch.placeholderapi.expansion.player.handler.PlayerLocaleHandler;
import at.helpch.placeholderapi.expansion.player.ping.PingFormatter;
import at.helpch.placeholderapi.expansion.player.util.ItemUtil;
import at.helpch.placeholderapi.expansion.player.util.PlayerUtil;
import at.helpch.placeholderapi.expansion.player.util.TimeUtil;
import at.helpch.placeholderapi.expansion.player.util.VersionHelper;
import com.google.common.collect.ImmutableMap;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import me.clip.placeholderapi.expansion.Configurable;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;
public final class PlayerExpansion extends PlaceholderExpansion implements Configurable {
private PingFormatter pingFormatter;
private Map<String, Object> directionNames;
@Override
public @NotNull String getIdentifier() {
return "player";
}
@Override
public @NotNull String getAuthor() {
return "HelpChat";
}
@Override
public @NotNull String getVersion() {
return getClass().getPackage().getImplementationVersion();
}
@Override
public Map<String, Object> getDefaults() {
return ImmutableMap.<String, Object>builder()
.put("direction.north", "N")
.put("direction.north_east", "NE")
.put("direction.east", "E")
.put("direction.south_east", "SE")
.put("direction.south", "S")
.put("direction.south_west", "SW")
.put("direction.west", "W")
.put("direction.north_west", "NW")
.put("ping.formatting.>200", "&4")
.put("ping.formatting.>150", "&c")
.put("ping.formatting.>100", "&e")
.put("ping.formatting.>75", "&2")
.put("ping.formatting.>50", "&a")
.put("ping.formatting.>25", "&b")
.put("ping.formatting.=0", "&9")
.build();
}
@Override
public boolean canRegister() {
pingFormatter = new PingFormatter(getConfigSection("ping.formatting"));
directionNames = Optional.ofNullable(getConfigSection("direction"))
.map(section -> section.getValues(false))
.orElseGet(HashMap::new);
return true;
}
/**
* Format a {@code boolean} as {@link PlaceholderAPIPlugin#booleanTrue()} or {@link PlaceholderAPIPlugin#booleanFalse()}
*
* @param bool boolean
* @return {@link PlaceholderAPIPlugin#booleanTrue()} if the boolean is true, otherwise {@link PlaceholderAPIPlugin#booleanFalse()}
*/
private @NotNull String bool(final boolean bool) {
return bool ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
}
private @NotNull String getItemInfo(@Nullable final ItemStack item, @NotNull final String args) {
switch (args) {
case "_name":
return ItemUtil.getName(item);
case "_data":
return String.valueOf(ItemUtil.getDamage(item));
case "_durability":
return String.valueOf(ItemUtil.getDurability(item));
default:
return ItemUtil.getMaterialName(item);
}
}
@SuppressWarnings("SpellCheckingInspection")
@Override
public @Nullable String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
final boolean targetedPing = params.startsWith("ping_");
final boolean targetedColoredPing = params.startsWith("colored_ping_");
if (targetedPing || targetedColoredPing) {
final String targetName = params.substring((targetedPing ? "ping_" : "colored_ping_").length());
return Optional.ofNullable(Bukkit.getPlayerExact(targetName))
.map(target -> pingFormatter.getPing(target, targetedColoredPing))
.orElse("0");
}
if (offlinePlayer == null) {
return "";
}
switch (params) {
case "name":
return offlinePlayer.getName();
case "uuid":
return offlinePlayer.getUniqueId().toString();
case "first_played":
case "first_join":
return String.valueOf(offlinePlayer.getFirstPlayed());
case "first_played_formatted":
case "first_join_date":
return PlaceholderAPIPlugin.getDateFormat().format(new Date(offlinePlayer.getFirstPlayed()));
case "last_played":
case "last_join":
//noinspection deprecation
return String.valueOf(offlinePlayer.getLastPlayed());
case "last_played_formatted":
case "last_join_date":
//noinspection deprecation
return PlaceholderAPIPlugin.getDateFormat().format(new Date(offlinePlayer.getLastPlayed()));
//<editor-fold desc="Bed location placeholders">
case "bed_is_set":
return bool(offlinePlayer.getBedSpawnLocation() != null);
case "bed_x":
return PlayerUtil.getBedLocationInfo(offlinePlayer, "0", Location::getBlockX);
case "bed_y":
return PlayerUtil.getBedLocationInfo(offlinePlayer, "0", Location::getBlockY);
case "bed_z":
return PlayerUtil.getBedLocationInfo(offlinePlayer, "0", Location::getBlockZ);
case "bed_world":
return PlayerUtil.getBedLocationInfo(offlinePlayer, "N/A", location -> location.getWorld().getName());
//</editor-fold>
//<editor-fold desc="Various boolean placeholders">
case "has_played_before":
return bool(offlinePlayer.hasPlayedBefore());
case "is_banned":
return bool(offlinePlayer.isBanned());
case "is_op":
return bool(offlinePlayer.isOp());
case "is_whitelisted":
return bool(offlinePlayer.isWhitelisted());
case "online":
return bool(offlinePlayer.isOnline());
//</editor-fold>
}
if (!offlinePlayer.isOnline()) {
return "";
}
final Player player = offlinePlayer.getPlayer();
// To get rid of IDE warnings
if (player == null) {
return "";
}
switch (params) {
//<editor-fold desc="General placeholders">
case "displayname":
//noinspection deprecation
return player.getDisplayName();
case "custom_name":
return Optional.ofNullable(player.getCustomName()).orElseGet(player::getName);
case "list_name":
//noinspection deprecation
return player.getPlayerListName();
case "absorption": {
if (VersionHelper.HAS_ABSORPTION_METHODS) {
return String.valueOf((int) player.getAbsorptionAmount());
} else {
return "-1";
}
}
case "fly_speed":
return String.valueOf(player.getFlySpeed());
case "food_level":
return String.valueOf(player.getFoodLevel());
case "gamemode":
return player.getGameMode().name();
case "health":
return String.valueOf(player.getHealth());
case "health_rounded":
return String.valueOf(Math.round(player.getHealth()));
case "health_scale":
return String.valueOf(player.getHealthScale());
case "health_boost": {
if (player.getHealthScale() > 20) {
return String.valueOf(player.getHealthScale() - 20);
} else {
return "0";
}
}
case "last_damage":
return String.valueOf(player.getLastDamage());
case "max_air":
return String.valueOf(player.getMaximumAir());
case "max_health":
return String.valueOf(PlayerUtil.getMaxHealth(player));
case "max_health_rounded":
return String.valueOf(Math.round(PlayerUtil.getMaxHealth(player)));
case "max_no_damage_ticks":
return String.valueOf(player.getMaximumNoDamageTicks());
case "no_damage_ticks":
return String.valueOf(player.getNoDamageTicks());
case "remaining_air":
return String.valueOf(player.getRemainingAir());
case "saturation":
return String.valueOf(player.getSaturation());
case "sleep_ticks":
return String.valueOf(player.getSleepTicks());
case "ticks_lived":
return String.valueOf(player.getTicksLived());
case "seconds_lived":
return String.valueOf(player.getTicksLived() / 20L);
case "minutes_lived":
return String.valueOf(TimeUnit.SECONDS.toMinutes(player.getTicksLived() / 20L));
case "walk_speed":
return String.valueOf(player.getWalkSpeed());
case "ip":
return Optional.ofNullable(player.getAddress())
.map(InetSocketAddress::getAddress)
.map(InetAddress::getHostAddress)
.orElse("");
case "ping":
case "colored_ping":
return pingFormatter.getPing(player, params.startsWith("colored"));
case "time":
return String.valueOf(player.getPlayerTime());
case "time_offset":
return String.valueOf(player.getPlayerTimeOffset());
//</editor-fold>
//<editor-fold desc="Location / position placeholders">
case "world":
return player.getWorld().getName();
case "world_type": {
final World.Environment environment = player.getWorld().getEnvironment();
if (environment == World.Environment.NETHER) {
return "Nether";
} else if (environment == World.Environment.THE_END) {
return "The End";
} else if (environment == World.Environment.NORMAL) {
return "Overworld";
} else if (environment.name().equals("CUSTOM")) {
return "Custom";
} else {
return environment.name();
}
}
case "world_time":
return String.valueOf(player.getWorld().getTime());
case "world_time_12":
case "world_time_24":
return TimeUtil.formatWorldTime(player.getWorld().getTime(), params.equals("world_time_24"));
case "weather_duration":
return String.valueOf(player.getWorld().getWeatherDuration());
case "thunder_duration":
return String.valueOf(player.getWorld().getThunderDuration());
case "direction":
// NORTH_EAST -> north_east -> value from config (e.g. NE)
return Optional.of(PlayerUtil.getDirection(player))
.map(BlockFace::name)
.map(String::toLowerCase)
.map(directionNames::get)
.map(String::valueOf)
.orElse("");
case "direction_xz":
return PlayerUtil.getXZDirection(player);
case "x":
return String.valueOf(player.getLocation().getBlockX());
case "x_long":
return String.valueOf(player.getLocation().getX());
case "y":
return String.valueOf(player.getLocation().getBlockY());
case "y_long":
return String.valueOf(player.getLocation().getY());
case "z":
return String.valueOf(player.getLocation().getBlockZ());
case "z_long":
return String.valueOf(player.getLocation().getZ());
case "yaw":
return String.valueOf(player.getLocation().getYaw());
case "pitch":
return String.valueOf(player.getLocation().getPitch());
case "block_underneath":
return String.valueOf(
player.getLocation()
.clone()
.subtract(0, 1, 0)
.getBlock()
.getType()
);
case "light_level":
return String.valueOf(player.getLocation().getBlock().getLightLevel());
case "biome":
case "biome_capitalized": {
final String biome = player.getLocation().getBlock().getBiome().toString();
if (!params.endsWith("_capitalized")) {
return biome;
}
final StringJoiner joiner = new StringJoiner(" ");
for (String part : biome.split("_")) {
joiner.add(part.substring(0, 1).toUpperCase() + part.substring(1).toLowerCase());
}
return joiner.toString();
}
case "compass_x":
return PlayerUtil.getCompassLocationInfo(player, "0", Location::getBlockX);
case "compass_y":
return PlayerUtil.getCompassLocationInfo(player, "0", Location::getBlockY);
case "compass_z":
return PlayerUtil.getCompassLocationInfo(player, "0", Location::getBlockZ);
case "compass_world":
return PlayerUtil.getCompassLocationInfo(player, Bukkit.getWorlds().get(0).getName(), location -> location.getWorld().getName());
//</editor-fold>
//<editor-fold desc="Experience placeholders">
case "exp":
return String.valueOf(player.getExp());
case "current_exp":
return String.valueOf(PlayerUtil.getTotalExperience(player));
case "total_exp":
return String.valueOf(player.getTotalExperience());
case "exp_to_level":
return String.valueOf(player.getExpToLevel());
case "level":
return String.valueOf(player.getLevel());
//</editor-fold>
//<editor-fold desc="Inventory placeholders">
case "has_empty_slot":
return bool(player.getInventory().firstEmpty() > -1);
case "empty_slots":
return String.valueOf(PlayerUtil.getEmptySlotsCount(player));
case "item_in_hand":
case "item_in_hand_name":
case "item_in_hand_data":
case "item_in_hand_durability":
return getItemInfo(PlayerUtil.getItemInMainHand(player), params.substring("item_in_hand".length()));
case "item_in_offhand":
case "item_in_offhand_name":
case "item_in_offhand_data":
case "item_in_offhand_durability":
return getItemInfo(player.getInventory().getItemInOffHand(), params.substring("item_in_offhand".length()));
case "armor_helmet":
case "armor_helmet_name":
case "armor_helmet_data":
case "armor_helmet_durability":
return getItemInfo(player.getInventory().getHelmet(), params.substring("armor_helmet".length()));
case "armor_chestplate":
case "armor_chestplate_name":
case "armor_chestplate_data":
case "armor_chestplate_durability":
return getItemInfo(player.getInventory().getChestplate(), params.substring("armor_chestplate".length()));
case "armor_leggings":
case "armor_leggings_name":
case "armor_leggings_data":
case "armor_leggings_durability":
return getItemInfo(player.getInventory().getLeggings(), params.substring("armor_leggings".length()));
case "armor_boots":
case "armor_boots_name":
case "armor_boots_data":
case "armor_boots_durability":
return getItemInfo(player.getInventory().getBoots(), params.substring("armor_boots".length()));
//</editor-fold>
//<editor-fold desc="Various boolean placeholders">
case "allow_flight":
return bool(player.getAllowFlight());
case "can_pickup_items":
return bool(player.getCanPickupItems());
case "has_health_boost":
return bool(player.hasPotionEffect(PotionEffectType.HEALTH_BOOST));
case "is_conversing":
return bool(player.isConversing());
case "is_dead":
return bool(player.isDead());
case "is_flying":
return bool(player.isFlying());
case "is_gliding":
return bool(player.isGliding());
case "is_inside_vehicle":
return bool(player.isInsideVehicle());
case "is_leashed":
return bool(player.isLeashed());
case "is_sleeping":
return bool(player.isSleeping());
case "is_sneaking":
return bool(player.isSneaking());
case "is_sprinting":
return bool(player.isSprinting());
//</editor-fold>
//<editor-fold desc="⚠ Deprecated placeholders">
case "server":
case "servername":
return "now available in the server expansion";
//</editor-fold>
}
// has_permission_<permission.node>
if (params.startsWith("has_permission_")) {
final String permission = params.substring("has_permission_".length());
return bool(player.hasPermission(permission));
}
// has_potioneffect_<effect>
if (params.startsWith("has_potioneffect_")) {
final String effectName = params.substring("has_potioneffect_".length());
final Optional<PotionEffectType> effectType = Optional.ofNullable(PotionEffectType.getByName(effectName));
if (!effectType.isPresent()) {
return "Unknown potion effect " + effectName;
}
return effectType.map(player::hasPotionEffect)
.map(this::bool)
.get();
}
// potion_effect_level_<effect>
if (params.startsWith("potion_effect_level_")) {
final String effectName = params.substring("potion_effect_level_".length());
final Optional<PotionEffectType> effectType = Optional.ofNullable(PotionEffectType.getByName(effectName));
if (!effectType.isPresent()) {
return "Unknown potion effect " + effectName;
}
return effectType.filter(player::hasPotionEffect)
.map(player::getPotionEffect)
.map(PotionEffect::getAmplifier)
.map(String::valueOf)
.orElse("0");
}
// item_in_hand_level_<enchantment name or key>
if (params.startsWith("item_in_hand_level_")) {
return ItemUtil.getEnchantmentLevel(PlayerUtil.getItemInMainHand(player), params.substring("item_in_hand_level_".length()));
}
// item_in_offhand_level_<enchantment name or key>
if (params.startsWith("item_in_offhand_level_")) {
return ItemUtil.getEnchantmentLevel(player.getInventory().getItemInOffHand(), params.substring("item_in_offhand_level_".length()));
}
// locale or locale_<option>
if (params.startsWith("locale")) {
final String localeString = PlayerLocaleHandler.INSTANCE.apply(player);
final Locale locale = Locale.forLanguageTag(localeString.replace('_', '-'));
switch (params) {
case "locale":
return localeString;
case "locale_country":
return Optional.ofNullable(locale).map(Locale::getCountry).orElse("");
case "locale_display_country":
return Optional.ofNullable(locale).map(Locale::getDisplayCountry).orElse("");
case "locale_display_name":
return Optional.ofNullable(locale).map(Locale::getDisplayName).orElse("");
case "locale_short":
return localeString.substring(0, localeString.indexOf("_"));
}
}
// has_unlocked_recipe_<recipe-key>
if (params.startsWith("has_unlocked_recipe_") && VersionHelper.HAS_KEYED_API) {
final String recipeName = params.substring("has_unlocked_recipe_".length());
final NamespacedKey recipeKey = (recipeName.contains(":")) ? NamespacedKey.fromString(recipeName) : NamespacedKey.minecraft(recipeName);
if (recipeKey == null) {
return "Unknown recipe " + recipeName;
}
return bool(player.hasDiscoveredRecipe(recipeKey));
}
return null;
}
}
@@ -0,0 +1,56 @@
package at.helpch.placeholderapi.expansion.player.handler;
import at.helpch.placeholderapi.expansion.player.util.Logging;
import at.helpch.placeholderapi.expansion.player.util.VersionHelper;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
public class PlayerLocaleHandler implements Function<@NotNull Player, @NotNull String> {
public static final PlayerLocaleHandler INSTANCE = new PlayerLocaleHandler();
private Field locale;
private Method getHandle;
private PlayerLocaleHandler() { }
private void cacheReflection(@NotNull final Player player) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
getHandle = player.getClass().getDeclaredMethod("getHandle");
getHandle.setAccessible(true);
locale = getHandle.invoke(player).getClass().getDeclaredField("locale");
}
@Override
public @NotNull String apply(@NotNull final Player player) {
if (VersionHelper.HAS_PLAYER_LOCALE_METHOD) {
//noinspection deprecation
return player.getLocale();
}
if (locale == null) {
try {
cacheReflection(player);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException |
NoSuchFieldException e) {
Logging.error(e, "Could not cache reflection for {0} (player: {1})", getClass().getSimpleName(), player.getName());
}
}
if (locale != null) {
try {
return (String) locale.get(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
Logging.error(e, "Could not get the locale of {0}, fallback to en_US", player.getName());
}
}
return "en_US";
}
}
@@ -0,0 +1,56 @@
package at.helpch.placeholderapi.expansion.player.handler;
import at.helpch.placeholderapi.expansion.player.util.Logging;
import at.helpch.placeholderapi.expansion.player.util.VersionHelper;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
public class PlayerPingHandler implements Function<@NotNull Player, @NotNull Integer> {
public static final PlayerPingHandler INSTANCE = new PlayerPingHandler();
private Field ping;
private Method getHandle;
private PlayerPingHandler() { }
private void cacheReflection(@NotNull final Player player) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
getHandle = player.getClass().getDeclaredMethod("getHandle");
getHandle.setAccessible(true);
ping = getHandle.invoke(player).getClass().getDeclaredField("ping");
ping.setAccessible(true);
}
@Override
public Integer apply(@NotNull final Player player) {
if (VersionHelper.HAS_PLAYER_PING_METHOD) {
return player.getPing();
}
if (ping == null) {
try {
cacheReflection(player);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException |
NoSuchFieldException e) {
Logging.error(e, "Could not cache reflection for {0} (player: {1})", getClass().getSimpleName(), player.getName());
}
}
if (ping != null) {
try {
return ping.getInt(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
Logging.error(e, "Could not get the ping of {0}, fallback to -1", player.getName());
}
}
return -1;
}
}
@@ -0,0 +1,75 @@
package at.helpch.placeholderapi.expansion.player.ping;
import at.helpch.placeholderapi.expansion.player.handler.PlayerPingHandler;
import at.helpch.placeholderapi.expansion.player.util.Logging;
import at.helpch.placeholderapi.expansion.player.util.PlayerUtil;
import com.google.common.primitives.Ints;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public final class PingFormatter {
private final List<PingFormattingRule> pingFormattingRules = new ArrayList<>();
public PingFormatter(@Nullable final ConfigurationSection config) {
if (config == null) {
Logging.warn("Could not find the 'ping.formatting' section in config");
return;
}
load(config);
}
private void load(@NotNull ConfigurationSection config) {
for (final String key : config.getKeys(false)) {
final String formatting = config.getString(key);
if (formatting == null) {
continue;
}
Integer ping = Ints.tryParse(key.replaceAll("\\D", ""));
if (ping == null) {
Logging.warn("(ping formatting) Invalid ping condition \"{0}\"", key);
continue;
}
switch (key.charAt(0)) {
case '>':
this.pingFormattingRules.add(PingFormattingRule.greaterThan(ping, formatting));
break;
case '<':
this.pingFormattingRules.add(PingFormattingRule.lessThan(ping, formatting));
break;
case '=':
default:
this.pingFormattingRules.add(PingFormattingRule.equalTo(ping, formatting));
break;
}
}
}
public @NotNull String getPing(@NotNull final Player player, final boolean colored) {
final int ping = PlayerPingHandler.INSTANCE.apply(player);
if (ping < 0 || !colored) {
return String.valueOf(ping);
}
return pingFormattingRules.stream()
.filter(rule -> rule.test(ping))
.findFirst()
.map(rule -> ChatColor.translateAlternateColorCodes('&', rule.getFormatting() + ping))
.orElseGet(() -> String.valueOf(ping));
}
}
@@ -0,0 +1,38 @@
package at.helpch.placeholderapi.expansion.player.ping;
import org.jetbrains.annotations.NotNull;
import java.util.function.Predicate;
public class PingFormattingRule implements Predicate<Integer> {
private final Predicate<@NotNull Integer> predicate;
private final String formatting;
public static @NotNull PingFormattingRule equalTo(final int pingValue, @NotNull final String formatting) {
return new PingFormattingRule((ping) -> ping == pingValue, formatting);
}
public static @NotNull PingFormattingRule greaterThan(final int pingValue, @NotNull final String formatting) {
return new PingFormattingRule((ping) -> ping > pingValue, formatting);
}
public static @NotNull PingFormattingRule lessThan(final int pingValue, @NotNull final String formatting) {
return new PingFormattingRule((ping) -> ping < pingValue, formatting);
}
private PingFormattingRule(Predicate<Integer> predicate, String formatting) {
this.predicate = predicate;
this.formatting = formatting;
}
@Override
public boolean test(@NotNull final Integer ping) {
return predicate.test(ping);
}
public String getFormatting() {
return formatting;
}
}
@@ -0,0 +1,98 @@
package at.helpch.placeholderapi.expansion.player.util;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
@SuppressWarnings("deprecation")
public final class ItemUtil {
/**
* Whether an item is null or its type is air (ends with _AIR)
*
* @param itemStack item to check
* @return whether the item is null or air
*/
public static boolean isNullOrAir(@Nullable final ItemStack itemStack) {
return itemStack == null || itemStack.getType().name().equals("AIR") || itemStack.getType().name().contains("_AIR");
}
/**
* Get the material name of an item
*
* @param item item
* @return {@link Material#name()} or empty string if the item {@link #isNullOrAir(ItemStack) is null or air}
*/
public static @NotNull String getMaterialName(@Nullable final ItemStack item) {
return isNullOrAir(item) ? "" : item.getType().name();
}
/**
* Get the {@link ItemMeta#getDisplayName() display name} of an item
*
* @param item item
* @return {@link ItemMeta#getDisplayName()} or empty string if the item {@link #isNullOrAir(ItemStack) is null or air}
*/
public static @NotNull String getName(@Nullable final ItemStack item) {
if (isNullOrAir(item)) {
return "";
}
//noinspection DataFlowIssue
return item.hasItemMeta() ? item.getItemMeta().getDisplayName() : "";
}
public static int getDamage(@Nullable final ItemStack item) {
if (isNullOrAir(item)) {
return 0;
}
if (VersionHelper.HAS_DAMAGEABLE_ITEM_META) {
//noinspection DataFlowIssue
return item.hasItemMeta() ? ((Damageable) item.getItemMeta()).getDamage() : 0;
} else {
//noinspection deprecation
return item.getDurability();
}
}
/**
* Get the durability left of an item
*
* @param item item
* @return durability left or 0 if the item {@link #isNullOrAir(ItemStack) is null or air}
*/
public static int getDurability(@Nullable final ItemStack item) {
return isNullOrAir(item) ? 0 : item.getType().getMaxDurability() - getDamage(item);
}
public static @Nullable Enchantment getEnchantmentFromString(@NotNull final String string) {
if (VersionHelper.HAS_KEYED_API) {
final NamespacedKey key = (string.contains(":")) ? NamespacedKey.fromString(string) : NamespacedKey.minecraft(string);
return Optional.ofNullable(key)
.map(Enchantment::getByKey)
.orElseGet(() -> Enchantment.getByName(string));
}
return Enchantment.getByName(string);
}
public static @NotNull String getEnchantmentLevel(@Nullable final ItemStack item, @NotNull final String enchantmentNameOrKey) {
if (isNullOrAir(item)) {
return "0";
}
return Optional.ofNullable(getEnchantmentFromString(enchantmentNameOrKey))
.map(item::getEnchantmentLevel)
.map(String::valueOf)
.orElse("0");
}
}
@@ -0,0 +1,32 @@
package at.helpch.placeholderapi.expansion.player.util;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.text.MessageFormat;
import java.util.logging.Level;
public final class Logging {
private static void log(
@NotNull final Level level, @Nullable final Throwable throwable,
@NotNull final String message, @NotNull final Object... args
) {
PlaceholderAPIPlugin.getInstance()
.getLogger()
.log(level, MessageFormat.format(message, args), throwable);
}
public static void error(
@Nullable final Throwable throwable, @NotNull final String message,
@NotNull final Object... args
) {
log(Level.SEVERE, throwable, message, args);
}
public static void warn(@NotNull final String message, @NotNull final Object... args) {
log(Level.WARNING, null, message, args);
}
}
@@ -0,0 +1,139 @@
package at.helpch.placeholderapi.expansion.player.util;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
public final class PlayerUtil {
private static final BlockFace[] radial = {
BlockFace.NORTH, BlockFace.NORTH_EAST,
BlockFace.EAST, BlockFace.SOUTH_EAST,
BlockFace.SOUTH, BlockFace.SOUTH_WEST,
BlockFace.WEST, BlockFace.NORTH_WEST
};
/**
* Get player's item in hand using the right method depending on the server version
*
* @param player player
* @return item in hand
* @see Player#getItemInHand() method for < 1.9
* @see PlayerInventory#getItemInMainHand() method for >= 1.9
*/
@SuppressWarnings({"DataFlowIssue", "deprecation"})
public static @Nullable ItemStack getItemInMainHand(@NotNull final Player player) {
return VersionHelper.HAS_OFF_HAND ? player.getInventory().getItemInMainHand() : player.getItemInHand();
}
public static @NotNull String getLocationInfo(
@Nullable final Location location, @NotNull final String defaultValue,
@NotNull final Function<@NotNull Location, @NotNull Object> coordinateMapper
) {
return Optional.ofNullable(location)
.map(coordinateMapper)
.map(String::valueOf)
.orElse(defaultValue);
}
public static @NotNull String getBedLocationInfo(
@NotNull final OfflinePlayer player, @NotNull final String defaultValue,
@NotNull final Function<@NotNull Location, @NotNull Object> coordinateMapper
) {
return getLocationInfo(player.getBedSpawnLocation(), defaultValue, coordinateMapper);
}
public static @NotNull String getCompassLocationInfo(
@NotNull final Player player, @NotNull final String defaultValue,
@NotNull final Function<@NotNull Location, @NotNull Object> coordinateMapper
) {
return getLocationInfo(player.getCompassTarget(), defaultValue, coordinateMapper);
}
public static int getEmptySlotsCount(@NotNull final Player player) {
final PlayerInventory inventory = player.getInventory();
final List<ItemStack> items = new ArrayList<>(Arrays.asList(inventory.getContents()));
items.add(inventory.getHelmet());
items.add(inventory.getChestplate());
items.add(inventory.getLeggings());
items.add(inventory.getBoots());
if (VersionHelper.HAS_OFF_HAND) {
items.add(inventory.getItemInOffHand());
}
return (int) items.stream().filter(ItemUtil::isNullOrAir).count();
}
public static @NotNull BlockFace getDirection(@NotNull final Player player) {
return radial[Math.round(player.getLocation().getYaw() / 45f) & 0x7].getOppositeFace();
}
public static String getXZDirection(Player player) {
double rotation = player.getLocation().getYaw();
if (rotation < 0.0D) {
rotation += 360.0D;
}
if (Math.abs(rotation) <= 45 || Math.abs(rotation - 360) <= 45) {
return "+Z";
} else if (Math.abs(rotation - 90) <= 45) {
return "-X";
} else if (Math.abs(rotation - 180) <= 45) {
return "-Z";
} else if (Math.abs(rotation - 270) <= 45) {
return "+X";
} else {
return "";
}
}
public static double getMaxHealth(@NotNull final Player player) {
if (VersionHelper.HAS_ATTRIBUTE_API) {
return Optional.ofNullable(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
.map(AttributeInstance::getValue)
.orElse(20.0);
} else {
//noinspection deprecation
return player.getMaxHealth();
}
}
private static int getExperienceAtLevel(int level) {
if (level <= 15) {
return (level << 1) + 7;
}
if (level <= 30) {
return (level * 5) - 38;
}
return (level * 9) - 158;
}
public static int getTotalExperience(Player player) {
int experience = Math.round(getExperienceAtLevel(player.getLevel()) * player.getExp());
int currentLevel = player.getLevel();
while (currentLevel > 0) {
currentLevel--;
experience += getExperienceAtLevel(currentLevel);
}
if (experience < 0) {
experience = 0;
}
return experience;
}
}
@@ -0,0 +1,19 @@
package at.helpch.placeholderapi.expansion.player.util;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public final class TimeUtil {
private static final LocalTime SIX_O_CLOCK = LocalTime.of(6, 0);
private static final double MINECRAFT_SECONDS_PER_TICK = 3.6d;
private static final DateTimeFormatter TWENTY_FOUR_FORMAT = DateTimeFormatter.ofPattern("HH:mm");
private static final DateTimeFormatter TWELVE_FORMAT = DateTimeFormatter.ofPattern("hh:mm a");
public static String formatWorldTime(final long ticks, final boolean twentyFourHourFormat) {
final LocalTime time = SIX_O_CLOCK.plusSeconds((long) (ticks * MINECRAFT_SECONDS_PER_TICK));
return time.format(twentyFourHourFormat ? TWENTY_FOUR_FORMAT : TWELVE_FORMAT);
}
}
@@ -0,0 +1,92 @@
package at.helpch.placeholderapi.expansion.player.util;
import com.google.common.primitives.Ints;
import org.bukkit.Bukkit;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Damageable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.PlayerInventory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Matt (<a href="https://github.com/lichthund">@LichtHund</a>)
*/
public final class VersionHelper {
private static final int VERSION = getCurrentVersion();
/**
* @see Player#getAttribute(Attribute)
* @since MC 1.9
*/
public static final boolean HAS_ATTRIBUTE_API = VERSION >= 1_9_0;
/**
* @see PlayerInventory#getItemInOffHand()
* @since MC 1.9
*/
public static final boolean HAS_OFF_HAND = VERSION >= 1_9_0;
/**
* @see Player#getLocale()
* @since MC 1.12
*/
public static final boolean HAS_PLAYER_LOCALE_METHOD = VERSION >= 1_12_0;
/**
* @see org.bukkit.inventory.meta.Damageable
* @since MC 1.13
*/
public static final boolean HAS_DAMAGEABLE_ITEM_META = VERSION >= 1_13_0;
/**
* @see org.bukkit.Keyed
* @since MC 1.13
*/
public static final boolean HAS_KEYED_API = VERSION >= 1_13_0;
/**
* @see Damageable#getAbsorptionAmount()
* @since MC 1.15
*/
public static final boolean HAS_ABSORPTION_METHODS = VERSION >= 1_15_0;
/**
* @see Player#getPing()
* @since MC 1.17
*/
public static final boolean HAS_PLAYER_PING_METHOD = VERSION >= 1_17_0;
private VersionHelper() { }
/**
* Gets the current server version
*
* @return A protocol like number representing the version, for example 1.16.5 - 1165
*/
private static int getCurrentVersion() {
// No need to cache since will only run once
final Matcher matcher = Pattern.compile("(?<version>\\d+\\.\\d+)(?<patch>\\.\\d+)?").matcher(Bukkit.getBukkitVersion());
final StringBuilder stringBuilder = new StringBuilder();
if (matcher.find()) {
final String patch = matcher.group("patch");
stringBuilder
.append(matcher.group("version").replace(".", ""))
.append((patch == null) ? "0" : patch.replace(".", ""));
}
final Integer version = Ints.tryParse(stringBuilder.toString());
// Should never fail
if (version == null) {
throw new IllegalArgumentException("Could not retrieve server version!");
}
return version;
}
}
@@ -1,324 +0,0 @@
/*
*
* Player-Expansion
* Copyright (C) 2018 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.player;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import me.clip.placeholderapi.expansion.Configurable;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import java.util.Date;
import static com.extendedclip.papi.expansion.player.PlayerUtil.*;
public class PlayerExpansion extends PlaceholderExpansion implements Configurable {
private final String VERSION = getClass().getPackage().getImplementationVersion();
private String low, medium, high;
@Override
public String getIdentifier() {
return "player";
}
@Override
public String getAuthor() {
return "clip";
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public Map<String, Object> getDefaults() {
Map<String, Object> defaults = new HashMap<>();
defaults.put("ping_color.high", "&a");
defaults.put("ping_color.medium", "&e");
defaults.put("ping_color.low", "&c");
return defaults;
}
public String onRequest(OfflinePlayer player, String identifier) {
high = this.getString("ping_color.high", "&a");
medium = this.getString("ping_color.medium", "&e");
low = this.getString("ping_color.low", "&c");
if (identifier.startsWith("ping_")) {
if (identifier.split("ping_").length > 1) {
identifier = identifier.split("ping_")[1];
Player t = Bukkit.getPlayer(identifier);
if (t != null) {
return getPing(t);
}
}
return "0";
}
if (identifier.startsWith("colored_ping_")) {
if (identifier.split("colored_ping_").length > 1) {
identifier = identifier.split("colored_ping_")[1];
Player t = Bukkit.getPlayer(identifier);
if (t != null) {
int p = Integer.valueOf(getPing(t));
return ChatColor.translateAlternateColorCodes('&', p > 100 ? low : p >= 50 ? medium : high) + getPing(t);
}
}
return "0";
}
if (player == null) {
return "";
}
// offline placeholders
switch (identifier) {
case "name":
return player.getName();
case "uuid":
return player.getUniqueId().toString();
case "has_played_before":
return bool(player.hasPlayedBefore());
case "online":
return bool(player.isOnline());
case "is_whitelisted":
return bool(player.isWhitelisted());
case "is_banned":
return bool(player.isBanned());
case "is_op":
return bool(player.isOp());
case "first_played":
case "first_join":
return String.valueOf(player.getFirstPlayed());
case "first_played_formatted":
case "first_join_date":
return PlaceholderAPIPlugin.getDateFormat().format(new Date(player.getFirstPlayed()));
case "last_played":
case "last_join":
return String.valueOf(player.getLastPlayed());
case "last_played_formatted":
case "last_join_date":
return PlaceholderAPIPlugin.getDateFormat().format(new Date(player.getLastPlayed()));
case "bed_x":
return player.getBedSpawnLocation() != null ? String.valueOf(player.getBedSpawnLocation().getX()) : "";
case "bed_y":
return player.getBedSpawnLocation() != null ? String.valueOf(player.getBedSpawnLocation().getY()) : "";
case "bed_z":
return player.getBedSpawnLocation() != null ? String.valueOf(player.getBedSpawnLocation().getZ()) : "";
case "bed_world":
return player.getBedSpawnLocation() != null ? player.getBedSpawnLocation().getWorld()
.getName() : "";
}
// online placeholders
if (!player.isOnline()) {
return "";
}
Player p = player.getPlayer();
if (identifier.startsWith("has_permission_")) {
if (identifier.split("has_permission_").length > 1) {
String perm = identifier.split("has_permission_")[1];
return bool(p.hasPermission(perm));
}
return bool(false);
}
if (identifier.startsWith("has_potioneffect_")) {
if (identifier.split("has_potioneffect_").length > 1) {
String effect = identifier.split("has_potioneffect_")[1];
PotionEffectType potion = PotionEffectType.getByName(effect);
return bool(p.hasPotionEffect(potion));
}
}
if (identifier.startsWith("item_in_hand_level_")){
if (identifier.split("item_in_hand_level_").length > 1){
String enchantment = identifier.split("item_in_hand_level_")[1];
return String.valueOf(itemInHand(p).getEnchantmentLevel(Enchantment.getByName(enchantment)));
}
return "0";
}
if (identifier.startsWith("item_in_offhand_level_")){
if (identifier.split("item_in_offhand_level_").length > 1) {
String enchantment = identifier.split("item_in_offhand_level_")[1];
return String.valueOf(p.getInventory().getItemInOffHand().getEnchantmentLevel(Enchantment.getByName(enchantment)));
}
return "0";
}
switch (identifier) {
case "has_empty_slot":
return bool(p.getInventory().firstEmpty() > - 1);
case "empty_slots":
return String.valueOf(getEmptySlots(p));
case "server":
case "servername":
return "now available in the server expansion";
case "displayname":
return p.getDisplayName();
case "locale":
return p.getLocale();
case "gamemode":
return p.getGameMode().name();
case "direction":
return getCardinalDirection(p);
case "world":
return p.getWorld().getName();
case "x":
return String.valueOf(p.getLocation().getBlockX());
case "y":
return String.valueOf(p.getLocation().getBlockY());
case "z":
return String.valueOf(p.getLocation().getBlockZ());
case "biome":
return String.valueOf(p.getLocation().getBlock().getBiome());
case "ip":
return p.getAddress().getAddress().getHostAddress();
case "allow_flight":
return bool(p.getAllowFlight());
case "can_pickup_items":
return bool(p.getCanPickupItems());
case "compass_x":
return p.getCompassTarget() != null ? String.valueOf(p.getCompassTarget().getBlockX()) : "";
case "compass_y":
return p.getCompassTarget() != null ? String.valueOf(p.getCompassTarget().getBlockY()) : "";
case "compass_z":
return p.getCompassTarget() != null ? String.valueOf(p.getCompassTarget().getBlockZ()) : "";
case "compass_world":
return p.getCompassTarget() != null ? p.getCompassTarget().getWorld().getName() : "";
case "custom_name":
return p.getCustomName() != null ? p.getCustomName() : p.getName();
case "exp":
return String.valueOf(p.getExp());
case "current_exp":
return String.valueOf(getTotalExperience(p));
case "total_exp":
return String.valueOf(p.getTotalExperience());
case "exp_to_level":
return String.valueOf(p.getExpToLevel());
case "level":
return String.valueOf(p.getLevel());
case "fly_speed":
return String.valueOf(p.getFlySpeed());
case "food_level":
return String.valueOf(p.getFoodLevel());
case "health":
return String.valueOf(p.getHealth());
case "health_rounded":
return String.valueOf(Math.round(p.getHealth()));
case "health_scale":
return String.valueOf(p.getHealthScale());
case "item_in_hand":
return String.valueOf(itemInHand(p).getType());
case "item_in_hand_name":
return itemInHand(p).getType() != Material.AIR && itemInHand(p).getItemMeta().hasDisplayName() ? itemInHand(p).getItemMeta().getDisplayName() : "";
case "item_in_hand_data":
return itemInHand(p).getType() != Material.AIR ? String.valueOf(itemInHand(p).getDurability()) : "0";
case "item_in_offhand":
return String.valueOf(p.getInventory().getItemInOffHand().getType());
case "item_in_offhand_name":
return p.getInventory().getItemInOffHand().getType() != Material.AIR && p.getInventory().getItemInOffHand().getItemMeta().hasDisplayName() ? p.getInventory().getItemInOffHand().getItemMeta().getDisplayName() : "";
case "item_in_offhand_data":
return p.getInventory().getItemInOffHand().getType() != Material.AIR ? String.valueOf(p.getInventory().getItemInOffHand().getDurability()) : "0";
case "last_damage":
return String.valueOf(p.getLastDamage());
case "max_health":
return String.valueOf(p.getMaxHealth());
case "max_health_rounded":
return String.valueOf(Math.round(p.getMaxHealth()));
case "max_air":
return String.valueOf(p.getMaximumAir());
case "max_no_damage_ticks":
return String.valueOf(p.getMaximumNoDamageTicks());
case "no_damage_ticks":
return String.valueOf(p.getNoDamageTicks());
case "armor_helmet_name":
return Optional.ofNullable(p.getInventory().getHelmet()).map(a -> a.getItemMeta().getDisplayName()).orElse("");
case "armor_helmet_data":
return p.getInventory().getHelmet() != null ? String.valueOf(p.getInventory().getHelmet().getDurability()) : "0";
case "armor_chestplate_name":
return Optional.ofNullable(p.getInventory().getChestplate()).map(a -> a.getItemMeta().getDisplayName()).orElse("");
case "armor_chestplate_data":
return p.getInventory().getChestplate() != null ? String.valueOf(p.getInventory().getChestplate().getDurability()) : "0";
case "armor_leggings_name":
return Optional.ofNullable(p.getInventory().getLeggings()).map(a -> a.getItemMeta().getDisplayName()).orElse("");
case "armor_leggings_data":
return p.getInventory().getLeggings() != null ? String.valueOf(p.getInventory().getLeggings().getDurability()) : "0";
case "armor_boots_name":
return Optional.ofNullable(p.getInventory().getBoots()).map(a -> a.getItemMeta().getDisplayName()).orElse("");
case "armor_boots_data":
return p.getInventory().getBoots() != null ? String.valueOf(p.getInventory().getBoots().getDurability()) : "0";
case "ping":
return getPing(p);
case "colored_ping":
int ping = Integer.valueOf(getPing(p));
return ChatColor.translateAlternateColorCodes('&', ping > 100 ? low : ping >= 50 ? medium : high) + getPing(p);
case "time":
return String.valueOf(p.getPlayerTime());
case "time_offset":
return String.valueOf(p.getPlayerTimeOffset());
case "remaining_air":
return String.valueOf(p.getRemainingAir());
case "saturation":
return String.valueOf(p.getSaturation());
case "sleep_ticks":
return String.valueOf(p.getSleepTicks());
case "thunder_duration":
return String.valueOf(p.getWorld().getThunderDuration());
case "ticks_lived":
return String.valueOf(p.getTicksLived());
case "seconds_lived":
return String.valueOf(p.getTicksLived() * 20);
case "minutes_lived":
return String.valueOf((p.getTicksLived() * 20) / 60);
case "walk_speed":
return String.valueOf(p.getWalkSpeed());
case "weather_duration":
return String.valueOf(p.getWorld().getWeatherDuration());
case "world_time":
return String.valueOf(p.getWorld().getTime());
case "world_time_12":
return format12(p.getWorld().getTime());
case "world_time_24":
return format24(p.getWorld().getTime());
}
// return null for unknown placeholders
return null;
}
public String bool(boolean b) {
return b ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
}
}
@@ -1,162 +0,0 @@
package com.extendedclip.papi.expansion.player;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
/*
*
* Player-Expansion
* Copyright (C) 2018 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
public class PlayerUtil {
public static final int ticksAtMidnight = 18000;
public static final int ticksPerDay = 24000;
public static final int ticksPerHour = 1000;
public static final double ticksPerMinute = 1000d / 60d;
public static final double ticksPerSecond = 1000d / 60d / 60d;
private static final SimpleDateFormat twentyFour = new SimpleDateFormat("HH:mm", Locale.ENGLISH);
private static final SimpleDateFormat twelve = new SimpleDateFormat("h:mm aa", Locale.ENGLISH);
public static String getPing(Player p) {
try {
Method getHandleMethod = p.getClass().getDeclaredMethod("getHandle", new Class[0]);
Object nmsplayer = getHandleMethod.invoke(p, new Object[0]);
Field pingField = nmsplayer.getClass().getDeclaredField("ping");
return String.valueOf(pingField.getInt(nmsplayer));
} catch (Exception e) {
e.printStackTrace();
}
return "0";
}
public static String format12(long ticks) {
try {
return twelve.format(twentyFour.parse(ticksToTime(ticks)));
} catch (ParseException e) {
return ticksToTime(ticks);
}
}
public static String format24(long ticks) {
return ticksToTime(ticks);
}
private static String ticksToTime(long ticks) {
ticks = ticks - ticksAtMidnight + ticksPerDay;
long hours = ticks / ticksPerHour;
ticks -= hours * ticksPerHour;
long mins = (long) Math.floor(ticks / ticksPerMinute);
if (hours >= 24) {
hours = hours - 24;
}
return (hours < 10 ? "0" + hours : hours) + ":" + (mins < 10 ? "0" + mins : mins);
}
public static String getCardinalDirection(Player player) {
double rotation = player.getLocation().getYaw() - 180.0F;
if (rotation < 0.0D) {
rotation += 360.0D;
}
if ((0.0D <= rotation) && (rotation < 22.5D)) {
return "N";
}
if ((22.5D <= rotation) && (rotation < 67.5D)) {
return "NE";
}
if ((67.5D <= rotation) && (rotation < 112.5D)) {
return "E";
}
if ((112.5D <= rotation) && (rotation < 157.5D)) {
return "SE";
}
if ((157.5D <= rotation) && (rotation < 202.5D)) {
return "S";
}
if ((202.5D <= rotation) && (rotation < 247.5D) || (rotation <= -119.33) && (rotation > -179)) {
return "SW";
}
if ((247.5D <= rotation) && (rotation < 292.5D) || (rotation <= -59.66) && (rotation > -119.33)) {
return "W";
}
if ((292.5D <= rotation) && (rotation < 337.5D) || (rotation <= -0.0) && (rotation > -59.66)) {
return "NW";
}
if ((337.5D <= rotation) && (rotation < 360.0D)) {
return "N";
}
return "";
}
public static ItemStack itemInHand(Player p) {
try {
return p.getInventory().getItemInMainHand();
} catch (NoSuchMethodError e) {
return p.getInventory().getItemInHand();
}
}
public static int getEmptySlots(Player p) {
int slots = 0;
PlayerInventory inv = p.getInventory();
for (ItemStack is : inv.getContents()) {
if (is == null) slots++;
}
if (!Bukkit.getBukkitVersion().contains("1.7") && !Bukkit.getBukkitVersion().contains("1.8")) {
if (inv.getItemInOffHand() == null || inv.getItemInOffHand().getType() == Material.AIR) slots--;
if (inv.getHelmet() == null) slots--;
if (inv.getChestplate() == null) slots--;
if (inv.getLeggings() == null) slots--;
if (inv.getBoots() == null) slots--;
}
return slots;
}
private static int getExperienceAtLevel(int level) {
if (level <= 15) {
return (level << 1) + 7;
}
if (level <= 30) {
return (level * 5) - 38;
}
return (level * 9) - 158;
}
public static int getTotalExperience(Player player) {
int experience = Math.round(getExperienceAtLevel(player.getLevel()) * player.getExp());
int currentLevel = player.getLevel();
while (currentLevel > 0) {
currentLevel--;
experience += getExperienceAtLevel(currentLevel);
}
if (experience < 0) {
experience = 0;
}
return experience;
}
}