convert to patches
This commit is contained in:
@@ -29,15 +29,14 @@ jobs:
|
|||||||
- run: git config --global user.email "circle@circleci.com"
|
- run: git config --global user.email "circle@circleci.com"
|
||||||
- run: git config --global user.name "CircleCI"
|
- run: git config --global user.name "CircleCI"
|
||||||
- run: chmod -Rv +x scripts/
|
- run: chmod -Rv +x scripts/
|
||||||
- run: ./scripts/build.sh
|
- run: ./akarin build
|
||||||
- run: ./scripts/inst.sh --setup --remote
|
|
||||||
# Save dependency cache
|
# Save dependency cache
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: v1-dep-{{ .Branch }}-{{ epoch }}
|
key: v1-dep-{{ .Branch }}-{{ epoch }}
|
||||||
paths:
|
paths:
|
||||||
- ~/.m2
|
- ~/.m2
|
||||||
# Test
|
# Test
|
||||||
- run: yes|cp -rf ./akarin-*.jar $CIRCLE_ARTIFACTS
|
- run: cp akarin-paperclip.jar $CIRCLE_ARTIFACTS
|
||||||
# Teardown
|
# Teardown
|
||||||
# Save test results
|
# Save test results
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
|
|||||||
74
.gitignore
vendored
74
.gitignore
vendored
@@ -1,57 +1,43 @@
|
|||||||
# Eclipse stuff
|
# Akarin
|
||||||
.classpath
|
Akarin-Server
|
||||||
.project
|
Akarin-API
|
||||||
.settings/
|
mc-dev
|
||||||
.factorypath
|
.idea
|
||||||
.externalToolBuilders/
|
testserver
|
||||||
|
run
|
||||||
|
/akarin-paperclip.jar
|
||||||
|
|
||||||
# netbeans
|
# Compiled class file
|
||||||
nbproject/
|
*.class
|
||||||
nbactions.xml
|
|
||||||
|
|
||||||
# we use maven!
|
# Log file
|
||||||
build.xml
|
*.log
|
||||||
|
|
||||||
# maven
|
# BlueJ files
|
||||||
target/
|
*.ctxt
|
||||||
dependency-reduced-pom.xml
|
|
||||||
|
|
||||||
# vim
|
# Mobile Tools for Java (J2ME)
|
||||||
.*.sw[a-p]
|
.mtj.tmp/
|
||||||
|
|
||||||
# various other potential build files
|
# IntelliJ
|
||||||
build/
|
|
||||||
bin/
|
|
||||||
dist/
|
|
||||||
manifest.mf
|
|
||||||
|
|
||||||
work/1.*
|
|
||||||
work/Minecraft
|
|
||||||
work/BuildData
|
|
||||||
work/Bukkit
|
|
||||||
work/CraftBukkit
|
|
||||||
work/Paperclip
|
|
||||||
work/Spigot
|
|
||||||
work/Spigot-Server
|
|
||||||
work/Spigot-API
|
|
||||||
work/*.jar
|
|
||||||
work/test-server
|
|
||||||
|
|
||||||
# Mac filesystem dust
|
|
||||||
.DS_Store/
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# intellij
|
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
.idea/
|
.idea/
|
||||||
out/
|
out/
|
||||||
|
|
||||||
# Linux temp files
|
# Maven
|
||||||
*~
|
target/
|
||||||
|
|
||||||
# other stuff
|
# Package Files #
|
||||||
run/
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
akarin-*.jar
|
|
||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +1,4 @@
|
|||||||
[submodule "work/Paper"]
|
[submodule "Paper"]
|
||||||
path = work/Paper
|
path = Paper
|
||||||
url = https://github.com/PaperMC/Paper.git
|
url = https://github.com/PaperMC/Paper.git
|
||||||
branch = master
|
branch = master
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
|||||||
#Sat Mar 28 16:11:26 MST 2020
|
|
||||||
gradle.version=6.2.2
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
25
.travis.yml
25
.travis.yml
@@ -1,25 +0,0 @@
|
|||||||
language: java
|
|
||||||
dist: trusty
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8
|
|
||||||
install: true
|
|
||||||
script:
|
|
||||||
- git config --global user.email "circle@circleci.com"
|
|
||||||
- git config --global user.name "CircleCI"
|
|
||||||
- chmod -Rv +x scripts/
|
|
||||||
- ./scripts/build.sh
|
|
||||||
- ./scripts/inst.sh --setup --remote
|
|
||||||
after_success:
|
|
||||||
- rm -rf push
|
|
||||||
- mkdir push
|
|
||||||
- cp ./target/*.jar ./push/
|
|
||||||
deploy:
|
|
||||||
skip_cleanup: true
|
|
||||||
provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: $Github_token
|
|
||||||
file:
|
|
||||||
- ./push/*
|
|
||||||
file_glob: true
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
133
akarin
Executable file
133
akarin
Executable file
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# exit immediately if a command exits with a non-zero status
|
||||||
|
set -e
|
||||||
|
# get base dir regardless of execution location
|
||||||
|
SOURCE="${BASH_SOURCE[0]}"
|
||||||
|
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||||
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
SOURCE="$(readlink "$SOURCE")"
|
||||||
|
[[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
|
done
|
||||||
|
SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}")
|
||||||
|
basedir=$(dirname "$SOURCE")
|
||||||
|
. "$basedir"/scripts/init.sh
|
||||||
|
|
||||||
|
paperstash() {
|
||||||
|
STASHED=$(git stash)
|
||||||
|
}
|
||||||
|
|
||||||
|
paperunstash() {
|
||||||
|
if [[ "$STASHED" != "No local changes to save" ]] ; then
|
||||||
|
git stash pop
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
"rb" | "rbp" | "rebuild")
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
cd "$basedir"
|
||||||
|
scripts/rebuildpatches.sh "$basedir"
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"p" | "patch" | "apply")
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
cd "$basedir"
|
||||||
|
if [ "$2" != "fast" ]; then
|
||||||
|
scripts/upstream.sh
|
||||||
|
fi
|
||||||
|
scripts/apply.sh "$basedir"
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"b" | "bu" | "build")
|
||||||
|
(
|
||||||
|
basedir
|
||||||
|
mvn -N install
|
||||||
|
cd ${FORK_NAME}-API
|
||||||
|
mvn -e clean install && cd ../${FORK_NAME}-Server && mvn -e clean install
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"jar" | "paperclip")
|
||||||
|
(
|
||||||
|
basedir
|
||||||
|
cd "$basedir"
|
||||||
|
if [ "$2" != "fast" ]; then
|
||||||
|
scripts/upstream.sh
|
||||||
|
fi
|
||||||
|
./scripts/apply.sh "$basedir"
|
||||||
|
cd "$basedir"
|
||||||
|
mvn -N install
|
||||||
|
cd ${FORK_NAME}-API
|
||||||
|
mvn -e clean install && cd ../${FORK_NAME}-Server && mvn -e clean install
|
||||||
|
cd "$basedir"
|
||||||
|
./scripts/paperclip.sh
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"d" | "de" | "deploy")
|
||||||
|
(
|
||||||
|
basedir
|
||||||
|
mvn -N install
|
||||||
|
cd ${FORK_NAME}-API
|
||||||
|
mvn clean deploy && cd ../${FORK_NAME}-Server && mvn clean install
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"up" | "upstream")
|
||||||
|
(
|
||||||
|
cd "$basedir"
|
||||||
|
scripts/upstream.sh "$2"
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
"r" | "root")
|
||||||
|
cd "$basedir"
|
||||||
|
;;
|
||||||
|
"a" | "api")
|
||||||
|
cd "$basedir/Akarin-API"
|
||||||
|
;;
|
||||||
|
"s" | "server")
|
||||||
|
cd "$basedir/Akarin-Server"
|
||||||
|
;;
|
||||||
|
"setup")
|
||||||
|
if [[ -f ~/.bashrc ]] ; then
|
||||||
|
NAME="ec"
|
||||||
|
if [[ ! -z "${2+x}" ]] ; then
|
||||||
|
NAME="$2"
|
||||||
|
fi
|
||||||
|
(grep "alias $NAME=" ~/.bashrc > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" ~/.bashrc) || (echo "alias $NAME='. $SOURCE'" >> ~/.bashrc)
|
||||||
|
alias "$NAME=. $SOURCE"
|
||||||
|
echo "You can now just type '$NAME' at any time to access the paper tool."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Akarin build tool command. This provides a variety of commands to build and manage the PaperMC build"
|
||||||
|
echo "environment. For all of the functionality of this command to be available, you must first run the"
|
||||||
|
echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup."
|
||||||
|
echo ""
|
||||||
|
echo " Normal commands:"
|
||||||
|
echo " * rb, rebuild | Rebuild patches, can be called from anywhere."
|
||||||
|
echo " * p, patch | Apply all patches to top of Paper without building it. Can be run from anywhere."
|
||||||
|
echo " * up, upstream | Build Paper upstream, pass arg up to update paper. Can be run from anywhere."
|
||||||
|
echo " * b, build | Build API and Server but no deploy. Can be ran anywhere."
|
||||||
|
echo " * d, deploy | Build and Deploy API jar and build Server. Can be ran anywhere."
|
||||||
|
echo ""
|
||||||
|
echo " These commands require the setup command before use:"
|
||||||
|
echo " * r, root | Change directory to the root of the project."
|
||||||
|
echo " * a. api | Move to the Paper-API directory."
|
||||||
|
echo " * s, server | Move to the Paper-Server directory."
|
||||||
|
echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\""
|
||||||
|
echo " | respectively to edit the correct project. Use the argument \"continue\" after"
|
||||||
|
echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere."
|
||||||
|
echo ""
|
||||||
|
echo " * setup | Add an alias to .bashrc to allow full functionality of this script. Run as:"
|
||||||
|
echo " | . ./akarin setup"
|
||||||
|
echo " | After you run this command you'll be able to just run 'akarin' from anywhere."
|
||||||
|
echo " | The default name for the resulting alias is 'akarin', you can give an argument to override"
|
||||||
|
echo " | this default, such as:"
|
||||||
|
echo " | . ./akarin setup example"
|
||||||
|
echo " | Which will allow you to run 'example' instead."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
unset -f paperstash
|
||||||
|
unset -f paperunstash
|
||||||
245
api/pom.xml
245
api/pom.xml
@@ -1,245 +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>
|
|
||||||
|
|
||||||
<artifactId>akarin-api</artifactId>
|
|
||||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.destroystokyo.paper</groupId>
|
|
||||||
<artifactId>paper-parent</artifactId>
|
|
||||||
<version>dev-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<name>Akarin-API</name>
|
|
||||||
<url>https://github.com/Akarin-project/Akarin</url>
|
|
||||||
<description>An enhanced plugin API for Minecraft servers.</description>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<!-- <skipTests>true</skipTests> Paper - This [was] not going to end well -->
|
|
||||||
<!-- Paper - #Logic -->
|
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<!--
|
|
||||||
If you are a plugin developer, please use https://hub.spigotmc.org/nexus/content/repositories/snapshots/
|
|
||||||
as your repository URL. This will ensure only Bukkit / Spigot-API are pulled from our Maven repository.
|
|
||||||
|
|
||||||
Please see https://www.spigotmc.org/go/maven for more information.
|
|
||||||
-->
|
|
||||||
<repository>
|
|
||||||
<id>spigotmc-public</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>sonatype</id>
|
|
||||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>spigotmc-public</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>it.unimi.dsi</groupId>
|
|
||||||
<artifactId>fastutil</artifactId>
|
|
||||||
<version>8.2.2</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-lang</groupId>
|
|
||||||
<artifactId>commons-lang</artifactId>
|
|
||||||
<version>2.6</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.json-simple</groupId>
|
|
||||||
<artifactId>json-simple</artifactId>
|
|
||||||
<version>1.1.1</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- bundled with Minecraft, shouldn't ever change -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
|
||||||
<artifactId>jsr305</artifactId>
|
|
||||||
<version>1.3.9</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- bundled with Minecraft, should be kept in sync -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>21.0</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- bundled with Minecraft, should be kept in sync -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>2.8.0</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-chat</artifactId>
|
|
||||||
<version>1.13-SNAPSHOT</version>
|
|
||||||
<type>jar</type>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.yaml</groupId>
|
|
||||||
<artifactId>snakeyaml</artifactId>
|
|
||||||
<version>1.23</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- annotations -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains</groupId>
|
|
||||||
<artifactId>annotations-java5</artifactId>
|
|
||||||
<version>17.0.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Paper - Add SLF4J -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
<version>1.7.25</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- testing -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.12</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest-library</artifactId>
|
|
||||||
<version>1.3</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ow2.asm</groupId>
|
|
||||||
<artifactId>asm-tree</artifactId>
|
|
||||||
<version>7.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- ASM -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ow2.asm</groupId>
|
|
||||||
<artifactId>asm</artifactId>
|
|
||||||
<version>7.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ow2.asm</groupId>
|
|
||||||
<artifactId>asm-commons</artifactId>
|
|
||||||
<version>7.1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Akarin -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.koloboke</groupId>
|
|
||||||
<artifactId>koloboke-api-jdk8</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.koloboke</groupId>
|
|
||||||
<artifactId>koloboke-impl-jdk8</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<defaultGoal>clean install</defaultGoal>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.8.0</version>
|
|
||||||
<dependencies>
|
|
||||||
<!-- we need our custom version as it fixes some bugs on case sensitive file systems -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
|
||||||
<artifactId>plexus-compiler-eclipse</artifactId>
|
|
||||||
<version>2.8.5-spigotmc</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>2.4</version>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestEntries>
|
|
||||||
<Automatic-Module-Name>org.bukkit</Automatic-Module-Name>
|
|
||||||
</manifestEntries>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.1.1</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
|
|
||||||
<!-- when downloading via Maven we can pull depends individually -->
|
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>development</id>
|
|
||||||
<properties>
|
|
||||||
<skipTests>false</skipTests>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
|
||||||
<version>1.17</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>process-classes</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>check</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<signature>
|
|
||||||
<groupId>org.codehaus.mojo.signature</groupId>
|
|
||||||
<artifactId>java17</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</signature>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</project>
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import static co.aikar.timings.TimingsManager.*;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class FullServerTickHandler extends TimingHandler {
|
|
||||||
private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null);
|
|
||||||
final TimingData minuteData;
|
|
||||||
double avgFreeMemory = -1D;
|
|
||||||
double avgUsedMemory = -1D;
|
|
||||||
FullServerTickHandler() {
|
|
||||||
super(IDENTITY);
|
|
||||||
minuteData = new TimingData(id);
|
|
||||||
|
|
||||||
TIMING_MAP.put(IDENTITY, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Timing startTiming() {
|
|
||||||
if (TimingsManager.needsFullReset) {
|
|
||||||
TimingsManager.resetTimings();
|
|
||||||
} else if (TimingsManager.needsRecheckEnabled) {
|
|
||||||
TimingsManager.recheckEnabled();
|
|
||||||
}
|
|
||||||
return super.startTiming();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTiming() {
|
|
||||||
super.stopTiming();
|
|
||||||
if (!isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (TimingHistory.timedTicks % 20 == 0) {
|
|
||||||
final Runtime runtime = Runtime.getRuntime();
|
|
||||||
double usedMemory = runtime.totalMemory() - runtime.freeMemory();
|
|
||||||
double freeMemory = runtime.maxMemory() - usedMemory;
|
|
||||||
if (this.avgFreeMemory == -1) {
|
|
||||||
this.avgFreeMemory = freeMemory;
|
|
||||||
} else {
|
|
||||||
this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.avgUsedMemory == -1) {
|
|
||||||
this.avgUsedMemory = usedMemory;
|
|
||||||
} else {
|
|
||||||
this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long start = System.nanoTime();
|
|
||||||
TimingsManager.tick();
|
|
||||||
long diff = System.nanoTime() - start;
|
|
||||||
TIMINGS_TICK.addDiff(diff, null);
|
|
||||||
// addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick.
|
|
||||||
record.setCurTickCount(record.getCurTickCount()-1);
|
|
||||||
|
|
||||||
minuteData.setCurTickTotal(record.getCurTickTotal());
|
|
||||||
minuteData.setCurTickCount(1);
|
|
||||||
|
|
||||||
boolean violated = isViolated();
|
|
||||||
minuteData.processTick(violated);
|
|
||||||
TIMINGS_TICK.processTick(violated);
|
|
||||||
processTick(violated);
|
|
||||||
|
|
||||||
|
|
||||||
if (TimingHistory.timedTicks % 1200 == 0) {
|
|
||||||
MINUTE_REPORTS.add(new TimingHistory.MinuteReport());
|
|
||||||
TimingHistory.resetTicks(false);
|
|
||||||
minuteData.reset();
|
|
||||||
}
|
|
||||||
if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) {
|
|
||||||
TimingsManager.HISTORY.add(new TimingHistory());
|
|
||||||
TimingsManager.resetTimings();
|
|
||||||
}
|
|
||||||
TimingsExport.reportTimings();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isViolated() {
|
|
||||||
return record.getCurTickTotal() > 50000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public final class NullTimingHandler implements Timing {
|
|
||||||
public static final Timing NULL = new NullTimingHandler();
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Timing startTiming() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTiming() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Timing startTimingIfSync() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTimingIfSync() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public TimingHandler getTimingHandler() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.EventException;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.plugin.EventExecutor;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class TimedEventExecutor implements EventExecutor {
|
|
||||||
|
|
||||||
private final EventExecutor executor;
|
|
||||||
private final Timing timings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps an event executor and associates a timing handler to it.
|
|
||||||
*
|
|
||||||
* @param executor Executor to wrap
|
|
||||||
* @param plugin Owning plugin
|
|
||||||
* @param method EventHandler method
|
|
||||||
* @param eventClass Owning class
|
|
||||||
*/
|
|
||||||
public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class<? extends Event> eventClass) {
|
|
||||||
this.executor = executor;
|
|
||||||
String id;
|
|
||||||
|
|
||||||
if (method == null) {
|
|
||||||
if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you
|
|
||||||
method = executor.getClass().getEnclosingMethod();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method != null) {
|
|
||||||
id = method.getDeclaringClass().getName();
|
|
||||||
} else {
|
|
||||||
id = executor.getClass().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final String eventName = eventClass.getSimpleName();
|
|
||||||
boolean verbose = "BlockPhysicsEvent".equals(eventName);
|
|
||||||
this.timings = Timings.ofSafe(plugin.getName(), (verbose ? "## " : "") +
|
|
||||||
"Event: " + id + " (" + eventName + ")", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
|
||||||
if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) {
|
|
||||||
executor.execute(listener, event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try (Timing ignored = timings.startTiming()){
|
|
||||||
executor.execute(listener, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an ability to time sections of code within the Minecraft Server
|
|
||||||
*/
|
|
||||||
public interface Timing extends AutoCloseable {
|
|
||||||
/**
|
|
||||||
* Starts timing the execution until {@link #stopTiming()} is called.
|
|
||||||
*
|
|
||||||
* @return Timing
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Timing startTiming();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Stops timing and records the data. Propagates the data up to group handlers.</p>
|
|
||||||
*
|
|
||||||
* Will automatically be called when this Timing is used with try-with-resources
|
|
||||||
*/
|
|
||||||
void stopTiming();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts timing the execution until {@link #stopTiming()} is called.
|
|
||||||
*
|
|
||||||
* But only if we are on the primary thread.
|
|
||||||
*
|
|
||||||
* @return Timing
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Timing startTimingIfSync();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Stops timing and records the data. Propagates the data up to group handlers.</p>
|
|
||||||
*
|
|
||||||
* <p>Will automatically be called when this Timing is used with try-with-resources</p>
|
|
||||||
*
|
|
||||||
* But only if we are on the primary thread.
|
|
||||||
*/
|
|
||||||
void stopTimingIfSync();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Doesn't do anything - Removed
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
void abort();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally to get the actual backing Handler in the case of delegated Handlers
|
|
||||||
*
|
|
||||||
* @return TimingHandler
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
TimingHandler getTimingHandler();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void close();
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static co.aikar.util.JSONUtil.toArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Lightweight object for tracking timing data</p>
|
|
||||||
*
|
|
||||||
* This is broken out to reduce memory usage
|
|
||||||
*/
|
|
||||||
class TimingData {
|
|
||||||
private final int id;
|
|
||||||
private int count = 0;
|
|
||||||
private int lagCount = 0;
|
|
||||||
private long totalTime = 0;
|
|
||||||
private long lagTotalTime = 0;
|
|
||||||
private int curTickCount = 0;
|
|
||||||
private long curTickTotal = 0;
|
|
||||||
|
|
||||||
TimingData(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimingData(TimingData data) {
|
|
||||||
this.id = data.id;
|
|
||||||
this.totalTime = data.totalTime;
|
|
||||||
this.lagTotalTime = data.lagTotalTime;
|
|
||||||
this.count = data.count;
|
|
||||||
this.lagCount = data.lagCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add(long diff) {
|
|
||||||
++curTickCount;
|
|
||||||
curTickTotal += diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void processTick(boolean violated) {
|
|
||||||
totalTime += curTickTotal;
|
|
||||||
count += curTickCount;
|
|
||||||
if (violated) {
|
|
||||||
lagTotalTime += curTickTotal;
|
|
||||||
lagCount += curTickCount;
|
|
||||||
}
|
|
||||||
curTickTotal = 0;
|
|
||||||
curTickCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
count = 0;
|
|
||||||
lagCount = 0;
|
|
||||||
curTickTotal = 0;
|
|
||||||
curTickCount = 0;
|
|
||||||
totalTime = 0;
|
|
||||||
lagTotalTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TimingData clone() {
|
|
||||||
return new TimingData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
List<Object> export() {
|
|
||||||
List<Object> list = toArray(
|
|
||||||
id,
|
|
||||||
count,
|
|
||||||
totalTime);
|
|
||||||
if (lagCount > 0) {
|
|
||||||
list.add(lagCount);
|
|
||||||
list.add(lagTotalTime);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasData() {
|
|
||||||
return count > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getTotalTime() {
|
|
||||||
return totalTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getCurTickCount() {
|
|
||||||
return curTickCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCurTickCount(int curTickCount) {
|
|
||||||
this.curTickCount = curTickCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getCurTickTotal() {
|
|
||||||
return curTickTotal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCurTickTotal(long curTickTotal) {
|
|
||||||
this.curTickTotal = curTickTotal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,227 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import co.aikar.util.LoadingIntMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
class TimingHandler implements Timing {
|
|
||||||
|
|
||||||
private static AtomicInteger idPool = new AtomicInteger(1);
|
|
||||||
private static Deque<TimingHandler> TIMING_STACK = new ArrayDeque<>();
|
|
||||||
final int id = idPool.getAndIncrement();
|
|
||||||
|
|
||||||
final TimingIdentifier identifier;
|
|
||||||
private final boolean verbose;
|
|
||||||
|
|
||||||
private final Int2ObjectOpenHashMap<TimingData> children = new LoadingIntMap<>(TimingData::new);
|
|
||||||
|
|
||||||
final TimingData record;
|
|
||||||
private TimingHandler startParent;
|
|
||||||
private final TimingHandler groupHandler;
|
|
||||||
|
|
||||||
private long start = 0;
|
|
||||||
private int timingDepth = 0;
|
|
||||||
private boolean added;
|
|
||||||
private boolean timed;
|
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
TimingHandler(@NotNull TimingIdentifier id) {
|
|
||||||
this.identifier = id;
|
|
||||||
this.verbose = id.name.startsWith("##");
|
|
||||||
this.record = new TimingData(this.id);
|
|
||||||
this.groupHandler = id.groupHandler;
|
|
||||||
|
|
||||||
TimingIdentifier.getGroup(id.group).handlers.add(this);
|
|
||||||
checkEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
final void checkEnabled() {
|
|
||||||
enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void processTick(boolean violated) {
|
|
||||||
if (timingDepth != 0 || record.getCurTickCount() == 0) {
|
|
||||||
timingDepth = 0;
|
|
||||||
start = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
record.processTick(violated);
|
|
||||||
for (TimingData handler : children.values()) {
|
|
||||||
handler.processTick(violated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Timing startTimingIfSync() {
|
|
||||||
startTiming();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTimingIfSync() {
|
|
||||||
stopTiming();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Timing startTiming() {
|
|
||||||
if (!enabled || !Bukkit.isPrimaryThread()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if (++timingDepth == 1) {
|
|
||||||
startParent = TIMING_STACK.peekLast();
|
|
||||||
start = System.nanoTime();
|
|
||||||
}
|
|
||||||
TIMING_STACK.addLast(this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopTiming() {
|
|
||||||
if (!enabled || timingDepth <= 0 || start == 0 || !Bukkit.isPrimaryThread()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
popTimingStack();
|
|
||||||
if (--timingDepth == 0) {
|
|
||||||
addDiff(System.nanoTime() - start, startParent);
|
|
||||||
startParent = null;
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void popTimingStack() {
|
|
||||||
TimingHandler last;
|
|
||||||
while ((last = TIMING_STACK.removeLast()) != this) {
|
|
||||||
last.timingDepth = 0;
|
|
||||||
String reportTo;
|
|
||||||
if ("Minecraft".equalsIgnoreCase(last.identifier.group)) {
|
|
||||||
reportTo = "Paper! This is a potential bug in Paper";
|
|
||||||
} else {
|
|
||||||
reportTo = "the plugin " + last.identifier.group + "(Look for errors above this in the logs)";
|
|
||||||
}
|
|
||||||
Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to " + reportTo + " (" + last.identifier + " did not stopTiming)", new Throwable());
|
|
||||||
boolean found = TIMING_STACK.contains(this);
|
|
||||||
if (!found) {
|
|
||||||
// We aren't even in the stack... Don't pop everything
|
|
||||||
TIMING_STACK.addLast(last);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void abort() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDiff(long diff, @Nullable TimingHandler parent) {
|
|
||||||
if (parent != null) {
|
|
||||||
parent.children.get(id).add(diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
record.add(diff);
|
|
||||||
if (!added) {
|
|
||||||
added = true;
|
|
||||||
timed = true;
|
|
||||||
TimingsManager.HANDLERS.add(this);
|
|
||||||
}
|
|
||||||
if (groupHandler != null) {
|
|
||||||
groupHandler.addDiff(diff, parent);
|
|
||||||
groupHandler.children.get(id).add(diff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset this timer, setting all values to zero.
|
|
||||||
*/
|
|
||||||
void reset(boolean full) {
|
|
||||||
record.reset();
|
|
||||||
if (full) {
|
|
||||||
timed = false;
|
|
||||||
}
|
|
||||||
start = 0;
|
|
||||||
timingDepth = 0;
|
|
||||||
added = false;
|
|
||||||
children.clear();
|
|
||||||
checkEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public TimingHandler getTimingHandler() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
return (this == o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is simply for the Closeable interface so it can be used with try-with-resources ()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
stopTimingIfSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSpecial() {
|
|
||||||
return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isTimed() {
|
|
||||||
return timed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
TimingData[] cloneChildren() {
|
|
||||||
final TimingData[] clonedChildren = new TimingData[children.size()];
|
|
||||||
int i = 0;
|
|
||||||
for (TimingData child : children.values()) {
|
|
||||||
clonedChildren[i++] = child.clone();
|
|
||||||
}
|
|
||||||
return clonedChildren;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import co.aikar.timings.TimingHistory.RegionData.RegionId;
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import co.aikar.util.LoadingMap;
|
|
||||||
import co.aikar.util.MRUMapCache;
|
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK;
|
|
||||||
import static co.aikar.timings.TimingsManager.MINUTE_REPORTS;
|
|
||||||
import static co.aikar.util.JSONUtil.*;
|
|
||||||
|
|
||||||
@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"})
|
|
||||||
public class TimingHistory {
|
|
||||||
public static long lastMinuteTime;
|
|
||||||
public static long timedTicks;
|
|
||||||
public static long playerTicks;
|
|
||||||
public static long entityTicks;
|
|
||||||
public static long tileEntityTicks;
|
|
||||||
public static long activatedEntityTicks;
|
|
||||||
private static int worldIdPool = 1;
|
|
||||||
static Map<String, Integer> worldMap = LoadingMap.newHashMap(new Function<String, Integer>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Integer apply(@Nullable String input) {
|
|
||||||
return worldIdPool++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
private final long endTime;
|
|
||||||
private final long startTime;
|
|
||||||
private final long totalTicks;
|
|
||||||
private final long totalTime; // Represents all time spent running the server this history
|
|
||||||
private final MinuteReport[] minuteReports;
|
|
||||||
|
|
||||||
private final TimingHistoryEntry[] entries;
|
|
||||||
final Set<Material> tileEntityTypeSet = Sets.newHashSet();
|
|
||||||
final Set<EntityType> entityTypeSet = Sets.newHashSet();
|
|
||||||
private final Map<Object, Object> worlds;
|
|
||||||
|
|
||||||
TimingHistory() {
|
|
||||||
this.endTime = System.currentTimeMillis() / 1000;
|
|
||||||
this.startTime = TimingsManager.historyStart / 1000;
|
|
||||||
if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) {
|
|
||||||
this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]);
|
|
||||||
this.minuteReports[this.minuteReports.length - 1] = new MinuteReport();
|
|
||||||
} else {
|
|
||||||
this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]);
|
|
||||||
}
|
|
||||||
long ticks = 0;
|
|
||||||
for (MinuteReport mp : this.minuteReports) {
|
|
||||||
ticks += mp.ticksRecord.timed;
|
|
||||||
}
|
|
||||||
this.totalTicks = ticks;
|
|
||||||
this.totalTime = FULL_SERVER_TICK.record.getTotalTime();
|
|
||||||
this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (TimingHandler handler : TimingsManager.HANDLERS) {
|
|
||||||
entries[i++] = new TimingHistoryEntry(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Information about all loaded chunks/entities
|
|
||||||
//noinspection unchecked
|
|
||||||
this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function<World, JSONPair>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JSONPair apply(World world) {
|
|
||||||
Map<RegionId, RegionData> regions = LoadingMap.newHashMap(RegionData.LOADER);
|
|
||||||
|
|
||||||
for (Chunk chunk : world.getLoadedChunks()) {
|
|
||||||
RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ()));
|
|
||||||
|
|
||||||
for (Entity entity : chunk.getEntities()) {
|
|
||||||
if (entity == null) {
|
|
||||||
Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.entityCounts.get(entity.getType()).increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BlockState tileEntity : chunk.getTileEntities(false)) {
|
|
||||||
if (tileEntity == null) {
|
|
||||||
Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pair(
|
|
||||||
worldMap.get(world.getName()),
|
|
||||||
toArrayMapper(regions.values(),new Function<RegionData, Object>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Object apply(RegionData input) {
|
|
||||||
return toArray(
|
|
||||||
input.regionId.x,
|
|
||||||
input.regionId.z,
|
|
||||||
toObjectMapper(input.entityCounts.entrySet(),
|
|
||||||
new Function<Map.Entry<EntityType, Counter>, JSONPair>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JSONPair apply(Map.Entry<EntityType, Counter> entry) {
|
|
||||||
entityTypeSet.add(entry.getKey());
|
|
||||||
return pair(
|
|
||||||
String.valueOf(entry.getKey().ordinal()),
|
|
||||||
entry.getValue().count()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
toObjectMapper(input.tileEntityCounts.entrySet(),
|
|
||||||
new Function<Map.Entry<Material, Counter>, JSONPair>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JSONPair apply(Map.Entry<Material, Counter> entry) {
|
|
||||||
tileEntityTypeSet.add(entry.getKey());
|
|
||||||
return pair(
|
|
||||||
String.valueOf(entry.getKey().ordinal()),
|
|
||||||
entry.getValue().count()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
static class RegionData {
|
|
||||||
final RegionId regionId;
|
|
||||||
@SuppressWarnings("Guava")
|
|
||||||
static Function<RegionId, RegionData> LOADER = new Function<RegionId, RegionData>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public RegionData apply(@NotNull RegionId id) {
|
|
||||||
return new RegionData(id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
RegionData(@NotNull RegionId id) {
|
|
||||||
this.regionId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegionData that = (RegionData) o;
|
|
||||||
|
|
||||||
return regionId.equals(that.regionId);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return regionId.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Map<EntityType, Counter> entityCounts = MRUMapCache.of(LoadingMap.of(
|
|
||||||
new EnumMap<EntityType, Counter>(EntityType.class), k -> new Counter()
|
|
||||||
));
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Map<Material, Counter> tileEntityCounts = MRUMapCache.of(LoadingMap.of(
|
|
||||||
new EnumMap<Material, Counter>(Material.class), k -> new Counter()
|
|
||||||
));
|
|
||||||
|
|
||||||
static class RegionId {
|
|
||||||
final int x, z;
|
|
||||||
final long regionId;
|
|
||||||
RegionId(int x, int z) {
|
|
||||||
this.x = x >> 5 << 5;
|
|
||||||
this.z = z >> 5 << 5;
|
|
||||||
this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
RegionId regionId1 = (RegionId) o;
|
|
||||||
|
|
||||||
return regionId == regionId1.regionId;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return (int) (regionId ^ (regionId >>> 32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void resetTicks(boolean fullReset) {
|
|
||||||
if (fullReset) {
|
|
||||||
// Non full is simply for 1 minute reports
|
|
||||||
timedTicks = 0;
|
|
||||||
}
|
|
||||||
lastMinuteTime = System.nanoTime();
|
|
||||||
playerTicks = 0;
|
|
||||||
tileEntityTicks = 0;
|
|
||||||
entityTicks = 0;
|
|
||||||
activatedEntityTicks = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
Object export() {
|
|
||||||
return createObject(
|
|
||||||
pair("s", startTime),
|
|
||||||
pair("e", endTime),
|
|
||||||
pair("tk", totalTicks),
|
|
||||||
pair("tm", totalTime),
|
|
||||||
pair("w", worlds),
|
|
||||||
pair("h", toArrayMapper(entries, new Function<TimingHistoryEntry, Object>() {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Object apply(TimingHistoryEntry entry) {
|
|
||||||
TimingData record = entry.data;
|
|
||||||
if (!record.hasData()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return entry.export();
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
pair("mp", toArrayMapper(minuteReports, new Function<MinuteReport, Object>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Object apply(MinuteReport input) {
|
|
||||||
return input.export();
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MinuteReport {
|
|
||||||
final long time = System.currentTimeMillis() / 1000;
|
|
||||||
|
|
||||||
final TicksRecord ticksRecord = new TicksRecord();
|
|
||||||
final PingRecord pingRecord = new PingRecord();
|
|
||||||
final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone();
|
|
||||||
final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed;
|
|
||||||
final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory;
|
|
||||||
final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory;
|
|
||||||
final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
List<Object> export() {
|
|
||||||
return toArray(
|
|
||||||
time,
|
|
||||||
Math.round(tps * 100D) / 100D,
|
|
||||||
Math.round(pingRecord.avg * 100D) / 100D,
|
|
||||||
fst.export(),
|
|
||||||
toArray(ticksRecord.timed,
|
|
||||||
ticksRecord.player,
|
|
||||||
ticksRecord.entity,
|
|
||||||
ticksRecord.activatedEntity,
|
|
||||||
ticksRecord.tileEntity
|
|
||||||
),
|
|
||||||
usedMemory,
|
|
||||||
freeMemory,
|
|
||||||
loadAvg
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TicksRecord {
|
|
||||||
final long timed;
|
|
||||||
final long player;
|
|
||||||
final long entity;
|
|
||||||
final long tileEntity;
|
|
||||||
final long activatedEntity;
|
|
||||||
|
|
||||||
TicksRecord() {
|
|
||||||
timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200);
|
|
||||||
player = playerTicks;
|
|
||||||
entity = entityTicks;
|
|
||||||
tileEntity = tileEntityTicks;
|
|
||||||
activatedEntity = activatedEntityTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PingRecord {
|
|
||||||
final double avg;
|
|
||||||
|
|
||||||
PingRecord() {
|
|
||||||
final Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
|
||||||
int totalPing = 0;
|
|
||||||
for (Player player : onlinePlayers) {
|
|
||||||
totalPing += player.spigot().getPing();
|
|
||||||
}
|
|
||||||
avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static class Counter {
|
|
||||||
private int count = 0;
|
|
||||||
public int increment() {
|
|
||||||
return ++count;
|
|
||||||
}
|
|
||||||
public int count() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static co.aikar.util.JSONUtil.toArrayMapper;
|
|
||||||
|
|
||||||
class TimingHistoryEntry {
|
|
||||||
final TimingData data;
|
|
||||||
private final TimingData[] children;
|
|
||||||
|
|
||||||
TimingHistoryEntry(@NotNull TimingHandler handler) {
|
|
||||||
this.data = handler.record.clone();
|
|
||||||
children = handler.cloneChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
List<Object> export() {
|
|
||||||
List<Object> result = data.export();
|
|
||||||
if (children.length > 0) {
|
|
||||||
result.add(
|
|
||||||
toArrayMapper(children, new Function<TimingData, Object>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Object apply(TimingData child) {
|
|
||||||
return child.export();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import co.aikar.util.LoadingMap;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Used as a basis for fast HashMap key comparisons for the Timing Map.</p>
|
|
||||||
*
|
|
||||||
* This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings
|
|
||||||
*/
|
|
||||||
final class TimingIdentifier {
|
|
||||||
/**
|
|
||||||
* Holds all groups. Autoloads on request for a group by name.
|
|
||||||
*/
|
|
||||||
static final Map<String, TimingGroup> GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new);
|
|
||||||
private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft");
|
|
||||||
final String group;
|
|
||||||
final String name;
|
|
||||||
final TimingHandler groupHandler;
|
|
||||||
private final int hashCode;
|
|
||||||
|
|
||||||
TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) {
|
|
||||||
this.group = group != null ? group: DEFAULT_GROUP.name;
|
|
||||||
this.name = name;
|
|
||||||
this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null;
|
|
||||||
this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static TimingGroup getGroup(@Nullable String groupName) {
|
|
||||||
if (groupName == null) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return DEFAULT_GROUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GROUP_MAP.get(groupName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimingIdentifier that = (TimingIdentifier) o;
|
|
||||||
return Objects.equals(group, that.group) && Objects.equals(name, that.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TimingIdentifier{id=" + group + ":" + name +'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TimingGroup {
|
|
||||||
|
|
||||||
private static AtomicInteger idPool = new AtomicInteger(1);
|
|
||||||
final int id = idPool.getAndIncrement();
|
|
||||||
|
|
||||||
final String name;
|
|
||||||
final List<TimingHandler> handlers = Collections.synchronizedList(new ArrayList<>(64));
|
|
||||||
|
|
||||||
private TimingGroup(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
TimingGroup that = (TimingGroup) o;
|
|
||||||
return id == that.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.EvictingQueue;
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"})
|
|
||||||
public final class Timings {
|
|
||||||
|
|
||||||
private static final int MAX_HISTORY_FRAMES = 12;
|
|
||||||
public static final Timing NULL_HANDLER = new NullTimingHandler();
|
|
||||||
static boolean timingsEnabled = false;
|
|
||||||
static boolean verboseEnabled = false;
|
|
||||||
private static int historyInterval = -1;
|
|
||||||
private static int historyLength = -1;
|
|
||||||
|
|
||||||
private Timings() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Timing for a plugin corresponding to a name.
|
|
||||||
*
|
|
||||||
* @param plugin Plugin to own the Timing
|
|
||||||
* @param name Name of Timing
|
|
||||||
* @return Handler
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Timing of(@NotNull Plugin plugin, @NotNull String name) {
|
|
||||||
Timing pluginHandler = null;
|
|
||||||
if (plugin != null) {
|
|
||||||
pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER);
|
|
||||||
}
|
|
||||||
return of(plugin, name, pluginHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns a handler that has a groupHandler timer handler. Parent timers should not have their
|
|
||||||
* start/stop methods called directly, as the children will call it for you.</p>
|
|
||||||
*
|
|
||||||
* Parent Timers are used to group multiple subsections together and get a summary of them combined
|
|
||||||
* Parent Handler can not be changed after first call
|
|
||||||
*
|
|
||||||
* @param plugin Plugin to own the Timing
|
|
||||||
* @param name Name of Timing
|
|
||||||
* @param groupHandler Parent handler to mirror .start/stop calls to
|
|
||||||
* @return Timing Handler
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) {
|
|
||||||
Preconditions.checkNotNull(plugin, "Plugin can not be null");
|
|
||||||
return TimingsManager.getHandler(plugin.getName(), name, groupHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Timing object after starting it, useful for Java7 try-with-resources.
|
|
||||||
*
|
|
||||||
* try (Timing ignored = Timings.ofStart(plugin, someName)) {
|
|
||||||
* // timed section
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param plugin Plugin to own the Timing
|
|
||||||
* @param name Name of Timing
|
|
||||||
* @return Timing Handler
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) {
|
|
||||||
return ofStart(plugin, name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Timing object after starting it, useful for Java7 try-with-resources.
|
|
||||||
*
|
|
||||||
* try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) {
|
|
||||||
* // timed section
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param plugin Plugin to own the Timing
|
|
||||||
* @param name Name of Timing
|
|
||||||
* @param groupHandler Parent handler to mirror .start/stop calls to
|
|
||||||
* @return Timing Handler
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) {
|
|
||||||
Timing timing = of(plugin, name, groupHandler);
|
|
||||||
timing.startTiming();
|
|
||||||
return timing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether or not the Spigot Timings system is enabled
|
|
||||||
*
|
|
||||||
* @return Enabled or not
|
|
||||||
*/
|
|
||||||
public static boolean isTimingsEnabled() {
|
|
||||||
return timingsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Sets whether or not the Spigot Timings system should be enabled</p>
|
|
||||||
*
|
|
||||||
* Calling this will reset timing data.
|
|
||||||
*
|
|
||||||
* @param enabled Should timings be reported
|
|
||||||
*/
|
|
||||||
public static void setTimingsEnabled(boolean enabled) {
|
|
||||||
timingsEnabled = enabled;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Sets whether or not the Timings should monitor at Verbose level.</p>
|
|
||||||
*
|
|
||||||
* <p>When Verbose is disabled, high-frequency timings will not be available.</p>
|
|
||||||
*
|
|
||||||
* @return Enabled or not
|
|
||||||
*/
|
|
||||||
public static boolean isVerboseTimingsEnabled() {
|
|
||||||
return verboseEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Sets whether or not the Timings should monitor at Verbose level.</p>
|
|
||||||
*
|
|
||||||
* When Verbose is disabled, high-frequency timings will not be available.
|
|
||||||
* Calling this will reset timing data.
|
|
||||||
*
|
|
||||||
* @param enabled Should high-frequency timings be reported
|
|
||||||
*/
|
|
||||||
public static void setVerboseTimingsEnabled(boolean enabled) {
|
|
||||||
verboseEnabled = enabled;
|
|
||||||
TimingsManager.needsRecheckEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Gets the interval between Timing History report generation.</p>
|
|
||||||
*
|
|
||||||
* Defaults to 5 minutes (6000 ticks)
|
|
||||||
*
|
|
||||||
* @return Interval in ticks
|
|
||||||
*/
|
|
||||||
public static int getHistoryInterval() {
|
|
||||||
return historyInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Sets the interval between Timing History report generations.</p>
|
|
||||||
*
|
|
||||||
* <p>Defaults to 5 minutes (6000 ticks)</p>
|
|
||||||
*
|
|
||||||
* This will recheck your history length, so lowering this value will lower your
|
|
||||||
* history length if you need more than 60 history windows.
|
|
||||||
*
|
|
||||||
* @param interval Interval in ticks
|
|
||||||
*/
|
|
||||||
public static void setHistoryInterval(int interval) {
|
|
||||||
historyInterval = Math.max(20*60, interval);
|
|
||||||
// Recheck the history length with the new Interval
|
|
||||||
if (historyLength != -1) {
|
|
||||||
setHistoryLength(historyLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets how long in ticks Timings history is kept for the server.
|
|
||||||
*
|
|
||||||
* Defaults to 1 hour (72000 ticks)
|
|
||||||
*
|
|
||||||
* @return Duration in Ticks
|
|
||||||
*/
|
|
||||||
public static int getHistoryLength() {
|
|
||||||
return historyLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets how long Timing History reports are kept for the server.
|
|
||||||
*
|
|
||||||
* Defaults to 1 hours(72000 ticks)
|
|
||||||
*
|
|
||||||
* This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12)
|
|
||||||
*
|
|
||||||
* Will not reset Timing Data but may truncate old history if the new length is less than old length.
|
|
||||||
*
|
|
||||||
* @param length Duration in ticks
|
|
||||||
*/
|
|
||||||
public static void setHistoryLength(int length) {
|
|
||||||
// Cap at 12 History Frames, 1 hour at 5 minute frames.
|
|
||||||
int maxLength = historyInterval * MAX_HISTORY_FRAMES;
|
|
||||||
// For special cases of servers with special permission to bypass the max.
|
|
||||||
// This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side.
|
|
||||||
// Setting this will not help you bypass the max unless Aikar has added an exception on the API side.
|
|
||||||
if (System.getProperty("timings.bypassMax") != null) {
|
|
||||||
maxLength = Integer.MAX_VALUE;
|
|
||||||
}
|
|
||||||
historyLength = Math.max(Math.min(maxLength, length), historyInterval);
|
|
||||||
Queue<TimingHistory> oldQueue = TimingsManager.HISTORY;
|
|
||||||
int frames = (getHistoryLength() / getHistoryInterval());
|
|
||||||
if (length > maxLength) {
|
|
||||||
Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length.");
|
|
||||||
}
|
|
||||||
TimingsManager.HISTORY = EvictingQueue.create(frames);
|
|
||||||
TimingsManager.HISTORY.addAll(oldQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets all Timing Data
|
|
||||||
*/
|
|
||||||
public static void reset() {
|
|
||||||
TimingsManager.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a report and sends it to the specified command sender.
|
|
||||||
*
|
|
||||||
* If sender is null, ConsoleCommandSender will be used.
|
|
||||||
* @param sender The sender to send to, or null to use the ConsoleCommandSender
|
|
||||||
*/
|
|
||||||
public static void generateReport(@Nullable CommandSender sender) {
|
|
||||||
if (sender == null) {
|
|
||||||
sender = Bukkit.getConsoleSender();
|
|
||||||
}
|
|
||||||
TimingsExport.requestingReport.add(sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a report and sends it to the specified listener.
|
|
||||||
* Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done!
|
|
||||||
* @param sender The listener to send responses too.
|
|
||||||
*/
|
|
||||||
public static void generateReport(@NotNull TimingsReportListener sender) {
|
|
||||||
Validate.notNull(sender);
|
|
||||||
TimingsExport.requestingReport.add(sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
Protected API: These are for internal use only in Bukkit/CraftBukkit
|
|
||||||
These do not have isPrimaryThread() checks in the startTiming/stopTiming
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
static TimingHandler ofSafe(@NotNull String name) {
|
|
||||||
return ofSafe(null, name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) {
|
|
||||||
Timing pluginHandler = null;
|
|
||||||
if (plugin != null) {
|
|
||||||
pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER);
|
|
||||||
}
|
|
||||||
return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) {
|
|
||||||
return ofSafe(null, name, groupHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) {
|
|
||||||
return TimingsManager.getHandler(groupName, name, groupHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.defaults.BukkitCommand;
|
|
||||||
import org.bukkit.util.StringUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
|
||||||
public class TimingsCommand extends BukkitCommand {
|
|
||||||
private static final List<String> TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff");
|
|
||||||
private long lastResetAttempt = 0;
|
|
||||||
|
|
||||||
public TimingsCommand(@NotNull String name) {
|
|
||||||
super(name);
|
|
||||||
this.description = "Manages Spigot Timings data to see performance of the server.";
|
|
||||||
this.usageMessage = "/timings <reset|report|on|off|verbon|verboff>";
|
|
||||||
this.setPermission("bukkit.command.timings");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
|
|
||||||
if (!testPermission(sender)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (args.length < 1) {
|
|
||||||
sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final String arg = args[0];
|
|
||||||
if ("on".equalsIgnoreCase(arg)) {
|
|
||||||
Timings.setTimingsEnabled(true);
|
|
||||||
sender.sendMessage("Enabled Timings & Reset");
|
|
||||||
return true;
|
|
||||||
} else if ("off".equalsIgnoreCase(arg)) {
|
|
||||||
Timings.setTimingsEnabled(false);
|
|
||||||
sender.sendMessage("Disabled Timings");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Timings.isTimingsEnabled()) {
|
|
||||||
sender.sendMessage("Please enable timings by typing /timings on");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if ("verbon".equalsIgnoreCase(arg)) {
|
|
||||||
Timings.setVerboseTimingsEnabled(true);
|
|
||||||
sender.sendMessage("Enabled Verbose Timings");
|
|
||||||
return true;
|
|
||||||
} else if ("verboff".equalsIgnoreCase(arg)) {
|
|
||||||
Timings.setVerboseTimingsEnabled(false);
|
|
||||||
sender.sendMessage("Disabled Verbose Timings");
|
|
||||||
return true;
|
|
||||||
} else if ("reset".equalsIgnoreCase(arg)) {
|
|
||||||
if (now - lastResetAttempt < 30000) {
|
|
||||||
TimingsManager.reset();
|
|
||||||
sender.sendMessage(ChatColor.RED + "Timings reset. Please wait 5-10 minutes before using /timings report.");
|
|
||||||
} else {
|
|
||||||
lastResetAttempt = now;
|
|
||||||
sender.sendMessage(ChatColor.RED + "WARNING: Timings v2 should not be reset. If you are encountering lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ("cost".equals(arg)) {
|
|
||||||
sender.sendMessage("Timings cost: " + TimingsExport.getCost());
|
|
||||||
} else if (
|
|
||||||
"paste".equalsIgnoreCase(arg) ||
|
|
||||||
"report".equalsIgnoreCase(arg) ||
|
|
||||||
"get".equalsIgnoreCase(arg) ||
|
|
||||||
"merged".equalsIgnoreCase(arg) ||
|
|
||||||
"separate".equalsIgnoreCase(arg)
|
|
||||||
) {
|
|
||||||
Timings.generateReport(sender);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
|
||||||
Validate.notNull(sender, "Sender cannot be null");
|
|
||||||
Validate.notNull(args, "Arguments cannot be null");
|
|
||||||
Validate.notNull(alias, "Alias cannot be null");
|
|
||||||
|
|
||||||
if (args.length == 1) {
|
|
||||||
return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS,
|
|
||||||
new ArrayList<String>(TIMINGS_SUBCOMMANDS.size()));
|
|
||||||
}
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,355 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.configuration.MemorySection;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
import org.json.simple.JSONValue;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.RuntimeMXBean;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
|
|
||||||
import static co.aikar.timings.TimingsManager.HISTORY;
|
|
||||||
import static co.aikar.util.JSONUtil.appendObjectData;
|
|
||||||
import static co.aikar.util.JSONUtil.createObject;
|
|
||||||
import static co.aikar.util.JSONUtil.pair;
|
|
||||||
import static co.aikar.util.JSONUtil.toArray;
|
|
||||||
import static co.aikar.util.JSONUtil.toArrayMapper;
|
|
||||||
import static co.aikar.util.JSONUtil.toObjectMapper;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "SuppressionAnnotation"})
|
|
||||||
class TimingsExport extends Thread {
|
|
||||||
|
|
||||||
private final TimingsReportListener listeners;
|
|
||||||
private final Map out;
|
|
||||||
private final TimingHistory[] history;
|
|
||||||
private static long lastReport = 0;
|
|
||||||
final static List<CommandSender> requestingReport = Lists.newArrayList();
|
|
||||||
|
|
||||||
private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) {
|
|
||||||
super("Timings paste thread");
|
|
||||||
this.listeners = listeners;
|
|
||||||
this.out = out;
|
|
||||||
this.history = history;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if any pending reports are being requested, and builds one if needed.
|
|
||||||
*/
|
|
||||||
static void reportTimings() {
|
|
||||||
if (requestingReport.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TimingsReportListener listeners = new TimingsReportListener(requestingReport);
|
|
||||||
listeners.addConsoleIfNeeded();
|
|
||||||
|
|
||||||
requestingReport.clear();
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
final long lastReportDiff = now - lastReport;
|
|
||||||
if (lastReportDiff < 60000) {
|
|
||||||
listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)");
|
|
||||||
listeners.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final long lastStartDiff = now - TimingsManager.timingStart;
|
|
||||||
if (lastStartDiff < 180000) {
|
|
||||||
listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)");
|
|
||||||
listeners.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report...");
|
|
||||||
lastReport = now;
|
|
||||||
Map parent = createObject(
|
|
||||||
// Get some basic system details about the server
|
|
||||||
pair("version", Bukkit.getVersion()),
|
|
||||||
pair("maxplayers", Bukkit.getMaxPlayers()),
|
|
||||||
pair("start", TimingsManager.timingStart / 1000),
|
|
||||||
pair("end", System.currentTimeMillis() / 1000),
|
|
||||||
pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000)
|
|
||||||
);
|
|
||||||
if (!TimingsManager.privacy) {
|
|
||||||
appendObjectData(parent,
|
|
||||||
pair("server", Bukkit.getUnsafe().getTimingsServerName()),
|
|
||||||
pair("motd", Bukkit.getServer().getMotd()),
|
|
||||||
pair("online-mode", Bukkit.getServer().getOnlineMode()),
|
|
||||||
pair("icon", Bukkit.getServer().getServerIcon().getData())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Runtime runtime = Runtime.getRuntime();
|
|
||||||
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
|
||||||
|
|
||||||
parent.put("system", createObject(
|
|
||||||
pair("timingcost", getCost()),
|
|
||||||
pair("name", System.getProperty("os.name")),
|
|
||||||
pair("version", System.getProperty("os.version")),
|
|
||||||
pair("jvmversion", System.getProperty("java.version")),
|
|
||||||
pair("arch", System.getProperty("os.arch")),
|
|
||||||
pair("maxmem", runtime.maxMemory()),
|
|
||||||
pair("cpu", runtime.availableProcessors()),
|
|
||||||
pair("runtime", ManagementFactory.getRuntimeMXBean().getUptime()),
|
|
||||||
pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")),
|
|
||||||
pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime()))))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
Set<Material> tileEntityTypeSet = Sets.newHashSet();
|
|
||||||
Set<EntityType> entityTypeSet = Sets.newHashSet();
|
|
||||||
|
|
||||||
int size = HISTORY.size();
|
|
||||||
TimingHistory[] history = new TimingHistory[size + 1];
|
|
||||||
int i = 0;
|
|
||||||
for (TimingHistory timingHistory : HISTORY) {
|
|
||||||
tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet);
|
|
||||||
entityTypeSet.addAll(timingHistory.entityTypeSet);
|
|
||||||
history[i++] = timingHistory;
|
|
||||||
}
|
|
||||||
|
|
||||||
history[i] = new TimingHistory(); // Current snapshot
|
|
||||||
tileEntityTypeSet.addAll(history[i].tileEntityTypeSet);
|
|
||||||
entityTypeSet.addAll(history[i].entityTypeSet);
|
|
||||||
|
|
||||||
|
|
||||||
Map handlers = createObject();
|
|
||||||
Map groupData;
|
|
||||||
synchronized (TimingIdentifier.GROUP_MAP) {
|
|
||||||
for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) {
|
|
||||||
synchronized (group.handlers) {
|
|
||||||
for (TimingHandler id : group.handlers) {
|
|
||||||
|
|
||||||
if (!id.isTimed() && !id.isSpecial()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = id.identifier.name;
|
|
||||||
if (name.startsWith("##")) {
|
|
||||||
name = name.substring(3);
|
|
||||||
}
|
|
||||||
handlers.put(id.id, toArray(
|
|
||||||
group.id,
|
|
||||||
name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupData = toObjectMapper(
|
|
||||||
TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.put("idmap", createObject(
|
|
||||||
pair("groups", groupData),
|
|
||||||
pair("handlers", handlers),
|
|
||||||
pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))),
|
|
||||||
pair("tileentity",
|
|
||||||
toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))),
|
|
||||||
pair("entity",
|
|
||||||
toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name())))
|
|
||||||
));
|
|
||||||
|
|
||||||
// Information about loaded plugins
|
|
||||||
|
|
||||||
parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(),
|
|
||||||
plugin -> pair(plugin.getName(), createObject(
|
|
||||||
pair("version", plugin.getDescription().getVersion()),
|
|
||||||
pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()),
|
|
||||||
pair("website", plugin.getDescription().getWebsite()),
|
|
||||||
pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", "))
|
|
||||||
))));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Information on the users Config
|
|
||||||
|
|
||||||
parent.put("config", createObject(
|
|
||||||
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
|
|
||||||
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
|
|
||||||
pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null))
|
|
||||||
));
|
|
||||||
|
|
||||||
new TimingsExport(listeners, parent, history).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
static long getCost() {
|
|
||||||
// Benchmark the users System.nanotime() for cost basis
|
|
||||||
int passes = 100;
|
|
||||||
TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1");
|
|
||||||
TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2");
|
|
||||||
TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3");
|
|
||||||
TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4");
|
|
||||||
TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5");
|
|
||||||
TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6");
|
|
||||||
|
|
||||||
long start = System.nanoTime();
|
|
||||||
for (int i = 0; i < passes; i++) {
|
|
||||||
SAMPLER1.startTiming();
|
|
||||||
SAMPLER2.startTiming();
|
|
||||||
SAMPLER3.startTiming();
|
|
||||||
SAMPLER3.stopTiming();
|
|
||||||
SAMPLER4.startTiming();
|
|
||||||
SAMPLER5.startTiming();
|
|
||||||
SAMPLER6.startTiming();
|
|
||||||
SAMPLER6.stopTiming();
|
|
||||||
SAMPLER5.stopTiming();
|
|
||||||
SAMPLER4.stopTiming();
|
|
||||||
SAMPLER2.stopTiming();
|
|
||||||
SAMPLER1.stopTiming();
|
|
||||||
}
|
|
||||||
long timingsCost = (System.nanoTime() - start) / passes / 6;
|
|
||||||
SAMPLER1.reset(true);
|
|
||||||
SAMPLER2.reset(true);
|
|
||||||
SAMPLER3.reset(true);
|
|
||||||
SAMPLER4.reset(true);
|
|
||||||
SAMPLER5.reset(true);
|
|
||||||
SAMPLER6.reset(true);
|
|
||||||
return timingsCost;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) {
|
|
||||||
|
|
||||||
JSONObject object = new JSONObject();
|
|
||||||
for (String key : config.getKeys(false)) {
|
|
||||||
String fullKey = (parentKey != null ? parentKey + "." + key : key);
|
|
||||||
if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final Object val = config.get(key);
|
|
||||||
|
|
||||||
object.put(key, valAsJSON(val, fullKey));
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object valAsJSON(Object val, final String parentKey) {
|
|
||||||
if (!(val instanceof MemorySection)) {
|
|
||||||
if (val instanceof List) {
|
|
||||||
Iterable<Object> v = (Iterable<Object>) val;
|
|
||||||
return toArrayMapper(v, input -> valAsJSON(input, parentKey));
|
|
||||||
} else {
|
|
||||||
return val.toString();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return mapAsJSON((ConfigurationSection) val, parentKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
out.put("data", toArrayMapper(history, TimingHistory::export));
|
|
||||||
|
|
||||||
|
|
||||||
String response = null;
|
|
||||||
String timingsURL = null;
|
|
||||||
try {
|
|
||||||
HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection();
|
|
||||||
con.setDoOutput(true);
|
|
||||||
String hostName = "BrokenHost";
|
|
||||||
try {
|
|
||||||
hostName = InetAddress.getLocalHost().getHostName();
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName);
|
|
||||||
con.setRequestMethod("POST");
|
|
||||||
con.setInstanceFollowRedirects(false);
|
|
||||||
|
|
||||||
OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{
|
|
||||||
this.def.setLevel(7);
|
|
||||||
}};
|
|
||||||
|
|
||||||
request.write(JSONValue.toJSONString(out).getBytes("UTF-8"));
|
|
||||||
request.close();
|
|
||||||
|
|
||||||
response = getResponse(con);
|
|
||||||
|
|
||||||
if (con.getResponseCode() != 302) {
|
|
||||||
listeners.sendMessage(
|
|
||||||
ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage());
|
|
||||||
listeners.sendMessage(ChatColor.RED + "Check your logs for more information");
|
|
||||||
if (response != null) {
|
|
||||||
Bukkit.getLogger().log(Level.SEVERE, response);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
timingsURL = con.getHeaderField("Location");
|
|
||||||
listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL);
|
|
||||||
|
|
||||||
if (response != null && !response.isEmpty()) {
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response);
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information");
|
|
||||||
if (response != null) {
|
|
||||||
Bukkit.getLogger().log(Level.SEVERE, response);
|
|
||||||
}
|
|
||||||
Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex);
|
|
||||||
} finally {
|
|
||||||
this.listeners.done(timingsURL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getResponse(HttpURLConnection con) throws IOException {
|
|
||||||
InputStream is = null;
|
|
||||||
try {
|
|
||||||
is = con.getInputStream();
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
byte[] b = new byte[1024];
|
|
||||||
int bytesRead;
|
|
||||||
while ((bytesRead = is.read(b)) != -1) {
|
|
||||||
bos.write(b, 0, bytesRead);
|
|
||||||
}
|
|
||||||
return bos.toString();
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
|
||||||
listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information");
|
|
||||||
Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex);
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
if (is != null) {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import co.aikar.util.LoadingMap;
|
|
||||||
import com.google.common.collect.EvictingQueue;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.plugin.java.PluginClassLoader;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public final class TimingsManager {
|
|
||||||
static final Map<TimingIdentifier, TimingHandler> TIMING_MAP = LoadingMap.of(
|
|
||||||
new ConcurrentHashMap<>(4096, .5F), TimingHandler::new
|
|
||||||
);
|
|
||||||
public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler();
|
|
||||||
public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK);
|
|
||||||
public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins");
|
|
||||||
public static List<String> hiddenConfigs = new ArrayList<String>();
|
|
||||||
public static boolean privacy = false;
|
|
||||||
|
|
||||||
static final List<TimingHandler> HANDLERS = new ArrayList<>(1024);
|
|
||||||
static final List<TimingHistory.MinuteReport> MINUTE_REPORTS = new ArrayList<>(64);
|
|
||||||
|
|
||||||
static EvictingQueue<TimingHistory> HISTORY = EvictingQueue.create(12);
|
|
||||||
static long timingStart = 0;
|
|
||||||
static long historyStart = 0;
|
|
||||||
static boolean needsFullReset = false;
|
|
||||||
static boolean needsRecheckEnabled = false;
|
|
||||||
|
|
||||||
private TimingsManager() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets all timing data on the next tick
|
|
||||||
*/
|
|
||||||
static void reset() {
|
|
||||||
needsFullReset = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ticked every tick by CraftBukkit to count the number of times a timer
|
|
||||||
* caused TPS loss.
|
|
||||||
*/
|
|
||||||
static void tick() {
|
|
||||||
if (Timings.timingsEnabled) {
|
|
||||||
boolean violated = FULL_SERVER_TICK.isViolated();
|
|
||||||
|
|
||||||
for (TimingHandler handler : HANDLERS) {
|
|
||||||
if (handler.isSpecial()) {
|
|
||||||
// We manually call this
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
handler.processTick(violated);
|
|
||||||
}
|
|
||||||
|
|
||||||
TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size();
|
|
||||||
TimingHistory.timedTicks++;
|
|
||||||
// Generate TPS/Ping/Tick reports every minute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void stopServer() {
|
|
||||||
Timings.timingsEnabled = false;
|
|
||||||
recheckEnabled();
|
|
||||||
}
|
|
||||||
static void recheckEnabled() {
|
|
||||||
synchronized (TIMING_MAP) {
|
|
||||||
for (TimingHandler timings : TIMING_MAP.values()) {
|
|
||||||
timings.checkEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
needsRecheckEnabled = false;
|
|
||||||
}
|
|
||||||
static void resetTimings() {
|
|
||||||
if (needsFullReset) {
|
|
||||||
// Full resets need to re-check every handlers enabled state
|
|
||||||
// Timing map can be modified from async so we must sync on it.
|
|
||||||
synchronized (TIMING_MAP) {
|
|
||||||
for (TimingHandler timings : TIMING_MAP.values()) {
|
|
||||||
timings.reset(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "Timings Reset");
|
|
||||||
HISTORY.clear();
|
|
||||||
needsFullReset = false;
|
|
||||||
needsRecheckEnabled = false;
|
|
||||||
timingStart = System.currentTimeMillis();
|
|
||||||
} else {
|
|
||||||
// Soft resets only need to act on timings that have done something
|
|
||||||
// Handlers can only be modified on main thread.
|
|
||||||
for (TimingHandler timings : HANDLERS) {
|
|
||||||
timings.reset(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLERS.clear();
|
|
||||||
MINUTE_REPORTS.clear();
|
|
||||||
|
|
||||||
TimingHistory.resetTicks(true);
|
|
||||||
historyStart = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) {
|
|
||||||
return TIMING_MAP.get(new TimingIdentifier(group, name, parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Due to access restrictions, we need a helper method to get a Command TimingHandler with String group</p>
|
|
||||||
*
|
|
||||||
* Plugins should never call this
|
|
||||||
*
|
|
||||||
* @param pluginName Plugin this command is associated with
|
|
||||||
* @param command Command to get timings for
|
|
||||||
* @return TimingHandler
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) {
|
|
||||||
Plugin plugin = null;
|
|
||||||
final Server server = Bukkit.getServer();
|
|
||||||
if (!( server == null || pluginName == null ||
|
|
||||||
"minecraft".equals(pluginName) || "bukkit".equals(pluginName) ||
|
|
||||||
"spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName)
|
|
||||||
)) {
|
|
||||||
plugin = server.getPluginManager().getPlugin(pluginName);
|
|
||||||
}
|
|
||||||
if (plugin == null) {
|
|
||||||
// Plugin is passing custom fallback prefix, try to look up by class loader
|
|
||||||
plugin = getPluginByClassloader(command.getClass());
|
|
||||||
}
|
|
||||||
if (plugin == null) {
|
|
||||||
return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the
|
|
||||||
* Plugin that created this class.
|
|
||||||
*
|
|
||||||
* @param clazz Class to check
|
|
||||||
* @return Plugin if created by a plugin
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static Plugin getPluginByClassloader(@Nullable Class<?> clazz) {
|
|
||||||
if (clazz == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final ClassLoader classLoader = clazz.getClassLoader();
|
|
||||||
if (classLoader instanceof PluginClassLoader) {
|
|
||||||
PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader;
|
|
||||||
return pluginClassLoader.getPlugin();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
|
||||||
import org.bukkit.command.MessageCommandSender;
|
|
||||||
import org.bukkit.command.RemoteConsoleCommandSender;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public class TimingsReportListener implements MessageCommandSender {
|
|
||||||
private final List<CommandSender> senders;
|
|
||||||
private final Runnable onDone;
|
|
||||||
private String timingsURL;
|
|
||||||
|
|
||||||
public TimingsReportListener(@NotNull CommandSender senders) {
|
|
||||||
this(senders, null);
|
|
||||||
}
|
|
||||||
public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) {
|
|
||||||
this(Lists.newArrayList(sender), onDone);
|
|
||||||
}
|
|
||||||
public TimingsReportListener(@NotNull List<CommandSender> senders) {
|
|
||||||
this(senders, null);
|
|
||||||
}
|
|
||||||
public TimingsReportListener(@NotNull List<CommandSender> senders, @Nullable Runnable onDone) {
|
|
||||||
Validate.notNull(senders);
|
|
||||||
Validate.notEmpty(senders);
|
|
||||||
|
|
||||||
this.senders = Lists.newArrayList(senders);
|
|
||||||
this.onDone = onDone;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getTimingsURL() {
|
|
||||||
return timingsURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void done() {
|
|
||||||
done(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void done(@Nullable String url) {
|
|
||||||
this.timingsURL = url;
|
|
||||||
if (onDone != null) {
|
|
||||||
onDone.run();
|
|
||||||
}
|
|
||||||
for (CommandSender sender : senders) {
|
|
||||||
if (sender instanceof TimingsReportListener) {
|
|
||||||
((TimingsReportListener) sender).done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(@NotNull String message) {
|
|
||||||
senders.forEach((sender) -> sender.sendMessage(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addConsoleIfNeeded() {
|
|
||||||
boolean hasConsole = false;
|
|
||||||
for (CommandSender sender : this.senders) {
|
|
||||||
if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
|
|
||||||
hasConsole = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasConsole) {
|
|
||||||
this.senders.add(Bukkit.getConsoleSender());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.timings;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
class UnsafeTimingHandler extends TimingHandler {
|
|
||||||
|
|
||||||
UnsafeTimingHandler(@NotNull TimingIdentifier id) {
|
|
||||||
super(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkThread() {
|
|
||||||
if (!Bukkit.isPrimaryThread()) {
|
|
||||||
throw new IllegalStateException("Calling Timings from Async Operation");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Timing startTiming() {
|
|
||||||
checkThread();
|
|
||||||
return super.startTiming();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTiming() {
|
|
||||||
checkThread();
|
|
||||||
super.stopTiming();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package co.aikar.util;
|
|
||||||
|
|
||||||
import com.google.common.collect.ForwardingMap;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class Counter <T> extends ForwardingMap<T, Long> {
|
|
||||||
private final Map<T, Long> counts = new HashMap<>();
|
|
||||||
|
|
||||||
public long decrement(@Nullable T key) {
|
|
||||||
return increment(key, -1);
|
|
||||||
}
|
|
||||||
public long increment(@Nullable T key) {
|
|
||||||
return increment(key, 1);
|
|
||||||
}
|
|
||||||
public long decrement(@Nullable T key, long amount) {
|
|
||||||
return decrement(key, -amount);
|
|
||||||
}
|
|
||||||
public long increment(@Nullable T key, long amount) {
|
|
||||||
Long count = this.getCount(key);
|
|
||||||
count += amount;
|
|
||||||
this.counts.put(key, count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCount(@Nullable T key) {
|
|
||||||
return this.counts.getOrDefault(key, 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
protected Map<T, Long> delegate() {
|
|
||||||
return this.counts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
package co.aikar.util;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.json.simple.JSONArray;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides Utility methods that assist with generating JSON Objects
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "SuppressionAnnotation"})
|
|
||||||
public final class JSONUtil {
|
|
||||||
private JSONUtil() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a key/value "JSONPair" object
|
|
||||||
*
|
|
||||||
* @param key Key to use
|
|
||||||
* @param obj Value to use
|
|
||||||
* @return JSONPair
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static JSONPair pair(@NotNull String key, @Nullable Object obj) {
|
|
||||||
return new JSONPair(key, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JSONPair pair(long key, @Nullable Object obj) {
|
|
||||||
return new JSONPair(String.valueOf(key), obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JSON object from multiple JSONPair key/value pairs
|
|
||||||
*
|
|
||||||
* @param data JSONPairs
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Map<String, Object> createObject(@NotNull JSONPair... data) {
|
|
||||||
return appendObjectData(new LinkedHashMap(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This appends multiple key/value Obj pairs into a JSON Object
|
|
||||||
*
|
|
||||||
* @param parent Map to be appended to
|
|
||||||
* @param data Data to append
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Map<String, Object> appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) {
|
|
||||||
for (JSONPair JSONPair : data) {
|
|
||||||
parent.put(JSONPair.key, JSONPair.val);
|
|
||||||
}
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This builds a JSON array from a set of data
|
|
||||||
*
|
|
||||||
* @param data Data to build JSON array from
|
|
||||||
* @return List
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static List toArray(@NotNull Object... data) {
|
|
||||||
return Lists.newArrayList(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These help build a single JSON array using a mapper function
|
|
||||||
*
|
|
||||||
* @param collection Collection to apply to
|
|
||||||
* @param mapper Mapper to apply
|
|
||||||
* @param <E> Element Type
|
|
||||||
* @return List
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <E> List toArrayMapper(@NotNull E[] collection, @NotNull Function<E, Object> mapper) {
|
|
||||||
return toArrayMapper(Lists.newArrayList(collection), mapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static <E> List toArrayMapper(@NotNull Iterable<E> collection, @NotNull Function<E, Object> mapper) {
|
|
||||||
List array = Lists.newArrayList();
|
|
||||||
for (E e : collection) {
|
|
||||||
Object object = mapper.apply(e);
|
|
||||||
if (object != null) {
|
|
||||||
array.add(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These help build a single JSON Object from a collection, using a mapper function
|
|
||||||
*
|
|
||||||
* @param collection Collection to apply to
|
|
||||||
* @param mapper Mapper to apply
|
|
||||||
* @param <E> Element Type
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <E> Map toObjectMapper(@NotNull E[] collection, @NotNull Function<E, JSONPair> mapper) {
|
|
||||||
return toObjectMapper(Lists.newArrayList(collection), mapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static <E> Map toObjectMapper(@NotNull Iterable<E> collection, @NotNull Function<E, JSONPair> mapper) {
|
|
||||||
Map object = Maps.newLinkedHashMap();
|
|
||||||
for (E e : collection) {
|
|
||||||
JSONPair JSONPair = mapper.apply(e);
|
|
||||||
if (JSONPair != null) {
|
|
||||||
object.put(JSONPair.key, JSONPair.val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simply stores a key and a value, used internally by many methods below.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("PublicInnerClass")
|
|
||||||
public static class JSONPair {
|
|
||||||
final String key;
|
|
||||||
final Object val;
|
|
||||||
|
|
||||||
JSONPair(@NotNull String key, @NotNull Object val) {
|
|
||||||
this.key = key;
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015. Starlis LLC / dba Empire Minecraft
|
|
||||||
*
|
|
||||||
* This source code is proprietary software and must not be redistributed without Starlis LLC's approval
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package co.aikar.util;
|
|
||||||
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to pass a Loader function that when a key is accessed that doesn't exist,
|
|
||||||
* automatically loads the entry into the map by calling the loader Function.
|
|
||||||
*
|
|
||||||
* .get() Will only return null if the Loader can return null.
|
|
||||||
*
|
|
||||||
* You may pass any backing Map to use.
|
|
||||||
*
|
|
||||||
* This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed.
|
|
||||||
*
|
|
||||||
* Do not wrap the backing map with Collections.synchronizedMap.
|
|
||||||
*
|
|
||||||
* @param <V> Value
|
|
||||||
*/
|
|
||||||
public class LoadingIntMap<V> extends Int2ObjectOpenHashMap<V> {
|
|
||||||
private final Function<Integer, V> loader;
|
|
||||||
|
|
||||||
public LoadingIntMap(@NotNull Function<Integer, V> loader) {
|
|
||||||
super();
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoadingIntMap(int expectedSize, @NotNull Function<Integer, V> loader) {
|
|
||||||
super(expectedSize);
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function<Integer, V> loader) {
|
|
||||||
super(expectedSize, loadFactor);
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public V get(int key) {
|
|
||||||
V res = super.get(key);
|
|
||||||
if (res == null) {
|
|
||||||
res = loader.apply(key);
|
|
||||||
if (res != null) {
|
|
||||||
put(key, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Due to java stuff, you will need to cast it to (Function) for some cases
|
|
||||||
*
|
|
||||||
* @param <T> Type
|
|
||||||
*/
|
|
||||||
public abstract static class Feeder <T> implements Function<T, T> {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public T apply(@Nullable Object input) {
|
|
||||||
return apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public abstract T apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,368 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.util;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.IdentityHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to pass a Loader function that when a key is accessed that doesn't exists,
|
|
||||||
* automatically loads the entry into the map by calling the loader Function.
|
|
||||||
*
|
|
||||||
* .get() Will only return null if the Loader can return null.
|
|
||||||
*
|
|
||||||
* You may pass any backing Map to use.
|
|
||||||
*
|
|
||||||
* This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed.
|
|
||||||
*
|
|
||||||
* Do not wrap the backing map with Collections.synchronizedMap.
|
|
||||||
*
|
|
||||||
* @param <K> Key
|
|
||||||
* @param <V> Value
|
|
||||||
*/
|
|
||||||
public class LoadingMap <K, V> extends AbstractMap<K, V> {
|
|
||||||
private final Map<K, V> backingMap;
|
|
||||||
private final java.util.function.Function<K, V> loader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using specified loader and backing map
|
|
||||||
* @param backingMap Map to wrap
|
|
||||||
* @param loader Loader
|
|
||||||
*/
|
|
||||||
public LoadingMap(@NotNull Map<K, V> backingMap, @NotNull java.util.function.Function<K, V> loader) {
|
|
||||||
this.backingMap = backingMap;
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new LoadingMap with the specified map and loader
|
|
||||||
*
|
|
||||||
* @param backingMap Actual map being used.
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> of(@NotNull Map<K, V> backingMap, @NotNull Function<K, V> loader) {
|
|
||||||
return new LoadingMap<>(backingMap, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a LoadingMap with an auto instantiating loader.
|
|
||||||
*
|
|
||||||
* Will auto construct class of of Value when not found
|
|
||||||
*
|
|
||||||
* Since this uses Reflection, It is more effecient to define your own static loader
|
|
||||||
* than using this helper, but if performance is not critical, this is easier.
|
|
||||||
*
|
|
||||||
* @param backingMap Actual map being used.
|
|
||||||
* @param keyClass Class used for the K generic
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newAutoMap(@NotNull Map<K, V> backingMap, @Nullable final Class<? extends K> keyClass,
|
|
||||||
@NotNull final Class<? extends V> valueClass) {
|
|
||||||
return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Creates a LoadingMap with an auto instantiating loader.
|
|
||||||
*
|
|
||||||
* Will auto construct class of of Value when not found
|
|
||||||
*
|
|
||||||
* Since this uses Reflection, It is more effecient to define your own static loader
|
|
||||||
* than using this helper, but if performance is not critical, this is easier.
|
|
||||||
*
|
|
||||||
* @param backingMap Actual map being used.
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newAutoMap(@NotNull Map<K, V> backingMap,
|
|
||||||
@NotNull final Class<? extends V> valueClass) {
|
|
||||||
return newAutoMap(backingMap, null, valueClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #newAutoMap
|
|
||||||
*
|
|
||||||
* new Auto initializing map using a HashMap.
|
|
||||||
*
|
|
||||||
* @param keyClass Class used for the K generic
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashAutoMap(@Nullable final Class<? extends K> keyClass, @NotNull final Class<? extends V> valueClass) {
|
|
||||||
return newAutoMap(new HashMap<>(), keyClass, valueClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #newAutoMap
|
|
||||||
*
|
|
||||||
* new Auto initializing map using a HashMap.
|
|
||||||
*
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashAutoMap(@NotNull final Class<? extends V> valueClass) {
|
|
||||||
return newHashAutoMap(null, valueClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #newAutoMap
|
|
||||||
*
|
|
||||||
* new Auto initializing map using a HashMap.
|
|
||||||
*
|
|
||||||
* @param keyClass Class used for the K generic
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param initialCapacity Initial capacity to use
|
|
||||||
* @param loadFactor Load factor to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashAutoMap(@Nullable final Class<? extends K> keyClass, @NotNull final Class<? extends V> valueClass, int initialCapacity, float loadFactor) {
|
|
||||||
return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #newAutoMap
|
|
||||||
*
|
|
||||||
* new Auto initializing map using a HashMap.
|
|
||||||
*
|
|
||||||
* @param valueClass Class used for the V generic
|
|
||||||
* @param initialCapacity Initial capacity to use
|
|
||||||
* @param loadFactor Load factor to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map that auto instantiates on .get()
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashAutoMap(@NotNull final Class<? extends V> valueClass, int initialCapacity, float loadFactor) {
|
|
||||||
return newHashAutoMap(null, valueClass, initialCapacity, loadFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using a HashMap
|
|
||||||
*
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader) {
|
|
||||||
return new LoadingMap<>(new HashMap<>(), loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using a HashMap
|
|
||||||
*
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param initialCapacity Initial capacity to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader, int initialCapacity) {
|
|
||||||
return new LoadingMap<>(new HashMap<>(initialCapacity), loader);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using a HashMap
|
|
||||||
*
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param initialCapacity Initial capacity to use
|
|
||||||
* @param loadFactor Load factor to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader, int initialCapacity, float loadFactor) {
|
|
||||||
return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using an Identity HashMap
|
|
||||||
*
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newIdentityHashMap(@NotNull Function<K, V> loader) {
|
|
||||||
return new LoadingMap<>(new IdentityHashMap<>(), loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes an auto loading map using an Identity HashMap
|
|
||||||
*
|
|
||||||
* @param loader Loader to use
|
|
||||||
* @param initialCapacity Initial capacity to use
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> newIdentityHashMap(@NotNull Function<K, V> loader, int initialCapacity) {
|
|
||||||
return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {return backingMap.size();}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {return backingMap.isEmpty();}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public V get(@Nullable Object key) {
|
|
||||||
V v = backingMap.get(key);
|
|
||||||
if (v != null) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
return backingMap.computeIfAbsent((K) key, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public V remove(@Nullable Object key) {return backingMap.remove(key);}
|
|
||||||
|
|
||||||
public void putAll(@NotNull Map<? extends K, ? extends V> m) {backingMap.putAll(m);}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {backingMap.clear();}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Set<K> keySet() {return backingMap.keySet();}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Collection<V> values() {return backingMap.values();}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object o) {return backingMap.equals(o);}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {return backingMap.hashCode();}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Set<Entry<K, V>> entrySet() {
|
|
||||||
return backingMap.entrySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public LoadingMap<K, V> clone() {
|
|
||||||
return new LoadingMap<>(backingMap, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AutoInstantiatingLoader<K, V> implements Function<K, V> {
|
|
||||||
final Constructor<? extends V> constructor;
|
|
||||||
private final Class<? extends V> valueClass;
|
|
||||||
|
|
||||||
AutoInstantiatingLoader(@Nullable Class<? extends K> keyClass, @NotNull Class<? extends V> valueClass) {
|
|
||||||
try {
|
|
||||||
this.valueClass = valueClass;
|
|
||||||
if (keyClass != null) {
|
|
||||||
constructor = valueClass.getConstructor(keyClass);
|
|
||||||
} else {
|
|
||||||
constructor = null;
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public V apply(@Nullable K input) {
|
|
||||||
try {
|
|
||||||
return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ExceptionInInitializerError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return super.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object object) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Due to java stuff, you will need to cast it to (Function) for some cases
|
|
||||||
*
|
|
||||||
* @param <T> Type
|
|
||||||
*/
|
|
||||||
public abstract static class Feeder <T> implements Function<T, T> {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public T apply(@Nullable Object input) {
|
|
||||||
return apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public abstract T apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package co.aikar.util;
|
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result.
|
|
||||||
*
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
*/
|
|
||||||
public class MRUMapCache<K, V> extends AbstractMap<K, V> {
|
|
||||||
final Map<K, V> backingMap;
|
|
||||||
Object cacheKey;
|
|
||||||
V cacheValue;
|
|
||||||
public MRUMapCache(@NotNull final Map<K, V> backingMap) {
|
|
||||||
this.backingMap = backingMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {return backingMap.size();}
|
|
||||||
|
|
||||||
public boolean isEmpty() {return backingMap.isEmpty();}
|
|
||||||
|
|
||||||
public boolean containsKey(@Nullable Object key) {
|
|
||||||
return key != null && key.equals(cacheKey) || backingMap.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsValue(@Nullable Object value) {
|
|
||||||
return value != null && value == cacheValue || backingMap.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public V get(@Nullable Object key) {
|
|
||||||
if (cacheKey != null && cacheKey.equals(key)) {
|
|
||||||
return cacheValue;
|
|
||||||
}
|
|
||||||
cacheKey = key;
|
|
||||||
return cacheValue = backingMap.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public V put(@Nullable K key, @Nullable V value) {
|
|
||||||
cacheKey = key;
|
|
||||||
return cacheValue = backingMap.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public V remove(@Nullable Object key) {
|
|
||||||
if (key != null && key.equals(cacheKey)) {
|
|
||||||
cacheKey = null;
|
|
||||||
}
|
|
||||||
return backingMap.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(@NotNull Map<? extends K, ? extends V> m) {backingMap.putAll(m);}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
cacheKey = null;
|
|
||||||
cacheValue = null;
|
|
||||||
backingMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Set<K> keySet() {return backingMap.keySet();}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Collection<V> values() {return backingMap.values();}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Set<Map.Entry<K, V>> entrySet() {return backingMap.entrySet();}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps the specified map with a most recently used cache
|
|
||||||
*
|
|
||||||
* @param map Map to be wrapped
|
|
||||||
* @param <K> Key Type of the Map
|
|
||||||
* @param <V> Value Type of the Map
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static <K, V> Map<K, V> of(@NotNull Map<K, V> map) {
|
|
||||||
return new MRUMapCache<K, V>(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import org.bukkit.World;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumeration of different heightmap types maintained by the server. Generally using these maps is much faster
|
|
||||||
* than using an iterative search for a block in a given x, z coordinate.
|
|
||||||
*/
|
|
||||||
public enum HeightmapType {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The highest block used for lighting in the world. Also the block returned by {@link World#getHighestBlockYAt(int, int)}}
|
|
||||||
*/
|
|
||||||
LIGHT_BLOCKING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References the highest block in the world.
|
|
||||||
*/
|
|
||||||
ANY,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References the highest solid block in a world.
|
|
||||||
*/
|
|
||||||
SOLID,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References the highest solid or liquid block in a world.
|
|
||||||
*/
|
|
||||||
SOLID_OR_LIQUID,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References the highest solid or liquid block in a world, excluding leaves.
|
|
||||||
*/
|
|
||||||
SOLID_OR_LIQUID_NO_LEAVES;
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.Tag;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class MaterialSetTag implements Tag<Material> {
|
|
||||||
|
|
||||||
private final NamespacedKey key;
|
|
||||||
private final Set<Material> materials;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use NamespacedKey version of constructor
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public MaterialSetTag(@NotNull Predicate<Material> filter) {
|
|
||||||
this(null, Stream.of(Material.values()).filter(filter).collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use NamespacedKey version of constructor
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public MaterialSetTag(@NotNull Collection<Material> materials) {
|
|
||||||
this(null, materials);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use NamespacedKey version of constructor
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public MaterialSetTag(@NotNull Material... materials) {
|
|
||||||
this(null, materials);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Predicate<Material> filter) {
|
|
||||||
this(key, Stream.of(Material.values()).filter(filter).collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Material... materials) {
|
|
||||||
this(key, Lists.newArrayList(materials));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection<Material> materials) {
|
|
||||||
this.key = key != null ? key : NamespacedKey.randomKey();
|
|
||||||
this.materials = Sets.newEnumSet(materials, Material.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public NamespacedKey getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag add(@NotNull Tag<Material>... tags) {
|
|
||||||
for (Tag<Material> tag : tags) {
|
|
||||||
add(tag.getValues());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag add(@NotNull MaterialSetTag... tags) {
|
|
||||||
for (Tag<Material> tag : tags) {
|
|
||||||
add(tag.getValues());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag add(@NotNull Material... material) {
|
|
||||||
this.materials.addAll(Lists.newArrayList(material));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag add(@NotNull Collection<Material> materials) {
|
|
||||||
this.materials.addAll(materials);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag contains(@NotNull String with) {
|
|
||||||
return add(mat -> mat.name().contains(with));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag endsWith(@NotNull String with) {
|
|
||||||
return add(mat -> mat.name().endsWith(with));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag startsWith(@NotNull String with) {
|
|
||||||
return add(mat -> mat.name().startsWith(with));
|
|
||||||
}
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag add(@NotNull Predicate<Material> filter) {
|
|
||||||
add(Stream.of(Material.values()).filter(((Predicate<Material>) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList()));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag not(@NotNull MaterialSetTag tags) {
|
|
||||||
not(tags.getValues());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag not(@NotNull Material... material) {
|
|
||||||
this.materials.removeAll(Lists.newArrayList(material));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag not(@NotNull Collection<Material> materials) {
|
|
||||||
this.materials.removeAll(materials);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag not(@NotNull Predicate<Material> filter) {
|
|
||||||
not(Stream.of(Material.values()).filter(((Predicate<Material>) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList()));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag notEndsWith(@NotNull String with) {
|
|
||||||
return not(mat -> mat.name().endsWith(with));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag notStartsWith(@NotNull String with) {
|
|
||||||
return not(mat -> mat.name().startsWith(with));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Set<Material> getValues() {
|
|
||||||
return this.materials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged(@NotNull BlockData block) {
|
|
||||||
return isTagged(block.getMaterial());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged(@NotNull BlockState block) {
|
|
||||||
return isTagged(block.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged(@NotNull Block block) {
|
|
||||||
return isTagged(block.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged(@NotNull ItemStack item) {
|
|
||||||
return isTagged(item.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged(@NotNull Material material) {
|
|
||||||
return this.materials.contains(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public MaterialSetTag ensureSize(@NotNull String label, int size) {
|
|
||||||
long actual = this.materials.stream().filter(((Predicate<Material>) Material::isLegacy).negate()).count();
|
|
||||||
if (size != actual) {
|
|
||||||
throw new IllegalStateException(label + " - Expected " + size + " materials, got " + actual);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,374 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.Tag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a collection tags to identify materials that share common properties.
|
|
||||||
* Will map to minecraft for missing tags, as well as custom ones that may be useful.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"NonFinalUtilityClass", "unused", "WeakerAccess"})
|
|
||||||
public class MaterialTags {
|
|
||||||
|
|
||||||
private static NamespacedKey keyFor(String key) {
|
|
||||||
//noinspection deprecation
|
|
||||||
return new NamespacedKey("paper", key + "_settag");
|
|
||||||
}
|
|
||||||
public static final MaterialSetTag ARROWS = new MaterialSetTag(keyFor("arrows"))
|
|
||||||
.endsWith("ARROW")
|
|
||||||
.ensureSize("ARROWS", 3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cover all 16 colors of beds.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds"))
|
|
||||||
.endsWith("_BED")
|
|
||||||
.ensureSize("BEDS", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all bucket items.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets"))
|
|
||||||
.endsWith("BUCKET")
|
|
||||||
.ensureSize("BUCKETS", 8);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers coal and charcoal.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals"))
|
|
||||||
.add(Material.COAL, Material.CHARCOAL);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers both cobblestone wall variants.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls"))
|
|
||||||
.endsWith("COBBLESTONE_WALL")
|
|
||||||
.ensureSize("COBBLESTONE_WALLS", 2);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers both cobblestone and mossy Cobblestone.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones"))
|
|
||||||
.add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 colors of concrete.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes"))
|
|
||||||
.endsWith("_CONCRETE")
|
|
||||||
.ensureSize("CONCRETES", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 colors of concrete powder.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder"))
|
|
||||||
.endsWith("_CONCRETE_POWDER")
|
|
||||||
.ensureSize("CONCRETE_POWDER", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the two types of cooked fish.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag COOKED_FISH = new MaterialSetTag(keyFor("cooked_fish"))
|
|
||||||
.add(Material.COOKED_COD, Material.COOKED_SALMON);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 dyes.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes"))
|
|
||||||
.endsWith("_DYE")
|
|
||||||
.ensureSize("DYES", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 6 wood variants of gates.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates"))
|
|
||||||
.endsWith("_GATE")
|
|
||||||
.ensureSize("FENCE_GATES", 6);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 6 wood variants and nether brick fence.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences"))
|
|
||||||
.endsWith("_FENCE")
|
|
||||||
.ensureSize("FENCES", 7);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 4 variants of fish buckets.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag(keyFor("fish_buckets"))
|
|
||||||
.add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the non-colored glass and 16 stained glass (not panes).
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass"))
|
|
||||||
.endsWith("_GLASS")
|
|
||||||
.add(Material.GLASS)
|
|
||||||
.ensureSize("GLASS", 17);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the non-colored glass panes and 16 stained glass panes (panes only).
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes"))
|
|
||||||
.endsWith("GLASS_PANE")
|
|
||||||
.ensureSize("GLASS_PANES", 17);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 glazed terracotta blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta"))
|
|
||||||
.endsWith("GLAZED_TERRACOTTA")
|
|
||||||
.ensureSize("GLAZED_TERRACOTTA", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 16 colors of stained terracotta.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag(keyFor("stained_terracotta"))
|
|
||||||
.endsWith("TERRACOTTA")
|
|
||||||
.not(Material.TERRACOTTA)
|
|
||||||
.notEndsWith("GLAZED_TERRACOTTA")
|
|
||||||
.ensureSize("STAINED_TERRACOTTA", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers terracotta along with the 16 stained variants.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta"))
|
|
||||||
.endsWith("TERRACOTTA")
|
|
||||||
.ensureSize("TERRACOTTA", 33);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers both golden apples.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples"))
|
|
||||||
.endsWith("GOLDEN_APPLE")
|
|
||||||
.ensureSize("GOLDEN_APPLES", 2);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of horse armor.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors"))
|
|
||||||
.endsWith("_HORSE_ARMOR")
|
|
||||||
.ensureSize("HORSE_ARMORS", 4);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 6 variants of infested blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks"))
|
|
||||||
.startsWith("INFESTED_")
|
|
||||||
.ensureSize("INFESTED_BLOCKS", 6);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of mushroom blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag(keyFor("mushroom_blocks"))
|
|
||||||
.endsWith("MUSHROOM_BLOCK")
|
|
||||||
.add(Material.MUSHROOM_STEM)
|
|
||||||
.ensureSize("MUSHROOM_BLOCKS", 3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers both mushrooms.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms"))
|
|
||||||
.add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 12 music disc items.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs"))
|
|
||||||
.startsWith("MUSIC_DISC_")
|
|
||||||
.ensureSize("MUSIC_DISCS", 12);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 8 ores.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores"))
|
|
||||||
.endsWith("_ORE")
|
|
||||||
.ensureSize("ORES", 8);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all piston typed items and blocks including the piston head and moving piston.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PISTONS = new MaterialSetTag(keyFor("pistons"))
|
|
||||||
.contains("PISTON")
|
|
||||||
.ensureSize("PISTONS", 4);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all potato items.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes"))
|
|
||||||
.endsWith("POTATO")
|
|
||||||
.ensureSize("POTATOES", 3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 6 wooden pressure plates and the 2 weighted pressure plates and 1 stone pressure plate.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates"))
|
|
||||||
.endsWith("_PRESSURE_PLATE")
|
|
||||||
.ensureSize("PRESSURE_PLATES", 9);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of prismarine blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine"))
|
|
||||||
.add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of prismarine slabs.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag(keyFor("prismarine_slabs"))
|
|
||||||
.add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of prismarine stairs.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag(keyFor("prismarine_stairs"))
|
|
||||||
.add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 3 variants of pumpkins.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins"))
|
|
||||||
.add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 4 variants of quartz blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag(keyFor("quartz_blocks"))
|
|
||||||
.add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all uncooked fish items.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag RAW_FISH = new MaterialSetTag(keyFor("raw_fish"))
|
|
||||||
.add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 4 variants of red sandstone blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones"))
|
|
||||||
.endsWith("RED_SANDSTONE")
|
|
||||||
.ensureSize("RED_SANDSTONES", 4);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the 4 variants of sandstone blocks.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag SANDSTONES = new MaterialSetTag(keyFor("sandstones"))
|
|
||||||
.add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers sponge and wet sponge.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges"))
|
|
||||||
.endsWith("SPONGE")
|
|
||||||
.ensureSize("SPONGES", 2);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers the non-colored and 16 colored shulker boxes.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes"))
|
|
||||||
.endsWith("SHULKER_BOX")
|
|
||||||
.ensureSize("SHULKER_BOXES", 17);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers zombie, creeper, skeleton, dragon, and player heads.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag SKULLS = new MaterialSetTag(keyFor("skulls"))
|
|
||||||
.endsWith("_HEAD")
|
|
||||||
.endsWith("_SKULL")
|
|
||||||
.not(Material.PISTON_HEAD)
|
|
||||||
.ensureSize("SKULLS", 12);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all spawn egg items.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs"))
|
|
||||||
.endsWith("_SPAWN_EGG")
|
|
||||||
.ensureSize("SPAWN_EGGS", 58);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 colors of stained glass.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass"))
|
|
||||||
.endsWith("_STAINED_GLASS")
|
|
||||||
.ensureSize("STAINED_GLASS", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 16 colors of stained glass panes.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag(keyFor("stained_glass_panes"))
|
|
||||||
.endsWith("STAINED_GLASS_PANE")
|
|
||||||
.ensureSize("STAINED_GLASS_PANES", 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 7 variants of trapdoors.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors"))
|
|
||||||
.endsWith("_TRAPDOOR")
|
|
||||||
.ensureSize("TRAPDOORS", 7);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 6 wood variants of fences.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag(keyFor("wooden_fences"))
|
|
||||||
.endsWith("_FENCE")
|
|
||||||
.not(Material.NETHER_BRICK_FENCE)
|
|
||||||
.ensureSize("WOODEN_FENCES", 6);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covers all 6 wood variants of trapdoors.
|
|
||||||
*/
|
|
||||||
public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors"))
|
|
||||||
.endsWith("_TRAPDOOR")
|
|
||||||
.not(Material.IRON_TRAPDOOR)
|
|
||||||
.ensureSize("WOODEN_TRAPDOORS", 6);
|
|
||||||
|
|
||||||
public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates"))
|
|
||||||
.endsWith("_GATE")
|
|
||||||
.ensureSize("WOODEN_GATES", 6);
|
|
||||||
|
|
||||||
public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur"))
|
|
||||||
.startsWith("PURPUR_")
|
|
||||||
.ensureSize("PURPUR", 4);
|
|
||||||
|
|
||||||
public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs"))
|
|
||||||
.endsWith("_SIGN")
|
|
||||||
.ensureSize("SIGNS", 12);
|
|
||||||
|
|
||||||
public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch"))
|
|
||||||
.add(Material.TORCH, Material.WALL_TORCH)
|
|
||||||
.ensureSize("TORCH", 2);
|
|
||||||
|
|
||||||
public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch"))
|
|
||||||
.add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH)
|
|
||||||
.ensureSize("REDSTONE_TORCH", 2);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static final MaterialSetTag COLORABLE = new MaterialSetTag(keyFor("colorable"))
|
|
||||||
.add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS);
|
|
||||||
//.ensureSize("COLORABLE", 81); unit test don't have the vanilla item tags, so counts don't line up for real
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements
|
|
||||||
* or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements
|
|
||||||
*
|
|
||||||
* Namespaces may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, and hyphens.
|
|
||||||
* <p>
|
|
||||||
* Keys may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, hyphens, and forward slashes.
|
|
||||||
* <p>
|
|
||||||
* You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey}
|
|
||||||
* or {@link com.destroystokyo.paper.NamespacedTag} as needed instead.
|
|
||||||
*/
|
|
||||||
public interface Namespaced {
|
|
||||||
/**
|
|
||||||
* Gets the namespace this resource is a part of
|
|
||||||
* <p>
|
|
||||||
* This is contractually obligated to only contain lowercase alphanumeric characters,
|
|
||||||
* periods, underscores, and hyphens.
|
|
||||||
*
|
|
||||||
* @return resource namespace
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
String getNamespace();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the key corresponding to this resource
|
|
||||||
* <p>
|
|
||||||
* This is contractually obligated to only contain lowercase alphanumeric characters,
|
|
||||||
* periods, underscores, hyphens, and forward slashes.
|
|
||||||
*
|
|
||||||
* @return resource key
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
String getKey();
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace
|
|
||||||
* and a key.
|
|
||||||
* <p>
|
|
||||||
* Namespaces may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, and hyphens.
|
|
||||||
* <p>
|
|
||||||
* Keys may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, hyphens, and forward slashes.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// Paper - entire class, based on org.bukkit.NamespacedKey
|
|
||||||
public final class NamespacedTag implements com.destroystokyo.paper.Namespaced {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The namespace representing all inbuilt keys.
|
|
||||||
*/
|
|
||||||
public static final String MINECRAFT = "minecraft";
|
|
||||||
/**
|
|
||||||
* The namespace representing all keys generated by Bukkit for backwards
|
|
||||||
* compatibility measures.
|
|
||||||
*/
|
|
||||||
public static final String BUKKIT = "bukkit";
|
|
||||||
//
|
|
||||||
private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+");
|
|
||||||
private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+");
|
|
||||||
//
|
|
||||||
private final String namespace;
|
|
||||||
private final String key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a key in a specific namespace.
|
|
||||||
*
|
|
||||||
* @param namespace String representing a grouping of keys
|
|
||||||
* @param key Name for this specific key
|
|
||||||
* @deprecated should never be used by plugins, for internal use only!!
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public NamespacedTag(@NotNull String namespace, @NotNull String key) {
|
|
||||||
Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
|
|
||||||
Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key);
|
|
||||||
|
|
||||||
this.namespace = namespace;
|
|
||||||
this.key = key;
|
|
||||||
|
|
||||||
String string = toString();
|
|
||||||
Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a key in the plugin's namespace.
|
|
||||||
* <p>
|
|
||||||
* Namespaces may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, and hyphens.
|
|
||||||
* <p>
|
|
||||||
* Keys may only contain lowercase alphanumeric characters, periods,
|
|
||||||
* underscores, hyphens, and forward slashes.
|
|
||||||
*
|
|
||||||
* @param plugin the plugin to use for the namespace
|
|
||||||
* @param key the key to create
|
|
||||||
*/
|
|
||||||
public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) {
|
|
||||||
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
|
|
||||||
Preconditions.checkArgument(key != null, "Key cannot be null");
|
|
||||||
|
|
||||||
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
|
|
||||||
this.key = key.toLowerCase().toLowerCase(Locale.ROOT);
|
|
||||||
|
|
||||||
// Check validity after normalization
|
|
||||||
Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
|
|
||||||
Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
|
|
||||||
|
|
||||||
String string = toString();
|
|
||||||
Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public String getNamespace() {
|
|
||||||
return namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 7;
|
|
||||||
hash = 47 * hash + this.namespace.hashCode();
|
|
||||||
hash = 47 * hash + this.key.hashCode();
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final NamespacedTag other = (NamespacedTag) obj;
|
|
||||||
return this.namespace.equals(other.namespace) && this.key.equals(other.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "#" + this.namespace + ":" + this.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new random key in the {@link #BUKKIT} namespace.
|
|
||||||
*
|
|
||||||
* @return new key
|
|
||||||
* @deprecated should never be used by plugins, for internal use only!!
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static NamespacedTag randomKey() {
|
|
||||||
return new NamespacedTag(BUKKIT, UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a key in the Minecraft namespace.
|
|
||||||
*
|
|
||||||
* @param key the key to use
|
|
||||||
* @return new key in the Minecraft namespace
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static NamespacedTag minecraft(@NotNull String key) {
|
|
||||||
return new NamespacedTag(MINECRAFT, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,478 +0,0 @@
|
|||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.bukkit.Color;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Particle;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.util.NumberConversions;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helps prepare a particle to be sent to players.
|
|
||||||
*
|
|
||||||
* Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API
|
|
||||||
*/
|
|
||||||
public class ParticleBuilder {
|
|
||||||
|
|
||||||
private Particle particle;
|
|
||||||
private List<Player> receivers;
|
|
||||||
private Player source;
|
|
||||||
private Location location;
|
|
||||||
private int count = 1;
|
|
||||||
private double offsetX = 0, offsetY = 0, offsetZ = 0;
|
|
||||||
private double extra = 1;
|
|
||||||
private Object data;
|
|
||||||
private boolean force = true;
|
|
||||||
|
|
||||||
public ParticleBuilder(@NotNull Particle particle) {
|
|
||||||
this.particle = particle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the particle to all receiving players (or all). This method is safe to use
|
|
||||||
* Asynchronously
|
|
||||||
*
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder spawn() {
|
|
||||||
if (this.location == null) {
|
|
||||||
throw new IllegalStateException("Please specify location for this particle");
|
|
||||||
}
|
|
||||||
location.getWorld().spawnParticle(particle, receivers, source,
|
|
||||||
location.getX(), location.getY(), location.getZ(),
|
|
||||||
count, offsetX, offsetY, offsetZ, extra, data, force
|
|
||||||
);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The particle going to be sent
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Particle particle() {
|
|
||||||
return particle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes what particle will be sent
|
|
||||||
*
|
|
||||||
* @param particle The particle
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder particle(@NotNull Particle particle) {
|
|
||||||
this.particle = particle;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List of players who will receive the particle, or null for all in world
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public List<Player> receivers() {
|
|
||||||
return receivers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example use:
|
|
||||||
*
|
|
||||||
* builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); }
|
|
||||||
*
|
|
||||||
* @return If this particle is going to be sent to someone
|
|
||||||
*/
|
|
||||||
public boolean hasReceivers() {
|
|
||||||
return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || (
|
|
||||||
receivers != null && !receivers.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends this particle to all players in the world. This is rather silly and you should likely not
|
|
||||||
* be doing this.
|
|
||||||
*
|
|
||||||
* Just be a logical person and use receivers by radius or collection.
|
|
||||||
*
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder allPlayers() {
|
|
||||||
this.receivers = null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param receivers List of players to receive this particle, or null for all players in the
|
|
||||||
* world
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(@Nullable List<Player> receivers) {
|
|
||||||
// Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars
|
|
||||||
// TODO: deprecate?
|
|
||||||
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param receivers List of players to receive this particle, or null for all players in the
|
|
||||||
* world
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(@Nullable Collection<Player> receivers) {
|
|
||||||
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param receivers List of players to be receive this particle, or null for all players in the
|
|
||||||
* world
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(@Nullable Player... receivers) {
|
|
||||||
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all players within a cuboid selection around the particle location, within the
|
|
||||||
* specified bounding box. If you want a more spherical check, see {@link #receivers(int,
|
|
||||||
* boolean)}
|
|
||||||
*
|
|
||||||
* @param radius amount to add on all axis
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(int radius) {
|
|
||||||
return receivers(radius, radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all players within the specified radius around the particle location. If byDistance is
|
|
||||||
* false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
|
|
||||||
* true, radius is tested by distance in a spherical shape
|
|
||||||
*
|
|
||||||
* @param radius amount to add on each axis
|
|
||||||
* @param byDistance true to use a spherical radius, false to use a cuboid
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(int radius, boolean byDistance) {
|
|
||||||
if (!byDistance) {
|
|
||||||
return receivers(radius, radius, radius);
|
|
||||||
} else {
|
|
||||||
this.receivers = Lists.newArrayList();
|
|
||||||
for (Player nearbyPlayer : location.getWorld()
|
|
||||||
.getNearbyPlayers(location, radius, radius, radius)) {
|
|
||||||
Location loc = nearbyPlayer.getLocation();
|
|
||||||
double x = NumberConversions.square(location.getX() - loc.getX());
|
|
||||||
double y = NumberConversions.square(location.getY() - loc.getY());
|
|
||||||
double z = NumberConversions.square(location.getZ() - loc.getZ());
|
|
||||||
if (Math.sqrt(x + y + z) > radius) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.receivers.add(nearbyPlayer);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all players within a cuboid selection around the particle location, within the
|
|
||||||
* specified bounding box. Allows specifying a different Y size than X and Z If you want a more
|
|
||||||
* cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check,
|
|
||||||
* see {@link #receivers(int, boolean)}
|
|
||||||
*
|
|
||||||
* @param xzRadius amount to add on the x/z axis
|
|
||||||
* @param yRadius amount to add on the y axis
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(int xzRadius, int yRadius) {
|
|
||||||
return receivers(xzRadius, yRadius, xzRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all players within the specified radius around the particle location. If byDistance is
|
|
||||||
* false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
|
|
||||||
* true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape.
|
|
||||||
*
|
|
||||||
* @param xzRadius amount to add on the x/z axis
|
|
||||||
* @param yRadius amount to add on the y axis
|
|
||||||
* @param byDistance true to use a cylinder shape, false to use cuboid
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) {
|
|
||||||
if (!byDistance) {
|
|
||||||
return receivers(xzRadius, yRadius, xzRadius);
|
|
||||||
} else {
|
|
||||||
this.receivers = Lists.newArrayList();
|
|
||||||
for (Player nearbyPlayer : location.getWorld()
|
|
||||||
.getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) {
|
|
||||||
Location loc = nearbyPlayer.getLocation();
|
|
||||||
if (Math.abs(loc.getY() - this.location.getY()) > yRadius) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
double x = NumberConversions.square(location.getX() - loc.getX());
|
|
||||||
double z = NumberConversions.square(location.getZ() - loc.getZ());
|
|
||||||
if (x + z > NumberConversions.square(xzRadius)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.receivers.add(nearbyPlayer);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all players within a cuboid selection around the particle location, within the
|
|
||||||
* specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int,
|
|
||||||
* boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)}
|
|
||||||
*
|
|
||||||
* @param xRadius amount to add on the x axis
|
|
||||||
* @param yRadius amount to add on the y axis
|
|
||||||
* @param zRadius amount to add on the z axis
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) {
|
|
||||||
if (location == null) {
|
|
||||||
throw new IllegalStateException("Please set location first");
|
|
||||||
}
|
|
||||||
return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The player considered the source of this particle (for Visibility concerns), or null
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Player source() {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the source of this particle for visibility concerns (Vanish API)
|
|
||||||
*
|
|
||||||
* @param source The player who is considered the source
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder source(@Nullable Player source) {
|
|
||||||
this.source = source;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Location of where the particle will spawn
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Location location() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the location of where to spawn the particle
|
|
||||||
*
|
|
||||||
* @param location The location of the particle
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder location(@NotNull Location location) {
|
|
||||||
this.location = location.clone();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the location of where to spawn the particle
|
|
||||||
*
|
|
||||||
* @param world World to spawn particle in
|
|
||||||
* @param x X location
|
|
||||||
* @param y Y location
|
|
||||||
* @param z Z location
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder location(@NotNull World world, double x, double y, double z) {
|
|
||||||
this.location = new Location(world, x, y, z);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Number of particles to spawn
|
|
||||||
*/
|
|
||||||
public int count() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number of particles to spawn
|
|
||||||
*
|
|
||||||
* @param count Number of particles
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder count(int count) {
|
|
||||||
this.count = count;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Particle offset X. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @return Particle offset X.
|
|
||||||
*/
|
|
||||||
public double offsetX() {
|
|
||||||
return offsetX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Particle offset Y. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @return Particle offset Y.
|
|
||||||
*/
|
|
||||||
public double offsetY() {
|
|
||||||
return offsetY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Particle offset Z. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @return Particle offset Z.
|
|
||||||
*/
|
|
||||||
public double offsetZ() {
|
|
||||||
return offsetZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle offset. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @param offsetX Particle offset X
|
|
||||||
* @param offsetY Particle offset Y
|
|
||||||
* @param offsetZ Particle offset Z
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) {
|
|
||||||
this.offsetX = offsetX;
|
|
||||||
this.offsetY = offsetY;
|
|
||||||
this.offsetZ = offsetZ;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Particle extra data. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @return the extra particle data
|
|
||||||
*/
|
|
||||||
public double extra() {
|
|
||||||
return extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle extra data. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @param extra the extra particle data
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder extra(double extra) {
|
|
||||||
this.extra = extra;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the particle custom data. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @param <T> The Particle data type
|
|
||||||
* @return the ParticleData for this particle
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public <T> T data() {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (T) data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle custom data. Varies by particle on how this is used
|
|
||||||
*
|
|
||||||
* @param data The new particle data
|
|
||||||
* @param <T> The Particle data type
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public <T> ParticleBuilder data(@Nullable T data) {
|
|
||||||
this.data = data;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the particle is forcefully shown to the player. If forced, the particle will show
|
|
||||||
* faraway, as far as the player's view distance allows. If false, the particle will show
|
|
||||||
* according to the client's particle settings.
|
|
||||||
*
|
|
||||||
* @param force true to force, false for normal
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder force(boolean force) {
|
|
||||||
this.force = force;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle Color. Only valid for REDSTONE.
|
|
||||||
*
|
|
||||||
* @param color the new particle color
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder color(@Nullable Color color) {
|
|
||||||
return color(color, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle Color and size. Only valid for REDSTONE.
|
|
||||||
*
|
|
||||||
* @param color the new particle color
|
|
||||||
* @param size the size of the particle
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder color(@Nullable Color color, float size) {
|
|
||||||
if (particle != Particle.REDSTONE && color != null) {
|
|
||||||
throw new IllegalStateException("Color may only be set on REDSTONE");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't officially support reusing these objects, but here we go
|
|
||||||
if (color == null) {
|
|
||||||
if (data instanceof Particle.DustOptions) {
|
|
||||||
return data(null);
|
|
||||||
} else {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data(new Particle.DustOptions(color, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the particle Color.
|
|
||||||
* Only valid for REDSTONE.
|
|
||||||
* @param r red color component
|
|
||||||
* @param g green color component
|
|
||||||
* @param b blue color component
|
|
||||||
* @return a reference to this object.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ParticleBuilder color(int r, int g, int b) {
|
|
||||||
return color(Color.fromRGB(r, g, b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
package com.destroystokyo.paper;
|
|
||||||
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a title to may be sent to a {@link Player}.
|
|
||||||
*
|
|
||||||
* <p>A title can be sent without subtitle text.</p>
|
|
||||||
*/
|
|
||||||
public final class Title {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default number of ticks for the title to fade in.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_FADE_IN = 20;
|
|
||||||
/**
|
|
||||||
* The default number of ticks for the title to stay.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_STAY = 200;
|
|
||||||
/**
|
|
||||||
* The default number of ticks for the title to fade out.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_FADE_OUT = 20;
|
|
||||||
|
|
||||||
private final BaseComponent[] title;
|
|
||||||
private final BaseComponent[] subtitle;
|
|
||||||
private final int fadeIn;
|
|
||||||
private final int stay;
|
|
||||||
private final int fadeOut;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values and no subtitle.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
public Title(@NotNull BaseComponent title) {
|
|
||||||
this(title, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values and no subtitle.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
public Title(@NotNull BaseComponent[] title) {
|
|
||||||
this(title, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values and no subtitle.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
public Title(@NotNull String title) {
|
|
||||||
this(title, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
*/
|
|
||||||
public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) {
|
|
||||||
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
*/
|
|
||||||
public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) {
|
|
||||||
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title with the default time values.
|
|
||||||
*
|
|
||||||
* <p>Times use default values.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
*/
|
|
||||||
public Title(@NotNull String title, @Nullable String subtitle) {
|
|
||||||
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new title.
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
* @param fadeIn the number of ticks for the title to fade in
|
|
||||||
* @param stay the number of ticks for the title to stay on screen
|
|
||||||
* @param fadeOut the number of ticks for the title to fade out
|
|
||||||
* @throws IllegalArgumentException if any of the times are negative
|
|
||||||
*/
|
|
||||||
public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) {
|
|
||||||
this(
|
|
||||||
new BaseComponent[]{checkNotNull(title, "title")},
|
|
||||||
subtitle == null ? null : new BaseComponent[]{subtitle},
|
|
||||||
fadeIn,
|
|
||||||
stay,
|
|
||||||
fadeOut
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new title.
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
* @param fadeIn the number of ticks for the title to fade in
|
|
||||||
* @param stay the number of ticks for the title to stay on screen
|
|
||||||
* @param fadeOut the number of ticks for the title to fade out
|
|
||||||
* @throws IllegalArgumentException if any of the times are negative
|
|
||||||
*/
|
|
||||||
public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) {
|
|
||||||
checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
|
||||||
checkArgument(stay >= 0, "Negative stay: %s", stay);
|
|
||||||
checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
|
||||||
this.title = checkNotNull(title, "title");
|
|
||||||
this.subtitle = subtitle;
|
|
||||||
this.fadeIn = fadeIn;
|
|
||||||
this.stay = stay;
|
|
||||||
this.fadeOut = fadeOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new title.
|
|
||||||
*
|
|
||||||
* <p>It is recommended to the {@link BaseComponent} constrctors.</p>
|
|
||||||
*
|
|
||||||
* @param title the main text of the title
|
|
||||||
* @param subtitle the secondary text of the title
|
|
||||||
* @param fadeIn the number of ticks for the title to fade in
|
|
||||||
* @param stay the number of ticks for the title to stay on screen
|
|
||||||
* @param fadeOut the number of ticks for the title to fade out
|
|
||||||
*/
|
|
||||||
public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) {
|
|
||||||
this(
|
|
||||||
TextComponent.fromLegacyText(checkNotNull(title, "title")),
|
|
||||||
subtitle == null ? null : TextComponent.fromLegacyText(subtitle),
|
|
||||||
fadeIn,
|
|
||||||
stay,
|
|
||||||
fadeOut
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the text of this title
|
|
||||||
*
|
|
||||||
* @return the text
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public BaseComponent[] getTitle() {
|
|
||||||
return this.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the text of this title's subtitle
|
|
||||||
*
|
|
||||||
* @return the text
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public BaseComponent[] getSubtitle() {
|
|
||||||
return this.subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of ticks to fade in.
|
|
||||||
*
|
|
||||||
* <p>The returned value is never negative.</p>
|
|
||||||
*
|
|
||||||
* @return the number of ticks to fade in
|
|
||||||
*/
|
|
||||||
public int getFadeIn() {
|
|
||||||
return this.fadeIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of ticks to stay.
|
|
||||||
*
|
|
||||||
* <p>The returned value is never negative.</p>
|
|
||||||
*
|
|
||||||
* @return the number of ticks to stay
|
|
||||||
*/
|
|
||||||
public int getStay() {
|
|
||||||
return this.stay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of ticks to fade out.
|
|
||||||
*
|
|
||||||
* <p>The returned value is never negative.</p>
|
|
||||||
*
|
|
||||||
* @return the number of ticks to fade out
|
|
||||||
*/
|
|
||||||
public int getFadeOut() {
|
|
||||||
return this.fadeOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Builder builder() {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder for creating titles
|
|
||||||
*/
|
|
||||||
public static final class Builder {
|
|
||||||
|
|
||||||
private BaseComponent[] title;
|
|
||||||
private BaseComponent[] subtitle;
|
|
||||||
private int fadeIn = DEFAULT_FADE_IN;
|
|
||||||
private int stay = DEFAULT_STAY;
|
|
||||||
private int fadeOut = DEFAULT_FADE_OUT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title to the given text.
|
|
||||||
*
|
|
||||||
* @param title the title text
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder title(@NotNull BaseComponent title) {
|
|
||||||
return this.title(new BaseComponent[]{checkNotNull(title, "title")});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title to the given text.
|
|
||||||
*
|
|
||||||
* @param title the title text
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder title(@NotNull BaseComponent[] title) {
|
|
||||||
this.title = checkNotNull(title, "title");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title to the given text.
|
|
||||||
*
|
|
||||||
* <p>It is recommended to the {@link BaseComponent} methods.</p>
|
|
||||||
*
|
|
||||||
* @param title the title text
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws NullPointerException if the title is null
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder title(@NotNull String title) {
|
|
||||||
return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subtitle to the given text.
|
|
||||||
*
|
|
||||||
* @param subtitle the title text
|
|
||||||
* @return this builder instance
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder subtitle(@Nullable BaseComponent subtitle) {
|
|
||||||
return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subtitle to the given text.
|
|
||||||
*
|
|
||||||
* @param subtitle the title text
|
|
||||||
* @return this builder instance
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder subtitle(@Nullable BaseComponent[] subtitle) {
|
|
||||||
this.subtitle = subtitle;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subtitle to the given text.
|
|
||||||
*
|
|
||||||
* <p>It is recommended to the {@link BaseComponent} methods.</p>
|
|
||||||
*
|
|
||||||
* @param subtitle the title text
|
|
||||||
* @return this builder instance
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder subtitle(@Nullable String subtitle) {
|
|
||||||
return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number of ticks for the title to fade in
|
|
||||||
*
|
|
||||||
* @param fadeIn the number of ticks to fade in
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws IllegalArgumentException if it is negative
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder fadeIn(int fadeIn) {
|
|
||||||
checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
|
||||||
this.fadeIn = fadeIn;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number of ticks for the title to stay.
|
|
||||||
*
|
|
||||||
* @param stay the number of ticks to stay
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws IllegalArgumentException if it is negative
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder stay(int stay) {
|
|
||||||
checkArgument(stay >= 0, "Negative stay: %s", stay);
|
|
||||||
this.stay = stay;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number of ticks for the title to fade out.
|
|
||||||
*
|
|
||||||
* @param fadeOut the number of ticks to fade out
|
|
||||||
* @return this builder instance
|
|
||||||
* @throws IllegalArgumentException if it is negative
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Builder fadeOut(int fadeOut) {
|
|
||||||
checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
|
||||||
this.fadeOut = fadeOut;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a title based on the values in the builder.
|
|
||||||
*
|
|
||||||
* @return a title from the values in this builder
|
|
||||||
* @throws IllegalStateException if title isn't specified
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Title build() {
|
|
||||||
checkState(title != null, "Title not specified");
|
|
||||||
return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package com.destroystokyo.paper.block;
|
|
||||||
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the sounds that a {@link Block} makes in certain situations
|
|
||||||
* <p>
|
|
||||||
* The sound group includes break, step, place, hit, and fall sounds.
|
|
||||||
*/
|
|
||||||
public interface BlockSoundGroup {
|
|
||||||
/**
|
|
||||||
* Gets the sound that plays when breaking this block
|
|
||||||
*
|
|
||||||
* @return The break sound
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Sound getBreakSound();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sound that plays when stepping on this block
|
|
||||||
*
|
|
||||||
* @return The step sound
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Sound getStepSound();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sound that plays when placing this block
|
|
||||||
*
|
|
||||||
* @return The place sound
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Sound getPlaceSound();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sound that plays when hitting this block
|
|
||||||
*
|
|
||||||
* @return The hit sound
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Sound getHitSound();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sound that plays when this block falls
|
|
||||||
*
|
|
||||||
* @return The fall sound
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Sound getFallSound();
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package com.destroystokyo.paper.block;
|
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents information about a targeted block
|
|
||||||
*/
|
|
||||||
public class TargetBlockInfo {
|
|
||||||
private final Block block;
|
|
||||||
private final BlockFace blockFace;
|
|
||||||
|
|
||||||
public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) {
|
|
||||||
this.block = block;
|
|
||||||
this.blockFace = blockFace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the block that is targeted
|
|
||||||
*
|
|
||||||
* @return Targeted block
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Block getBlock() {
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the targeted BlockFace
|
|
||||||
*
|
|
||||||
* @return Targeted blockface
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public BlockFace getBlockFace() {
|
|
||||||
return blockFace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the relative Block to the targeted block on the side it is targeted at
|
|
||||||
*
|
|
||||||
* @return Block relative to targeted block
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Block getRelativeBlock() {
|
|
||||||
return block.getRelative(blockFace);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum FluidMode {
|
|
||||||
NEVER,
|
|
||||||
SOURCE_ONLY,
|
|
||||||
ALWAYS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
package com.destroystokyo.paper.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Mob;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles pathfinding operations for an Entity
|
|
||||||
*/
|
|
||||||
public interface Pathfinder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return The entity that is controlled by this pathfinder
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Mob getEntity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructs the Entity to stop trying to navigate to its current desired location
|
|
||||||
*/
|
|
||||||
void stopPathfinding();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the entity is currently trying to navigate to a destination, this will return true
|
|
||||||
* @return true if the entity is navigating to a destination
|
|
||||||
*/
|
|
||||||
boolean hasPath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The location the entity is trying to navigate to, or null if there is no destination
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
PathResult getCurrentPath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to, but does not set it
|
|
||||||
* as the current target. Useful for calculating what would happen before setting it.
|
|
||||||
* @param loc Location to navigate to
|
|
||||||
* @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
|
|
||||||
*/
|
|
||||||
@Nullable PathResult findPath(@NotNull Location loc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
||||||
* but does not set it as the current target.
|
|
||||||
* Useful for calculating what would happen before setting it.
|
|
||||||
*
|
|
||||||
* The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
||||||
* result in the pathfinding automatically updating to follow the target Entity.
|
|
||||||
*
|
|
||||||
* However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
||||||
*
|
|
||||||
* @param target the Entity to navigate to
|
|
||||||
* @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
|
|
||||||
*/
|
|
||||||
@Nullable PathResult findPath(@NotNull LivingEntity target);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to, and sets it with default speed
|
|
||||||
* as the current target.
|
|
||||||
* @param loc Location to navigate to
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
default boolean moveTo(@NotNull Location loc) {
|
|
||||||
return moveTo(loc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to, with desired speed
|
|
||||||
* as the current target.
|
|
||||||
* @param loc Location to navigate to
|
|
||||||
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
default boolean moveTo(@NotNull Location loc, double speed) {
|
|
||||||
PathResult path = findPath(loc);
|
|
||||||
return path != null && moveTo(path, speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
||||||
* and sets it with default speed.
|
|
||||||
*
|
|
||||||
* The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
||||||
* result in the pathfinding automatically updating to follow the target Entity.
|
|
||||||
*
|
|
||||||
* However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
||||||
*
|
|
||||||
* @param target the Entity to navigate to
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
default boolean moveTo(@NotNull LivingEntity target) {
|
|
||||||
return moveTo(target, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
||||||
* and sets it with specified speed.
|
|
||||||
*
|
|
||||||
* The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
||||||
* result in the pathfinding automatically updating to follow the target Entity.
|
|
||||||
*
|
|
||||||
* However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
||||||
*
|
|
||||||
* @param target the Entity to navigate to
|
|
||||||
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
default boolean moveTo(@NotNull LivingEntity target, double speed) {
|
|
||||||
PathResult path = findPath(target);
|
|
||||||
return path != null && moveTo(path, speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes the result of a previous pathfinding calculation and sets it
|
|
||||||
* as the active pathfinding with default speed.
|
|
||||||
*
|
|
||||||
* @param path The Path to start following
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
default boolean moveTo(@NotNull PathResult path) {
|
|
||||||
return moveTo(path, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes the result of a previous pathfinding calculation and sets it
|
|
||||||
* as the active pathfinding,
|
|
||||||
*
|
|
||||||
* @param path The Path to start following
|
|
||||||
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
||||||
* @return If the pathfinding was successfully started
|
|
||||||
*/
|
|
||||||
boolean moveTo(@NotNull PathResult path, double speed);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the result of a pathfinding calculation
|
|
||||||
*/
|
|
||||||
interface PathResult {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All currently calculated points to follow along the path to reach the destination location
|
|
||||||
*
|
|
||||||
* Will return points the entity has already moved past, see {@link #getNextPointIndex()}
|
|
||||||
* @return List of points
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
List<Location> getPoints();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity
|
|
||||||
* is trying to reach, or null if we are done with this pathfinding.
|
|
||||||
*/
|
|
||||||
int getNextPointIndex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The next location in the path points the entity is trying to reach, or null if there is no next point
|
|
||||||
*/
|
|
||||||
@Nullable Location getNextPoint();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The closest point the path can get to the target location
|
|
||||||
*/
|
|
||||||
@Nullable Location getFinalPoint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.destroystokyo.paper.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Mob;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface RangedEntity extends Mob {
|
|
||||||
/**
|
|
||||||
* Attack the specified entity using a ranged attack.
|
|
||||||
*
|
|
||||||
* @param target the entity to target
|
|
||||||
* @param charge How "charged" the attack is (how far back the bow was pulled for Bow attacks).
|
|
||||||
* This should be a value between 0 and 1, represented as targetDistance/maxDistance.
|
|
||||||
*/
|
|
||||||
void rangedAttack(@NotNull LivingEntity target, float charge);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets that the Entity is "charging" up an attack, by raising its hands
|
|
||||||
*
|
|
||||||
* @param raiseHands Whether the entities hands are raised to charge attack
|
|
||||||
*/
|
|
||||||
void setChargingAttack(boolean raiseHands);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alias to {@link LivingEntity#isHandRaised()}, if the entity is charging an attack
|
|
||||||
* @return If entities hands are raised
|
|
||||||
*/
|
|
||||||
default boolean isChargingAttack() {
|
|
||||||
return isHandRaised();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.destroystokyo.paper.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents information about a targeted entity
|
|
||||||
*/
|
|
||||||
public class TargetEntityInfo {
|
|
||||||
private final Entity entity;
|
|
||||||
private final Vector hitVec;
|
|
||||||
|
|
||||||
public TargetEntityInfo(@NotNull Entity entity, @NotNull Vector hitVec) {
|
|
||||||
this.entity = entity;
|
|
||||||
this.hitVec = hitVec;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the entity that is targeted
|
|
||||||
*
|
|
||||||
* @return Targeted entity
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Entity getEntity() {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the position the entity is targeted at
|
|
||||||
*
|
|
||||||
* @return Targeted position
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Vector getHitVector() {
|
|
||||||
return hitVec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.block;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.inventory.InventoryEvent;
|
|
||||||
import org.bukkit.inventory.AnvilInventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an anvil is damaged from being used
|
|
||||||
*/
|
|
||||||
public class AnvilDamagedEvent extends InventoryEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancel;
|
|
||||||
private DamageState damageState;
|
|
||||||
|
|
||||||
public AnvilDamagedEvent(@NotNull InventoryView inventory, @NotNull BlockData blockData) {
|
|
||||||
super(inventory);
|
|
||||||
this.damageState = DamageState.getState(blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public AnvilInventory getInventory() {
|
|
||||||
return (AnvilInventory) super.getInventory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the new state of damage on the anvil
|
|
||||||
*
|
|
||||||
* @return Damage state
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public DamageState getDamageState() {
|
|
||||||
return damageState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the new state of damage on the anvil
|
|
||||||
*
|
|
||||||
* @param damageState Damage state
|
|
||||||
*/
|
|
||||||
public void setDamageState(@NotNull DamageState damageState) {
|
|
||||||
this.damageState = damageState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets if anvil is breaking on this use
|
|
||||||
*
|
|
||||||
* @return True if breaking
|
|
||||||
*/
|
|
||||||
public boolean isBreaking() {
|
|
||||||
return damageState == DamageState.BROKEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if anvil is breaking on this use
|
|
||||||
*
|
|
||||||
* @param breaking True if breaking
|
|
||||||
*/
|
|
||||||
public void setBreaking(boolean breaking) {
|
|
||||||
if (breaking) {
|
|
||||||
damageState = DamageState.BROKEN;
|
|
||||||
} else if (damageState == DamageState.BROKEN) {
|
|
||||||
damageState = DamageState.DAMAGED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancel = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the amount of damage on an anvil block
|
|
||||||
*/
|
|
||||||
public enum DamageState {
|
|
||||||
FULL(Material.ANVIL),
|
|
||||||
CHIPPED(Material.CHIPPED_ANVIL),
|
|
||||||
DAMAGED(Material.DAMAGED_ANVIL),
|
|
||||||
BROKEN(Material.AIR);
|
|
||||||
|
|
||||||
private Material material;
|
|
||||||
|
|
||||||
DamageState(@NotNull Material material) {
|
|
||||||
this.material = material;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get block material of this state
|
|
||||||
*
|
|
||||||
* @return Material
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Material getMaterial() {
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get damaged state by block data
|
|
||||||
*
|
|
||||||
* @param blockData Block data
|
|
||||||
* @return DamageState
|
|
||||||
* @throws IllegalArgumentException If non anvil block data is given
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static DamageState getState(@Nullable BlockData blockData) {
|
|
||||||
return blockData == null ? BROKEN : getState(blockData.getMaterial());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get damaged state by block material
|
|
||||||
*
|
|
||||||
* @param material Block material
|
|
||||||
* @return DamageState
|
|
||||||
* @throws IllegalArgumentException If non anvil material is given
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static DamageState getState(@Nullable Material material) {
|
|
||||||
if (material == null) {
|
|
||||||
return BROKEN;
|
|
||||||
}
|
|
||||||
for (DamageState state : values()) {
|
|
||||||
if (state.material == material) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Material not an anvil");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.block;
|
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.block.BlockEvent;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a beacon effect is being applied to a player.
|
|
||||||
*/
|
|
||||||
public class BeaconEffectEvent extends BlockEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled;
|
|
||||||
private PotionEffect effect;
|
|
||||||
private Player player;
|
|
||||||
private boolean primary;
|
|
||||||
|
|
||||||
public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) {
|
|
||||||
super(block);
|
|
||||||
this.effect = effect;
|
|
||||||
this.player = player;
|
|
||||||
this.primary = primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancelled) {
|
|
||||||
this.cancelled = cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the potion effect being applied.
|
|
||||||
*
|
|
||||||
* @return Potion effect
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public PotionEffect getEffect() {
|
|
||||||
return effect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the potion effect that will be applied.
|
|
||||||
*
|
|
||||||
* @param effect Potion effect
|
|
||||||
*/
|
|
||||||
public void setEffect(@NotNull PotionEffect effect) {
|
|
||||||
this.effect = effect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the player who the potion effect is being applied to.
|
|
||||||
*
|
|
||||||
* @return Affected player
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Player getPlayer() {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether the effect is a primary beacon effect.
|
|
||||||
*
|
|
||||||
* @return true if this event represents a primary effect
|
|
||||||
*/
|
|
||||||
public boolean isPrimary() {
|
|
||||||
return primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.block;
|
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.block.BlockEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired anytime the server intends to 'destroy' a block through some triggering reason.
|
|
||||||
* This does not fire anytime a block is set to air, but only with more direct triggers such
|
|
||||||
* as physics updates, pistons, Entities changing blocks, commands set to "Destroy".
|
|
||||||
*
|
|
||||||
* This event is associated with the game playing a sound effect at the block in question, when
|
|
||||||
* something can be described as "intend to destroy what is there",
|
|
||||||
*
|
|
||||||
* Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class BlockDestroyEvent extends BlockEvent implements Cancellable {
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull private final BlockData newState;
|
|
||||||
private final boolean willDrop;
|
|
||||||
private boolean playEffect;
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) {
|
|
||||||
super(block);
|
|
||||||
this.newState = newState;
|
|
||||||
this.willDrop = willDrop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The new state of this block (Air, or a Fluid type)
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public BlockData getNewState() {
|
|
||||||
return newState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the server is going to drop the block in question with this destroy event
|
|
||||||
*/
|
|
||||||
public boolean willDrop() {
|
|
||||||
return this.willDrop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the server is going to play the sound effect for this destruction
|
|
||||||
*/
|
|
||||||
public boolean playEffect() {
|
|
||||||
return this.playEffect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param playEffect If the server should play the sound effect for this destruction
|
|
||||||
*/
|
|
||||||
public void setPlayEffect(boolean playEffect) {
|
|
||||||
this.playEffect = playEffect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the event is cancelled, meaning the block will not be destroyed
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the event is cancelled, the block will remain in its previous state.
|
|
||||||
* @param cancel true if you wish to cancel this event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.block;
|
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.block.BlockEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when TNT block is about to turn into {@link org.bukkit.entity.TNTPrimed}
|
|
||||||
* <p>
|
|
||||||
* Cancelling it won't turn TNT into {@link org.bukkit.entity.TNTPrimed} and leaves
|
|
||||||
* the TNT block as-is
|
|
||||||
*
|
|
||||||
* @author Mark Vainomaa
|
|
||||||
*/
|
|
||||||
public class TNTPrimeEvent extends BlockEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled;
|
|
||||||
@NotNull private PrimeReason reason;
|
|
||||||
@Nullable private Entity primerEntity;
|
|
||||||
|
|
||||||
public TNTPrimeEvent(@NotNull Block theBlock, @NotNull PrimeReason reason, @Nullable Entity primerEntity) {
|
|
||||||
super(theBlock);
|
|
||||||
this.reason = reason;
|
|
||||||
this.primerEntity = primerEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the TNT prime reason
|
|
||||||
*
|
|
||||||
* @return Prime reason
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public PrimeReason getReason() {
|
|
||||||
return this.reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the TNT primer {@link Entity}.
|
|
||||||
*
|
|
||||||
* It's null if {@link #getReason()} is {@link PrimeReason#REDSTONE} or {@link PrimeReason#FIRE}.
|
|
||||||
* It's not null if {@link #getReason()} is {@link PrimeReason#ITEM} or {@link PrimeReason#PROJECTILE}
|
|
||||||
* It might be null if {@link #getReason()} is {@link PrimeReason#EXPLOSION}
|
|
||||||
*
|
|
||||||
* @return The {@link Entity} who primed the TNT
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Entity getPrimerEntity() {
|
|
||||||
return this.primerEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
|
|
||||||
*
|
|
||||||
* @return Whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return this.cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether to cancel spawning {@link org.bukkit.entity.TNTPrimed} or not
|
|
||||||
*
|
|
||||||
* @param cancel whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PrimeReason {
|
|
||||||
/**
|
|
||||||
* When TNT prime was caused by other explosion (chain reaction)
|
|
||||||
*/
|
|
||||||
EXPLOSION,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When TNT prime was caused by fire
|
|
||||||
*/
|
|
||||||
FIRE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When {@link org.bukkit.entity.Player} used {@link org.bukkit.Material#FLINT_AND_STEEL} or
|
|
||||||
* {@link org.bukkit.Material#FIRE_CHARGE} on given TNT block
|
|
||||||
*/
|
|
||||||
ITEM,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When TNT prime was caused by an {@link Entity} shooting TNT
|
|
||||||
* using a bow with {@link org.bukkit.enchantments.Enchantment#ARROW_FIRE} enchantment
|
|
||||||
*/
|
|
||||||
PROJECTILE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When redstone power triggered the TNT prime
|
|
||||||
*/
|
|
||||||
REDSTONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Creeper;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a Creeper is ignite flag is changed (armed/disarmed to explode).
|
|
||||||
*/
|
|
||||||
public class CreeperIgniteEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean canceled;
|
|
||||||
private boolean ignited;
|
|
||||||
|
|
||||||
public CreeperIgniteEvent(@NotNull Creeper creeper, boolean ignited) {
|
|
||||||
super(creeper);
|
|
||||||
this.ignited = ignited;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Creeper getEntity() {
|
|
||||||
return (Creeper) entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isIgnited() {
|
|
||||||
return ignited;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIgnited(boolean ignited) {
|
|
||||||
this.ignited = ignited;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return canceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
canceled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.AreaEffectCloud;
|
|
||||||
import org.bukkit.entity.DragonFireball;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud
|
|
||||||
*/
|
|
||||||
public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable {
|
|
||||||
@Nullable private final Collection<LivingEntity> targets;
|
|
||||||
@NotNull private final AreaEffectCloud areaEffectCloud;
|
|
||||||
|
|
||||||
public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @Nullable Collection<LivingEntity> targets, @NotNull AreaEffectCloud areaEffectCloud) {
|
|
||||||
super(fireball);
|
|
||||||
this.targets = targets;
|
|
||||||
this.areaEffectCloud = areaEffectCloud;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The fireball involved in this event
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public DragonFireball getEntity() {
|
|
||||||
return (DragonFireball) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The living entities hit by fireball
|
|
||||||
*
|
|
||||||
* May be null if no entities were hit
|
|
||||||
*
|
|
||||||
* @return the targets
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Collection<LivingEntity> getTargets() {
|
|
||||||
return targets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The area effect cloud spawned in this collision
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public AreaEffectCloud getAreaEffectCloud() {
|
|
||||||
return areaEffectCloud;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.AreaEffectCloud;
|
|
||||||
import org.bukkit.entity.EnderDragon;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an EnderDragon spawns an AreaEffectCloud by shooting flames
|
|
||||||
*/
|
|
||||||
public class EnderDragonFlameEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final AreaEffectCloud areaEffectCloud;
|
|
||||||
|
|
||||||
public EnderDragonFlameEvent(@NotNull EnderDragon enderDragon, @NotNull AreaEffectCloud areaEffectCloud) {
|
|
||||||
super(enderDragon);
|
|
||||||
this.areaEffectCloud = areaEffectCloud;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The enderdragon involved in this event
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public EnderDragon getEntity() {
|
|
||||||
return (EnderDragon) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The area effect cloud spawned in this collision
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public AreaEffectCloud getAreaEffectCloud() {
|
|
||||||
return areaEffectCloud;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.DragonFireball;
|
|
||||||
import org.bukkit.entity.EnderDragon;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an EnderDragon shoots a fireball
|
|
||||||
*/
|
|
||||||
public class EnderDragonShootFireballEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final DragonFireball fireball;
|
|
||||||
|
|
||||||
public EnderDragonShootFireballEvent(@NotNull EnderDragon entity, @NotNull DragonFireball fireball) {
|
|
||||||
super(entity);
|
|
||||||
this.fireball = fireball;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The enderdragon shooting the fireball
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public EnderDragon getEntity() {
|
|
||||||
return (EnderDragon) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The fireball being shot
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public DragonFireball getFireball() {
|
|
||||||
return fireball;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Enderman;
|
|
||||||
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;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an Enderman determines if it should attack a player or not.
|
|
||||||
* Starts off cancelled if the player is wearing a pumpkin head or is not looking
|
|
||||||
* at the Enderman, according to Vanilla rules.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final Player player;
|
|
||||||
|
|
||||||
public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) {
|
|
||||||
super(entity);
|
|
||||||
this.player = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The enderman considering attacking
|
|
||||||
*
|
|
||||||
* @return The enderman considering attacking
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Enderman getEntity() {
|
|
||||||
return (Enderman) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The player the Enderman is considering attacking
|
|
||||||
*
|
|
||||||
* @return The player the Enderman is considering attacking
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Player getPlayer() {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return If cancelled, the enderman will not attack
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels if the Enderman will attack this player
|
|
||||||
* @param cancel true if you wish to cancel this event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Enderman;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final Reason reason;
|
|
||||||
|
|
||||||
public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) {
|
|
||||||
super(entity);
|
|
||||||
this.reason = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Enderman getEntity() {
|
|
||||||
return (Enderman) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The reason the enderman is trying to escape
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Reason getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels the escape.
|
|
||||||
*
|
|
||||||
* If this escape normally would of resulted in damage avoidance such as indirect,
|
|
||||||
* the enderman will now take damage.
|
|
||||||
*
|
|
||||||
* @param cancel true if you wish to cancel this event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Reason {
|
|
||||||
/**
|
|
||||||
* The enderman has stopped attacking and ran away
|
|
||||||
*/
|
|
||||||
RUNAWAY,
|
|
||||||
/**
|
|
||||||
* The enderman has teleported away due to indirect damage (ranged)
|
|
||||||
*/
|
|
||||||
INDIRECT,
|
|
||||||
/**
|
|
||||||
* The enderman has teleported away due to a critical hit
|
|
||||||
*/
|
|
||||||
CRITICAL_HIT,
|
|
||||||
/**
|
|
||||||
* The enderman has teleported away due to the player staring at it during combat
|
|
||||||
*/
|
|
||||||
STARE,
|
|
||||||
/**
|
|
||||||
* Specific case for CRITICAL_HIT where the enderman is taking rain damage
|
|
||||||
*/
|
|
||||||
DROWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired any time an entity is being added to the world for any reason.
|
|
||||||
*
|
|
||||||
* Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent}
|
|
||||||
* This will fire anytime a chunk is reloaded too.
|
|
||||||
*/
|
|
||||||
public class EntityAddToWorldEvent extends EntityEvent {
|
|
||||||
|
|
||||||
public EntityAddToWorldEvent(@NotNull Entity entity) {
|
|
||||||
super(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an Entity is knocked back by the hit of another Entity. The acceleration
|
|
||||||
* vector can be modified. If this event is cancelled, the entity is not knocked back.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class EntityKnockbackByEntityEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull private final Entity hitBy;
|
|
||||||
private final float knockbackStrength;
|
|
||||||
@NotNull private final Vector acceleration;
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) {
|
|
||||||
super(entity);
|
|
||||||
this.hitBy = hitBy;
|
|
||||||
this.knockbackStrength = knockbackStrength;
|
|
||||||
this.acceleration = acceleration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the entity which was knocked back
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public LivingEntity getEntity() {
|
|
||||||
return (LivingEntity) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the original knockback strength.
|
|
||||||
*/
|
|
||||||
public float getKnockbackStrength() {
|
|
||||||
return knockbackStrength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the Entity which hit
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Entity getHitBy() {
|
|
||||||
return hitBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the acceleration that will be applied
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Vector getAcceleration() {
|
|
||||||
return acceleration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an Entity decides to start moving towards a location.
|
|
||||||
*
|
|
||||||
* This event does not fire for the entities actual movement. Only when it
|
|
||||||
* is choosing to start moving to a location.
|
|
||||||
*/
|
|
||||||
public class EntityPathfindEvent extends EntityEvent implements Cancellable {
|
|
||||||
@Nullable private final Entity targetEntity;
|
|
||||||
@NotNull private final Location loc;
|
|
||||||
|
|
||||||
public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) {
|
|
||||||
super(entity);
|
|
||||||
this.targetEntity = targetEntity;
|
|
||||||
this.loc = loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Entity that is pathfinding.
|
|
||||||
* @return The Entity that is pathfinding.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Entity getEntity() {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the Entity is trying to pathfind to an entity, this is the entity in relation.
|
|
||||||
*
|
|
||||||
* Otherwise this will return null.
|
|
||||||
*
|
|
||||||
* @return The entity target or null
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Entity getTargetEntity() {
|
|
||||||
return targetEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Location of where the entity is about to move to.
|
|
||||||
*
|
|
||||||
* Note that if the target happened to of been an entity
|
|
||||||
* @return Location of where the entity is trying to pathfind to.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getLoc() {
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired any time an entity is being removed from a world for any reason
|
|
||||||
*/
|
|
||||||
public class EntityRemoveFromWorldEvent extends EntityEvent {
|
|
||||||
|
|
||||||
public EntityRemoveFromWorldEvent(@NotNull Entity entity) {
|
|
||||||
super(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.EndGateway;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.entity.EntityTeleportEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired any time an entity attempts to teleport in an end gateway
|
|
||||||
*/
|
|
||||||
public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent {
|
|
||||||
|
|
||||||
@NotNull private final EndGateway gateway;
|
|
||||||
|
|
||||||
public EntityTeleportEndGatewayEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) {
|
|
||||||
super(what, from, to);
|
|
||||||
this.gateway = gateway;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The gateway triggering the teleport
|
|
||||||
*
|
|
||||||
* @return EndGateway used
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public EndGateway getGateway() {
|
|
||||||
return gateway;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.event.entity.EntityTransformEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when an entity transforms into another entity
|
|
||||||
* <p>
|
|
||||||
* If the event is cancelled, the entity will not transform
|
|
||||||
* @deprecated Bukkit has added {@link EntityTransformEvent}, you should start using that
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class EntityTransformedEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled;
|
|
||||||
private final Entity transformed;
|
|
||||||
private final TransformedReason reason;
|
|
||||||
|
|
||||||
public EntityTransformedEvent(Entity entity, Entity transformed, TransformedReason reason) {
|
|
||||||
super(entity);
|
|
||||||
this.transformed = transformed;
|
|
||||||
this.reason = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The entity after it has transformed
|
|
||||||
*
|
|
||||||
* @return Transformed entity
|
|
||||||
* @deprecated see {@link EntityTransformEvent#getTransformedEntity()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Entity getTransformed() {
|
|
||||||
return transformed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The reason for the transformation
|
|
||||||
* @deprecated see {@link EntityTransformEvent#getTransformReason()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public TransformedReason getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers(){
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HandlerList getHandlerList(){
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled(){
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel){
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TransformedReason {
|
|
||||||
/**
|
|
||||||
* When a zombie drowns
|
|
||||||
*/
|
|
||||||
DROWNED,
|
|
||||||
/**
|
|
||||||
* When a zombie villager is cured
|
|
||||||
*/
|
|
||||||
CURED,
|
|
||||||
/**
|
|
||||||
* When a villager turns to a zombie villager
|
|
||||||
*/
|
|
||||||
INFECTED,
|
|
||||||
/**
|
|
||||||
* When a mooshroom turns to a cow
|
|
||||||
*/
|
|
||||||
SHEARED,
|
|
||||||
/**
|
|
||||||
* When a pig turns to a zombiepigman
|
|
||||||
*/
|
|
||||||
LIGHTNING
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LightningStrike;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.event.entity.EntityTransformEvent;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when lightning strikes an entity
|
|
||||||
*/
|
|
||||||
public class EntityZapEvent extends EntityTransformEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled;
|
|
||||||
@NotNull private final LightningStrike bolt;
|
|
||||||
|
|
||||||
public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) {
|
|
||||||
super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING);
|
|
||||||
Validate.notNull(bolt);
|
|
||||||
Validate.notNull(replacementEntity);
|
|
||||||
this.bolt = bolt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the lightning bolt that is striking the entity.
|
|
||||||
* @return The lightning bolt responsible for this event
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public LightningStrike getBolt() {
|
|
||||||
return bolt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the entity that will replace the struck entity.
|
|
||||||
* @return The entity that will replace the struck entity
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Entity getReplacementEntity() {
|
|
||||||
return getTransformedEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.ExperienceOrb;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired anytime the server is about to merge 2 experience orbs into one
|
|
||||||
*/
|
|
||||||
public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final ExperienceOrb mergeTarget;
|
|
||||||
@NotNull private final ExperienceOrb mergeSource;
|
|
||||||
|
|
||||||
public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) {
|
|
||||||
super(mergeTarget);
|
|
||||||
this.mergeTarget = mergeTarget;
|
|
||||||
this.mergeSource = mergeSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The orb that will absorb the other experience orb
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ExperienceOrb getMergeTarget() {
|
|
||||||
return mergeTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The orb that is subject to being removed and merged into the target orb
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ExperienceOrb getMergeSource() {
|
|
||||||
return mergeSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cancel true if you wish to cancel this event, and prevent the orbs from merging
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a phantom is spawned for an exhausted player
|
|
||||||
*/
|
|
||||||
public class PhantomPreSpawnEvent extends PreCreatureSpawnEvent {
|
|
||||||
@NotNull private final Entity entity;
|
|
||||||
|
|
||||||
public PhantomPreSpawnEvent(@NotNull Location location, @NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) {
|
|
||||||
super(location, EntityType.PHANTOM, reason);
|
|
||||||
this.entity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the entity this phantom is spawning for
|
|
||||||
*
|
|
||||||
* @return Entity
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Entity getSpawningEntity() {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event
|
|
||||||
*/
|
|
||||||
public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable {
|
|
||||||
private byte radius;
|
|
||||||
|
|
||||||
public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) {
|
|
||||||
super(player);
|
|
||||||
this.radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The radius of chunks around this player to be included in natural spawn selection
|
|
||||||
*/
|
|
||||||
public byte getSpawnRadius() {
|
|
||||||
return radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param radius The radius of chunks around this player to be included in natural spawn selection
|
|
||||||
*/
|
|
||||||
public void setSpawnRadius(byte radius) {
|
|
||||||
this.radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If this players chunks will be excluded from natural spawns
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does.
|
|
||||||
*
|
|
||||||
* You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement".
|
|
||||||
* The intent of this event is to improve server performance, so limited use cases.
|
|
||||||
*
|
|
||||||
* Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions.
|
|
||||||
* Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event.
|
|
||||||
*/
|
|
||||||
public class PreCreatureSpawnEvent extends Event implements Cancellable {
|
|
||||||
@NotNull private final Location location;
|
|
||||||
@NotNull private final EntityType type;
|
|
||||||
@NotNull private final CreatureSpawnEvent.SpawnReason reason;
|
|
||||||
private boolean shouldAbortSpawn;
|
|
||||||
|
|
||||||
public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) {
|
|
||||||
this.location = Preconditions.checkNotNull(location, "Location may not be null").clone();
|
|
||||||
this.type = Preconditions.checkNotNull(type, "Type may not be null");
|
|
||||||
this.reason = Preconditions.checkNotNull(reason, "Reason may not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The location this creature is being spawned at
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getSpawnLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The type of creature being spawned
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public EntityType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Reason this creature is spawning (ie, NATURAL vs SPAWNER)
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public CreatureSpawnEvent.SpawnReason getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the spawn process should be aborted vs trying more attempts
|
|
||||||
*/
|
|
||||||
public boolean shouldAbortSpawn() {
|
|
||||||
return shouldAbortSpawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from
|
|
||||||
* trying more attempts after this cancellation.
|
|
||||||
*
|
|
||||||
* @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts
|
|
||||||
*/
|
|
||||||
public void setShouldAbortSpawn(boolean shouldAbortSpawn) {
|
|
||||||
this.shouldAbortSpawn = shouldAbortSpawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the spawn of this creature is cancelled or not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancelling this event is more effecient than cancelling CreatureSpawnEvent
|
|
||||||
* @param cancel true if you wish to cancel this event, and abort the spawn of this creature
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before an entity is spawned into a world by a spawner.
|
|
||||||
*
|
|
||||||
* This only includes the spawner's location and not the full BlockState snapshot for performance reasons.
|
|
||||||
* If you really need it you have to get the spawner yourself.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent {
|
|
||||||
@NotNull private final Location spawnerLocation;
|
|
||||||
|
|
||||||
public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) {
|
|
||||||
super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
|
||||||
this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Location getSpawnerLocation() {
|
|
||||||
return spawnerLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Projectile;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an projectile collides with an entity
|
|
||||||
* <p>
|
|
||||||
* This event is called <b>before</b> {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying
|
|
||||||
*/
|
|
||||||
public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final Entity collidedWith;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the entity the projectile collided with
|
|
||||||
*
|
|
||||||
* @return the entity collided with
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Entity getCollidedWith() {
|
|
||||||
return collidedWith;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) {
|
|
||||||
super(what);
|
|
||||||
this.collidedWith = collidedWith;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the projectile that collided
|
|
||||||
*
|
|
||||||
* @return the projectile that collided
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Projectile getEntity() {
|
|
||||||
return (Projectile) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlerList = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlerList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlerList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.SkeletonHorse;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event called when a player gets close to a skeleton horse and triggers the lightning trap
|
|
||||||
*/
|
|
||||||
public class SkeletonHorseTrapEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled;
|
|
||||||
|
|
||||||
public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) {
|
|
||||||
super(horse);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public SkeletonHorse getEntity() {
|
|
||||||
return (SkeletonHorse) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Slime;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Slime decides to change it's facing direction.
|
|
||||||
* <p>
|
|
||||||
* This event does not fire for the entity's actual movement. Only when it
|
|
||||||
* is choosing to change direction.
|
|
||||||
*/
|
|
||||||
public class SlimeChangeDirectionEvent extends SlimePathfindEvent implements Cancellable {
|
|
||||||
private float yaw;
|
|
||||||
|
|
||||||
public SlimeChangeDirectionEvent(@NotNull Slime slime, float yaw) {
|
|
||||||
super(slime);
|
|
||||||
this.yaw = yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the new chosen yaw
|
|
||||||
*
|
|
||||||
* @return Chosen yaw
|
|
||||||
*/
|
|
||||||
public float getNewYaw() {
|
|
||||||
return yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the new chosen yaw
|
|
||||||
*
|
|
||||||
* @param yaw Chosen yaw
|
|
||||||
*/
|
|
||||||
public void setNewYaw(float yaw) {
|
|
||||||
this.yaw = yaw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Slime;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Slime decides to start pathfinding.
|
|
||||||
* <p>
|
|
||||||
* This event does not fire for the entity's actual movement. Only when it
|
|
||||||
* is choosing to start moving.
|
|
||||||
*/
|
|
||||||
public class SlimePathfindEvent extends EntityEvent implements Cancellable {
|
|
||||||
public SlimePathfindEvent(@NotNull Slime slime) {
|
|
||||||
super(slime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Slime that is pathfinding.
|
|
||||||
*
|
|
||||||
* @return The Slime that is pathfinding.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Slime getEntity() {
|
|
||||||
return (Slime) entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Slime;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Slime decides to start jumping while swimming in water/lava.
|
|
||||||
* <p>
|
|
||||||
* This event does not fire for the entity's actual movement. Only when it
|
|
||||||
* is choosing to start jumping.
|
|
||||||
*/
|
|
||||||
public class SlimeSwimEvent extends SlimeWanderEvent implements Cancellable {
|
|
||||||
public SlimeSwimEvent(@NotNull Slime slime) {
|
|
||||||
super(slime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Slime;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Slime decides to change direction to target a LivingEntity.
|
|
||||||
* <p>
|
|
||||||
* This event does not fire for the entity's actual movement. Only when it
|
|
||||||
* is choosing to start moving.
|
|
||||||
*/
|
|
||||||
public class SlimeTargetLivingEntityEvent extends SlimePathfindEvent implements Cancellable {
|
|
||||||
@NotNull private final LivingEntity target;
|
|
||||||
|
|
||||||
public SlimeTargetLivingEntityEvent(@NotNull Slime slime, @NotNull LivingEntity target) {
|
|
||||||
super(slime);
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the targeted entity
|
|
||||||
*
|
|
||||||
* @return Targeted entity
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public LivingEntity getTarget() {
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Slime;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Slime decides to start wandering.
|
|
||||||
* <p>
|
|
||||||
* This event does not fire for the entity's actual movement. Only when it
|
|
||||||
* is choosing to start moving.
|
|
||||||
*/
|
|
||||||
public class SlimeWanderEvent extends SlimePathfindEvent implements Cancellable {
|
|
||||||
public SlimeWanderEvent(@NotNull Slime slime) {
|
|
||||||
super(slime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Turtle;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Turtle decides to go home
|
|
||||||
*/
|
|
||||||
public class TurtleGoHomeEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
public TurtleGoHomeEvent(@NotNull Turtle turtle) {
|
|
||||||
super(turtle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The turtle going home
|
|
||||||
*
|
|
||||||
* @return The turtle
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Turtle getEntity() {
|
|
||||||
return (Turtle) entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Turtle;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Turtle lays eggs
|
|
||||||
*/
|
|
||||||
public class TurtleLayEggEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled = false;
|
|
||||||
@NotNull
|
|
||||||
private final Location location;
|
|
||||||
private int eggCount;
|
|
||||||
|
|
||||||
public TurtleLayEggEvent(@NotNull Turtle turtle, @NotNull Location location, int eggCount) {
|
|
||||||
super(turtle);
|
|
||||||
this.location = location;
|
|
||||||
this.eggCount = eggCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The turtle laying the eggs
|
|
||||||
*
|
|
||||||
* @return The turtle
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Turtle getEntity() {
|
|
||||||
return (Turtle) entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the location where the eggs are being laid
|
|
||||||
*
|
|
||||||
* @return Location of eggs
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of eggs being laid
|
|
||||||
*
|
|
||||||
* @return Number of eggs
|
|
||||||
*/
|
|
||||||
public int getEggCount() {
|
|
||||||
return eggCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the number of eggs being laid
|
|
||||||
*
|
|
||||||
* @param eggCount Number of eggs
|
|
||||||
*/
|
|
||||||
public void setEggCount(int eggCount) {
|
|
||||||
if (eggCount < 1) {
|
|
||||||
cancelled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eggCount = Math.min(eggCount, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Turtle;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a Turtle starts digging to lay eggs
|
|
||||||
*/
|
|
||||||
public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled = false;
|
|
||||||
@NotNull private final Location location;
|
|
||||||
|
|
||||||
public TurtleStartDiggingEvent(@NotNull Turtle turtle, @NotNull Location location) {
|
|
||||||
super(turtle);
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The turtle digging
|
|
||||||
*
|
|
||||||
* @return The turtle
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Turtle getEntity() {
|
|
||||||
return (Turtle) entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the location where the turtle is digging
|
|
||||||
*
|
|
||||||
* @return Location where digging
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Witch;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a witch consumes the potion in their hand to buff themselves.
|
|
||||||
*/
|
|
||||||
public class WitchConsumePotionEvent extends EntityEvent implements Cancellable {
|
|
||||||
@Nullable private ItemStack potion;
|
|
||||||
|
|
||||||
public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
|
|
||||||
super(witch);
|
|
||||||
this.potion = potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Witch getEntity() {
|
|
||||||
return (Witch) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the potion the witch will consume and have the effects applied.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ItemStack getPotion() {
|
|
||||||
return potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the potion to be consumed and applied to the witch.
|
|
||||||
* @param potion The potion
|
|
||||||
*/
|
|
||||||
public void setPotion(@Nullable ItemStack potion) {
|
|
||||||
this.potion = potion != null ? potion.clone() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Event was cancelled or potion was null
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled || potion == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Witch;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class WitchReadyPotionEvent extends EntityEvent implements Cancellable {
|
|
||||||
private ItemStack potion;
|
|
||||||
|
|
||||||
public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
|
|
||||||
super(witch);
|
|
||||||
this.potion = potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fires thee event, returning the desired potion, or air of cancelled
|
|
||||||
* @param witch the witch whom is readying to use a potion
|
|
||||||
* @param potion the potion to be used
|
|
||||||
* @return The ItemStack to be used
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static ItemStack process(@NotNull Witch witch, @Nullable ItemStack potion) {
|
|
||||||
WitchReadyPotionEvent event = new WitchReadyPotionEvent(witch, potion);
|
|
||||||
if (!event.callEvent() || event.getPotion() == null) {
|
|
||||||
return new ItemStack(Material.AIR);
|
|
||||||
}
|
|
||||||
return event.getPotion();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Witch getEntity() {
|
|
||||||
return (Witch) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the potion the witch is readying to use
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ItemStack getPotion() {
|
|
||||||
return potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the potion the which is going to hold and use
|
|
||||||
* @param potion The potion
|
|
||||||
*/
|
|
||||||
public void setPotion(@Nullable ItemStack potion) {
|
|
||||||
this.potion = potion != null ? potion.clone() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.entity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Witch;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a witch throws a potion at a player
|
|
||||||
*/
|
|
||||||
public class WitchThrowPotionEvent extends EntityEvent implements Cancellable {
|
|
||||||
@NotNull private final LivingEntity target;
|
|
||||||
@Nullable private ItemStack potion;
|
|
||||||
|
|
||||||
public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) {
|
|
||||||
super(witch);
|
|
||||||
this.target = target;
|
|
||||||
this.potion = potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Witch getEntity() {
|
|
||||||
return (Witch) super.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The target of the potion
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public LivingEntity getTarget() {
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The potion the witch will throw at a player
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ItemStack getPotion() {
|
|
||||||
return potion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the potion to be thrown at a player
|
|
||||||
* @param potion The potion
|
|
||||||
*/
|
|
||||||
public void setPotion(@Nullable ItemStack potion) {
|
|
||||||
this.potion = potion != null ? potion.clone() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Event was cancelled or potion was null
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled || potion == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.executor;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import com.destroystokyo.paper.util.SneakyThrow;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.EventException;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.plugin.EventExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class MethodHandleEventExecutor implements EventExecutor {
|
|
||||||
private final Class<? extends Event> eventClass;
|
|
||||||
private final MethodHandle handle;
|
|
||||||
|
|
||||||
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
|
|
||||||
this.eventClass = eventClass;
|
|
||||||
this.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
|
||||||
this.eventClass = eventClass;
|
|
||||||
try {
|
|
||||||
m.setAccessible(true);
|
|
||||||
this.handle = MethodHandles.lookup().unreflect(m);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AssertionError("Unable to set accessible", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
|
||||||
if (!eventClass.isInstance(event)) return;
|
|
||||||
try {
|
|
||||||
handle.invoke(listener, event);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
SneakyThrow.sneaky(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.executor;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
import com.destroystokyo.paper.util.SneakyThrow;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.EventException;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.plugin.EventExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class StaticMethodHandleEventExecutor implements EventExecutor {
|
|
||||||
private final Class<? extends Event> eventClass;
|
|
||||||
private final MethodHandle handle;
|
|
||||||
|
|
||||||
public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
|
||||||
Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
|
|
||||||
Preconditions.checkArgument(eventClass != null, "eventClass is null");
|
|
||||||
this.eventClass = eventClass;
|
|
||||||
try {
|
|
||||||
m.setAccessible(true);
|
|
||||||
this.handle = MethodHandles.lookup().unreflect(m);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AssertionError("Unable to set accessible", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
|
||||||
if (!eventClass.isInstance(event)) return;
|
|
||||||
try {
|
|
||||||
handle.invoke(event);
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
SneakyThrow.sneaky(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.executor.asm;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.bukkit.plugin.EventExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
|
||||||
|
|
||||||
public class ASMEventExecutorGenerator {
|
|
||||||
@NotNull
|
|
||||||
public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) {
|
|
||||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
|
||||||
writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)});
|
|
||||||
// Generate constructor
|
|
||||||
GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null), ACC_PUBLIC, "<init>", "()V");
|
|
||||||
methodGenerator.loadThis();
|
|
||||||
methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // Invoke the super class (Object) constructor
|
|
||||||
methodGenerator.returnValue();
|
|
||||||
methodGenerator.endMethod();
|
|
||||||
// Generate the execute method
|
|
||||||
methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");;
|
|
||||||
methodGenerator.loadArg(0);
|
|
||||||
methodGenerator.checkCast(Type.getType(m.getDeclaringClass()));
|
|
||||||
methodGenerator.loadArg(1);
|
|
||||||
methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0]));
|
|
||||||
methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface());
|
|
||||||
if (m.getReturnType() != void.class) {
|
|
||||||
methodGenerator.pop();
|
|
||||||
}
|
|
||||||
methodGenerator.returnValue();
|
|
||||||
methodGenerator.endMethod();
|
|
||||||
writer.visitEnd();
|
|
||||||
return writer.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AtomicInteger NEXT_ID = new AtomicInteger(1);
|
|
||||||
@NotNull
|
|
||||||
public static String generateName() {
|
|
||||||
int id = NEXT_ID.getAndIncrement();
|
|
||||||
return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.executor.asm;
|
|
||||||
|
|
||||||
import com.destroystokyo.paper.utils.UnsafeUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface ClassDefiner {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the defined classes can bypass access checks
|
|
||||||
*
|
|
||||||
* @return if classes bypass access checks
|
|
||||||
*/
|
|
||||||
public default boolean isBypassAccessChecks() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define a class
|
|
||||||
*
|
|
||||||
* @param parentLoader the parent classloader
|
|
||||||
* @param name the name of the class
|
|
||||||
* @param data the class data to load
|
|
||||||
* @return the defined class
|
|
||||||
* @throws ClassFormatError if the class data is invalid
|
|
||||||
* @throws NullPointerException if any of the arguments are null
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static ClassDefiner getInstance() {
|
|
||||||
return SafeClassDefiner.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.executor.asm;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
public class SafeClassDefiner implements ClassDefiner {
|
|
||||||
/* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
|
|
||||||
|
|
||||||
private SafeClassDefiner() {}
|
|
||||||
|
|
||||||
private final ConcurrentMap<ClassLoader, GeneratedClassLoader> loaders = new MapMaker().weakKeys().makeMap();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) {
|
|
||||||
GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
|
|
||||||
synchronized (loader.getClassLoadingLock(name)) {
|
|
||||||
Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
|
|
||||||
Class<?> c = loader.define(name, data);
|
|
||||||
assert c.getName().equals(name);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class GeneratedClassLoader extends ClassLoader {
|
|
||||||
static {
|
|
||||||
ClassLoader.registerAsParallelCapable();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GeneratedClassLoader(@NotNull ClassLoader parent) {
|
|
||||||
super(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> define(@NotNull String name, byte[] data) {
|
|
||||||
synchronized (getClassLoadingLock(name)) {
|
|
||||||
assert !hasClass(name);
|
|
||||||
Class<?> c = defineClass(name, data, 0, data.length);
|
|
||||||
resolveClass(c);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public Object getClassLoadingLock(@NotNull String name) {
|
|
||||||
return super.getClassLoadingLock(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasClass(@NotNull String name) {
|
|
||||||
synchronized (getClassLoadingLock(name)) {
|
|
||||||
try {
|
|
||||||
Class.forName(name);
|
|
||||||
return true;
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class IllegalPacketEvent extends PlayerEvent {
|
|
||||||
@Nullable private final String type;
|
|
||||||
@Nullable private final String ex;
|
|
||||||
@Nullable private String kickMessage;
|
|
||||||
private boolean shouldKick = true;
|
|
||||||
|
|
||||||
public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) {
|
|
||||||
super(player);
|
|
||||||
this.type = type;
|
|
||||||
this.kickMessage = kickMessage;
|
|
||||||
this.ex = e.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isShouldKick() {
|
|
||||||
return shouldKick;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShouldKick(boolean shouldKick) {
|
|
||||||
this.shouldKick = shouldKick;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getKickMessage() {
|
|
||||||
return kickMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKickMessage(@Nullable String kickMessage) {
|
|
||||||
this.kickMessage = kickMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getExceptionMessage() {
|
|
||||||
return ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) {
|
|
||||||
IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception);
|
|
||||||
event.callEvent();
|
|
||||||
if (event.shouldKick) {
|
|
||||||
player.kickPlayer(kickMessage);
|
|
||||||
}
|
|
||||||
Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.advancement.Advancement;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player is granted a criteria in an advancement.
|
|
||||||
*/
|
|
||||||
public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
@NotNull private final Advancement advancement;
|
|
||||||
@NotNull private final String criterion;
|
|
||||||
private boolean cancel = false;
|
|
||||||
|
|
||||||
public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) {
|
|
||||||
super(who);
|
|
||||||
this.advancement = advancement;
|
|
||||||
this.criterion = criterion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the advancement which has been affected.
|
|
||||||
*
|
|
||||||
* @return affected advancement
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Advancement getAdvancement() {
|
|
||||||
return advancement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the criterion which has been granted.
|
|
||||||
*
|
|
||||||
* @return granted criterion
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getCriterion() {
|
|
||||||
return criterion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancel = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import static org.bukkit.Material.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the player themselves change their armor items
|
|
||||||
* <p>
|
|
||||||
* Not currently called for environmental factors though it <strong>MAY BE IN THE FUTURE</strong>
|
|
||||||
*/
|
|
||||||
public class PlayerArmorChangeEvent extends PlayerEvent {
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull private final SlotType slotType;
|
|
||||||
@Nullable private final ItemStack oldItem;
|
|
||||||
@Nullable private final ItemStack newItem;
|
|
||||||
|
|
||||||
public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable ItemStack newItem) {
|
|
||||||
super(player);
|
|
||||||
this.slotType = slotType;
|
|
||||||
this.oldItem = oldItem;
|
|
||||||
this.newItem = newItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type of slot being altered.
|
|
||||||
*
|
|
||||||
* @return type of slot being altered
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public SlotType getSlotType() {
|
|
||||||
return this.slotType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the existing item that's being replaced
|
|
||||||
*
|
|
||||||
* @return old item
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ItemStack getOldItem() {
|
|
||||||
return this.oldItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the new item that's replacing the old
|
|
||||||
*
|
|
||||||
* @return new item
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ItemStack getNewItem() {
|
|
||||||
return this.newItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SlotType {
|
|
||||||
HEAD(DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, PUMPKIN, JACK_O_LANTERN),
|
|
||||||
CHEST(DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA),
|
|
||||||
LEGS(DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS),
|
|
||||||
FEET(DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS);
|
|
||||||
|
|
||||||
private final Set<Material> mutableTypes = new HashSet<>();
|
|
||||||
private Set<Material> immutableTypes;
|
|
||||||
|
|
||||||
SlotType(Material... types) {
|
|
||||||
this.mutableTypes.addAll(Arrays.asList(types));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an immutable set of all allowed material types that can be placed in an
|
|
||||||
* armor slot.
|
|
||||||
*
|
|
||||||
* @return immutable set of material types
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Set<Material> getTypes() {
|
|
||||||
if (immutableTypes == null) {
|
|
||||||
immutableTypes = Collections.unmodifiableSet(mutableTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return immutableTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type of slot via the specified material
|
|
||||||
*
|
|
||||||
* @param material material to get slot by
|
|
||||||
* @return slot type the material will go in, or null if it won't
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static SlotType getByMaterial(@NotNull Material material) {
|
|
||||||
for (SlotType slotType : values()) {
|
|
||||||
if (slotType.getTypes().contains(material)) {
|
|
||||||
return slotType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether or not this material can be equipped to a slot
|
|
||||||
*
|
|
||||||
* @param material material to check
|
|
||||||
* @return whether or not this material can be equipped
|
|
||||||
*/
|
|
||||||
public static boolean isEquipable(@NotNull Material material) {
|
|
||||||
return getByMaterial(material) != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This event is invoked when a player has disconnected. It is guaranteed that,
|
|
||||||
* if the server is in online-mode, that the provided uuid and username have been
|
|
||||||
* validated.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The event is invoked for players who have not yet logged into the world, whereas
|
|
||||||
* {@link org.bukkit.event.player.PlayerQuitEvent} is only invoked on players who have logged into the world.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The event is invoked for players who have already logged into the world,
|
|
||||||
* although whether or not the player exists in the world at the time of
|
|
||||||
* firing is undefined. (That is, whether the plugin can retrieve a Player object
|
|
||||||
* using the event parameters is undefined). However, it is guaranteed that this
|
|
||||||
* event is invoked AFTER {@link org.bukkit.event.player.PlayerQuitEvent}, if the player has already logged into the world.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This event is guaranteed to never fire unless {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} has
|
|
||||||
* been fired beforehand, and this event may not be called in parallel with
|
|
||||||
* {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} for the same connection.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Cancelling the {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} guarantees the corresponding
|
|
||||||
* {@code PlayerConnectionCloseEvent} is never called.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The event may be invoked asynchronously or synchronously. Plugins should check
|
|
||||||
* {@link Event#isAsynchronous()} and handle accordingly.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public class PlayerConnectionCloseEvent extends Event {
|
|
||||||
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
|
||||||
|
|
||||||
@NotNull private final UUID playerUniqueId;
|
|
||||||
@NotNull private final String playerName;
|
|
||||||
@NotNull private final InetAddress ipAddress;
|
|
||||||
|
|
||||||
public PlayerConnectionCloseEvent(@NotNull final UUID playerUniqueId, @NotNull final String playerName, @NotNull final InetAddress ipAddress, final boolean async) {
|
|
||||||
super(async);
|
|
||||||
this.playerUniqueId = playerUniqueId;
|
|
||||||
this.playerName = playerName;
|
|
||||||
this.ipAddress = ipAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@code UUID} of the player disconnecting.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public UUID getPlayerUniqueId() {
|
|
||||||
return this.playerUniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the player disconnecting.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getPlayerName() {
|
|
||||||
return this.playerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the player's IP address.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public InetAddress getIpAddress() {
|
|
||||||
return this.ipAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Firework;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a player boosts elytra flight with a firework
|
|
||||||
*/
|
|
||||||
public class PlayerElytraBoostEvent extends PlayerEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancelled = false;
|
|
||||||
@NotNull private final ItemStack itemStack;
|
|
||||||
@NotNull private Firework firework;
|
|
||||||
private boolean consume = true;
|
|
||||||
|
|
||||||
public PlayerElytraBoostEvent(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull Firework firework) {
|
|
||||||
super(player);
|
|
||||||
this.itemStack = itemStack;
|
|
||||||
this.firework = firework;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the firework itemstack used
|
|
||||||
*
|
|
||||||
* @return ItemStack of firework
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public ItemStack getItemStack() {
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the firework entity that was spawned
|
|
||||||
*
|
|
||||||
* @return Firework entity
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Firework getFirework() {
|
|
||||||
return firework;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether to consume the firework or not
|
|
||||||
*
|
|
||||||
* @return True to consume
|
|
||||||
*/
|
|
||||||
public boolean shouldConsume() {
|
|
||||||
return consume;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether to consume the firework or not
|
|
||||||
*
|
|
||||||
* @param consume True to consume
|
|
||||||
*/
|
|
||||||
public void setShouldConsume(boolean consume) {
|
|
||||||
this.consume = consume;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
cancelled = cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This event is fired during a player handshake.
|
|
||||||
*
|
|
||||||
* <p>If there are no listeners listening to this event, the logic default
|
|
||||||
* to your server platform will be ran.</p>
|
|
||||||
*
|
|
||||||
* <p>WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS</p>
|
|
||||||
*/
|
|
||||||
public class PlayerHandshakeEvent extends Event implements Cancellable {
|
|
||||||
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
|
||||||
@NotNull private final String originalHandshake;
|
|
||||||
private boolean cancelled;
|
|
||||||
@Nullable private String serverHostname;
|
|
||||||
@Nullable private String socketAddressHostname;
|
|
||||||
@Nullable private UUID uniqueId;
|
|
||||||
@Nullable private String propertiesJson;
|
|
||||||
private boolean failed;
|
|
||||||
private String failMessage = "If you wish to use IP forwarding, please enable it in your BungeeCord config as well!";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link PlayerHandshakeEvent}.
|
|
||||||
*
|
|
||||||
* @param originalHandshake the original handshake string
|
|
||||||
* @param cancelled if this event is enabled
|
|
||||||
*/
|
|
||||||
public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) {
|
|
||||||
super(true);
|
|
||||||
this.originalHandshake = originalHandshake;
|
|
||||||
this.cancelled = cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if this event is cancelled.
|
|
||||||
*
|
|
||||||
* <p>When this event is cancelled, custom handshake logic will not
|
|
||||||
* be processed.</p>
|
|
||||||
*
|
|
||||||
* @return {@code true} if this event is cancelled, {@code false} otherwise
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return this.cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if this event is cancelled.
|
|
||||||
*
|
|
||||||
* <p>When this event is cancelled, custom handshake logic will not
|
|
||||||
* be processed.</p>
|
|
||||||
*
|
|
||||||
* @param cancelled {@code true} if this event is cancelled, {@code false} otherwise
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancelled) {
|
|
||||||
this.cancelled = cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the original handshake string.
|
|
||||||
*
|
|
||||||
* @return the original handshake string
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getOriginalHandshake() {
|
|
||||||
return this.originalHandshake;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the server hostname string.
|
|
||||||
*
|
|
||||||
* <p>This should not include the port.</p>
|
|
||||||
*
|
|
||||||
* @return the server hostname string
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public String getServerHostname() {
|
|
||||||
return this.serverHostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the server hostname string.
|
|
||||||
*
|
|
||||||
* <p>This should not include the port.</p>
|
|
||||||
*
|
|
||||||
* @param serverHostname the server hostname string
|
|
||||||
*/
|
|
||||||
public void setServerHostname(@NotNull String serverHostname) {
|
|
||||||
this.serverHostname = serverHostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the socket address hostname string.
|
|
||||||
*
|
|
||||||
* <p>This should not include the port.</p>
|
|
||||||
*
|
|
||||||
* @return the socket address hostname string
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public String getSocketAddressHostname() {
|
|
||||||
return this.socketAddressHostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the socket address hostname string.
|
|
||||||
*
|
|
||||||
* <p>This should not include the port.</p>
|
|
||||||
*
|
|
||||||
* @param socketAddressHostname the socket address hostname string
|
|
||||||
*/
|
|
||||||
public void setSocketAddressHostname(@NotNull String socketAddressHostname) {
|
|
||||||
this.socketAddressHostname = socketAddressHostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the unique id.
|
|
||||||
*
|
|
||||||
* @return the unique id
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public UUID getUniqueId() {
|
|
||||||
return this.uniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the unique id.
|
|
||||||
*
|
|
||||||
* @param uniqueId the unique id
|
|
||||||
*/
|
|
||||||
public void setUniqueId(@NotNull UUID uniqueId) {
|
|
||||||
this.uniqueId = uniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the profile properties.
|
|
||||||
*
|
|
||||||
* <p>This should be a valid JSON string.</p>
|
|
||||||
*
|
|
||||||
* @return the profile properties, as JSON
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public String getPropertiesJson() {
|
|
||||||
return this.propertiesJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if authentication failed.
|
|
||||||
*
|
|
||||||
* <p>When {@code true}, the client connecting will be disconnected
|
|
||||||
* with the {@link #getFailMessage() fail message}.</p>
|
|
||||||
*
|
|
||||||
* @return {@code true} if authentication failed, {@code false} otherwise
|
|
||||||
*/
|
|
||||||
public boolean isFailed() {
|
|
||||||
return this.failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if authentication failed and the client should be disconnected.
|
|
||||||
*
|
|
||||||
* <p>When {@code true}, the client connecting will be disconnected
|
|
||||||
* with the {@link #getFailMessage() fail message}.</p>
|
|
||||||
*
|
|
||||||
* @param failed {@code true} if authentication failed, {@code false} otherwise
|
|
||||||
*/
|
|
||||||
public void setFailed(boolean failed) {
|
|
||||||
this.failed = failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the profile properties.
|
|
||||||
*
|
|
||||||
* <p>This should be a valid JSON string.</p>
|
|
||||||
*
|
|
||||||
* @param propertiesJson the profile properties, as JSON
|
|
||||||
*/
|
|
||||||
public void setPropertiesJson(@NotNull String propertiesJson) {
|
|
||||||
this.propertiesJson = propertiesJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the message to display to the client when authentication fails.
|
|
||||||
*
|
|
||||||
* @return the message to display to the client
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getFailMessage() {
|
|
||||||
return this.failMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the message to display to the client when authentication fails.
|
|
||||||
*
|
|
||||||
* @param failMessage the message to display to the client
|
|
||||||
*/
|
|
||||||
public void setFailMessage(@NotNull String failMessage) {
|
|
||||||
Validate.notEmpty(failMessage, "fail message cannot be null or empty");
|
|
||||||
this.failMessage = failMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return HANDLERS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class PlayerInitialSpawnEvent extends PlayerEvent {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
@NotNull private Location spawnLocation;
|
|
||||||
|
|
||||||
public PlayerInitialSpawnEvent(@NotNull final Player player, @NotNull final Location spawnLocation) {
|
|
||||||
super(player);
|
|
||||||
this.spawnLocation = spawnLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current spawn location
|
|
||||||
*
|
|
||||||
* @return Location current spawn location
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getSpawnLocation() {
|
|
||||||
return this.spawnLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the new spawn location
|
|
||||||
*
|
|
||||||
* @param spawnLocation new location for the spawn
|
|
||||||
*/
|
|
||||||
public void setSpawnLocation(@NotNull Location spawnLocation) {
|
|
||||||
this.spawnLocation = spawnLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
package com.destroystokyo.paper.event.player;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the server detects the player is jumping.
|
|
||||||
* <p>
|
|
||||||
* Added to avoid the overhead and special case logic that many plugins use
|
|
||||||
* when checking for jumps via PlayerMoveEvent, this event is fired whenever
|
|
||||||
* the server detects that the player is jumping.
|
|
||||||
*/
|
|
||||||
public class PlayerJumpEvent extends PlayerEvent implements Cancellable {
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
private boolean cancel = false;
|
|
||||||
@NotNull private Location from;
|
|
||||||
@NotNull private Location to;
|
|
||||||
|
|
||||||
public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) {
|
|
||||||
super(player);
|
|
||||||
this.from = from;
|
|
||||||
this.to = to;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the cancellation state of this event. A cancelled event will not
|
|
||||||
* be executed in the server, but will still pass to other plugins
|
|
||||||
* <p>
|
|
||||||
* If a jump event is cancelled, the player will be moved or
|
|
||||||
* teleported back to the Location as defined by getFrom(). This will not
|
|
||||||
* fire an event
|
|
||||||
*
|
|
||||||
* @return true if this event is cancelled
|
|
||||||
*/
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the cancellation state of this event. A cancelled event will not
|
|
||||||
* be executed in the server, but will still pass to other plugins
|
|
||||||
* <p>
|
|
||||||
* If a jump event is cancelled, the player will be moved or
|
|
||||||
* teleported back to the Location as defined by getFrom(). This will not
|
|
||||||
* fire an event
|
|
||||||
*
|
|
||||||
* @param cancel true if you wish to cancel this event
|
|
||||||
*/
|
|
||||||
public void setCancelled(boolean cancel) {
|
|
||||||
this.cancel = cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the location this player jumped from
|
|
||||||
*
|
|
||||||
* @return Location the player jumped from
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getFrom() {
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the location to mark as where the player jumped from
|
|
||||||
*
|
|
||||||
* @param from New location to mark as the players previous location
|
|
||||||
*/
|
|
||||||
public void setFrom(@NotNull Location from) {
|
|
||||||
validateLocation(from);
|
|
||||||
this.from = from;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the location this player jumped to
|
|
||||||
*
|
|
||||||
* This information is based on what the client sends, it typically
|
|
||||||
* has little relation to the arc of the jump at any given point.
|
|
||||||
*
|
|
||||||
* @return Location the player jumped to
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public Location getTo() {
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateLocation(Location loc) {
|
|
||||||
Preconditions.checkArgument(loc != null, "Cannot use null location!");
|
|
||||||
Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user