Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
|
bee74680e6 | ||
|
0a44692ef6 | ||
|
e6137f7f1c | ||
|
7d1c30bc57 | ||
|
be328f1d29 | ||
|
ae3378abc9 | ||
|
4afd50fa36 |
4596 changed files with 646015 additions and 61781 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -62,8 +62,6 @@ out/
|
|||
# other stuff
|
||||
run/
|
||||
|
||||
Paper-Server
|
||||
Paper-API
|
||||
Paperclip.jar
|
||||
paperclip.jar
|
||||
paperclip-*.jar
|
||||
|
@ -71,5 +69,5 @@ paperclip.properties
|
|||
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
test-plugin.settings.gradle.kts
|
||||
paper-test-plugin.settings.gradle.kts
|
||||
paper-api-generator.settings.gradle.kts
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":paper-api"))
|
||||
api("com.mojang:brigadier:1.0.18")
|
||||
|
||||
compileOnly("it.unimi.dsi:fastutil:8.5.6")
|
||||
compileOnly("org.jetbrains:annotations:23.0.0")
|
||||
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
testImplementation("org.hamcrest:hamcrest-library:1.3")
|
||||
testImplementation("org.ow2.asm:asm-tree:9.2")
|
||||
}
|
||||
|
||||
configure<PublishingExtension> {
|
||||
publications.create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
|
||||
val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
|
||||
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
|
||||
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
|
||||
classpath.from(configurations.compileClasspath)
|
||||
}
|
||||
tasks.check {
|
||||
dependsOn(scanJar)
|
||||
}
|
|
@ -1,18 +1,9 @@
|
|||
# You can use this file to change the access modifiers on a member
|
||||
# This line would make the field rollAmount public in Bee
|
||||
#public net.minecraft.world.entity.animal.Bee rollAmount
|
||||
# This line would make the field public and remove the final modifier
|
||||
#public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender
|
||||
# Leave out the member and it will apply to the class itself
|
||||
# More info, see here https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers
|
||||
|
||||
# Remap/Decompile fix (unclear why this is happening)
|
||||
public net.minecraft.server.MinecraftServer doRunTask(Lnet/minecraft/server/TickTask;)V
|
||||
|
||||
# AT remap issue? todo 1.18
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight findExitPortal()Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;
|
||||
public net.minecraft.nbt.TagParser readArrayTag()Lnet/minecraft/nbt/Tag;
|
||||
|
||||
# TODO 1.20 remapSpigotAt.at doesn't remap the return type for this method for some reason
|
||||
public net/minecraft/world/entity/Display$TextDisplay getText()Lnet/minecraft/network/chat/Component;
|
||||
public net/minecraft/world/entity/Display$BlockDisplay getBlockState()Lnet/minecraft/world/level/block/state/BlockState;
|
||||
public net.minecraft.world.entity.Display$BlockDisplay getBlockState()Lnet/minecraft/world/level/block/state/BlockState;
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight findExitPortal()Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;
|
||||
public net.minecraft.server.MinecraftServer doRunTask(Lnet/minecraft/server/TickTask;)V
|
||||
public net.minecraft.CrashReport saveFile
|
||||
public+f net.minecraft.CrashReport getDetails()Ljava/lang/String;
|
||||
public+f net.minecraft.CrashReport getTitle()Ljava/lang/String;
|
||||
public+f net.minecraft.CrashReport getExceptionMessage()Ljava/lang/String;
|
||||
public net.minecraft.world.entity.Display$TextDisplay getText()Lnet/minecraft/network/chat/Component;
|
||||
|
|
|
@ -11,7 +11,7 @@ plugins {
|
|||
java
|
||||
`maven-publish`
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1" apply false
|
||||
id("io.papermc.paperweight.core") version "1.5.11"
|
||||
id("io.papermc.paperweight.core") version "2.0.0-SNAPSHOT"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
@ -67,43 +67,39 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
paramMappings("net.fabricmc:yarn:1.20.4+build.1:mergedv2")
|
||||
remapper("net.fabricmc:tiny-remapper:0.8.10:fat")
|
||||
paperclip("io.papermc:paperclip:3.0.3")
|
||||
mache("io.papermc:mache:1.20.4+build.1")
|
||||
|
||||
// only for patch remap
|
||||
paramMappings("net.fabricmc:yarn:1.20.2+build.1:mergedv2")
|
||||
remapper("net.fabricmc:tiny-remapper:0.8.6:fat")
|
||||
decompiler("net.minecraftforge:forgeflower:2.0.627.2")
|
||||
spigotDecompiler("io.papermc:patched-spigot-fernflower:0.1+build.6")
|
||||
paperclip("io.papermc:paperclip:3.0.3")
|
||||
}
|
||||
|
||||
paperweight {
|
||||
minecraftVersion = providers.gradleProperty("mcVersion")
|
||||
serverProject = project(":paper-server")
|
||||
softSpoon.set(true)
|
||||
|
||||
paramMappingsRepo = paperMavenPublicUrl
|
||||
remapRepo = paperMavenPublicUrl
|
||||
decompileRepo = paperMavenPublicUrl
|
||||
// todo we shouldn't need this anymore, this should come via mache?
|
||||
minecraftVersion.set(providers.gradleProperty("mcVersion"))
|
||||
serverProject.set(project(":paper-server"))
|
||||
|
||||
|
||||
// only for patch remap
|
||||
paramMappingsRepo.set(paperMavenPublicUrl)
|
||||
remapRepo.set(paperMavenPublicUrl)
|
||||
decompileRepo.set(paperMavenPublicUrl)
|
||||
|
||||
craftBukkit {
|
||||
fernFlowerJar = layout.file(spigotDecompiler.elements.map { it.single().asFile })
|
||||
fernFlowerJar.set(layout.file(spigotDecompiler.elements.map { it.single().asFile }))
|
||||
}
|
||||
|
||||
paper {
|
||||
spigotApiPatchDir = layout.projectDirectory.dir("patches/api")
|
||||
spigotServerPatchDir = layout.projectDirectory.dir("patches/server")
|
||||
mappingsPatch.set(layout.projectDirectory.file("build-data/mappings-patch.tiny"))
|
||||
reobfMappingsPatch.set(layout.projectDirectory.file("build-data/reobf-mappings-patch.tiny"))
|
||||
|
||||
mappingsPatch = layout.projectDirectory.file("build-data/mappings-patch.tiny")
|
||||
reobfMappingsPatch = layout.projectDirectory.file("build-data/reobf-mappings-patch.tiny")
|
||||
|
||||
reobfPackagesToFix.addAll(
|
||||
"co.aikar.timings",
|
||||
"com.destroystokyo.paper",
|
||||
"com.mojang",
|
||||
"io.papermc.paper",
|
||||
"ca.spottedleaf",
|
||||
"net.kyori.adventure.bossbar",
|
||||
"net.minecraft",
|
||||
"org.bukkit.craftbukkit",
|
||||
"org.spigotmc",
|
||||
)
|
||||
paperApiDir.set(layout.projectDirectory.dir("paper-api"))
|
||||
paperServerDir.set(layout.projectDirectory.dir("paper-server"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +207,7 @@ abstract class RebasePatches : BaseTask() {
|
|||
val f = redirect(proc.inputStream, out)
|
||||
|
||||
val exit = proc.waitFor()
|
||||
f.get()
|
||||
f.join()
|
||||
|
||||
if (exit != 0) {
|
||||
val outStr = String(out.toByteArray())
|
||||
|
@ -255,7 +251,7 @@ abstract class RebasePatches : BaseTask() {
|
|||
|
||||
val f1 = redirect(apply2.inputStream, System.out)
|
||||
apply2.waitFor()
|
||||
f1.get()
|
||||
f1.join()
|
||||
|
||||
logger.lifecycle(outStr)
|
||||
logger.lifecycle("Patch failed at $failed; See Git output above.")
|
||||
|
|
40
paper-api/.gitignore
vendored
Normal file
40
paper-api/.gitignore
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
.gradle/
|
||||
|
||||
# Eclipse stuff
|
||||
/.classpath
|
||||
/.project
|
||||
/.settings
|
||||
/.checkstyle
|
||||
/.factorypath
|
||||
|
||||
# netbeans
|
||||
/nbproject
|
||||
/nb-configuration.xml
|
||||
|
||||
# we use maven!
|
||||
/build.xml
|
||||
|
||||
# maven
|
||||
/target
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
||||
# various other potential build files
|
||||
/build
|
||||
/bin
|
||||
/dist
|
||||
/manifest.mf
|
||||
|
||||
# Mac filesystem dust
|
||||
.DS_Store
|
||||
|
||||
# intellij
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# vs code
|
||||
/.vscode
|
||||
/.factorypath
|
674
paper-api/LICENCE.txt
Normal file
674
paper-api/LICENCE.txt
Normal file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
203
paper-api/build.gradle.kts
Normal file
203
paper-api/build.gradle.kts
Normal file
|
@ -0,0 +1,203 @@
|
|||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
idea // Paper
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
val annotationsVersion = "24.0.1"
|
||||
val bungeeCordChatVersion = "1.20-R0.1"
|
||||
val adventureVersion = "4.14.0"
|
||||
val slf4jVersion = "2.0.9"
|
||||
val log4jVersion = "2.17.1"
|
||||
val apiAndDocs: Configuration by configurations.creating {
|
||||
attributes {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
||||
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES))
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
}
|
||||
}
|
||||
configurations.api {
|
||||
extendsFrom(apiAndDocs)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// api dependencies are listed transitively to API consumers
|
||||
api("com.google.guava:guava:32.1.2-jre")
|
||||
api("com.google.code.gson:gson:2.10.1")
|
||||
// Paper start - adventure
|
||||
api("net.md-5:bungeecord-chat:$bungeeCordChatVersion-deprecated+build.14") {
|
||||
exclude("com.google.guava", "guava")
|
||||
}
|
||||
// Paper - adventure
|
||||
api("org.yaml:snakeyaml:2.2")
|
||||
api("org.joml:joml:1.10.5")
|
||||
// Paper start
|
||||
api("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
isTransitive = false // includes junit
|
||||
}
|
||||
api("it.unimi.dsi:fastutil:8.5.6")
|
||||
apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
|
||||
apiAndDocs("net.kyori:adventure-api")
|
||||
apiAndDocs("net.kyori:adventure-text-minimessage")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-gson")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-plain")
|
||||
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
|
||||
api("org.apache.logging.log4j:log4j-api:$log4jVersion")
|
||||
api("org.slf4j:slf4j-api:$slf4jVersion")
|
||||
|
||||
implementation("org.ow2.asm:asm:9.5")
|
||||
implementation("org.ow2.asm:asm-commons:9.5")
|
||||
// Paper end
|
||||
|
||||
api("org.apache.maven:maven-resolver-provider:3.9.6") // Paper - make API dependency for Paper Plugins
|
||||
compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
|
||||
compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18")
|
||||
|
||||
val annotations = "org.jetbrains:annotations:$annotationsVersion" // Paper - we don't want Java 5 annotations...
|
||||
compileOnly(annotations)
|
||||
testCompileOnly(annotations)
|
||||
|
||||
// Paper start - add checker
|
||||
val checkerQual = "org.checkerframework:checker-qual:3.33.0"
|
||||
compileOnlyApi(checkerQual)
|
||||
testCompileOnly(checkerQual)
|
||||
// Paper end
|
||||
|
||||
api("com.mojang:brigadier:1.0.18")
|
||||
|
||||
testImplementation("org.apache.commons:commons-lang3:3.12.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
|
||||
testImplementation("org.hamcrest:hamcrest:2.2")
|
||||
testImplementation("org.mockito:mockito-core:5.5.0")
|
||||
testImplementation("org.ow2.asm:asm-tree:9.5")
|
||||
}
|
||||
|
||||
// Paper start
|
||||
val generatedApiPath: java.nio.file.Path = rootProject.projectDir.toPath().resolve("paper-api-generator/generated")
|
||||
idea {
|
||||
module {
|
||||
generatedSourceDirs.add(generatedApiPath.toFile())
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir(generatedApiPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
configure<PublishingExtension> {
|
||||
publications.create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
|
||||
val generateApiVersioningFile by tasks.registering {
|
||||
inputs.property("version", project.version)
|
||||
val pomProps = layout.buildDirectory.file("pom.properties")
|
||||
outputs.file(pomProps)
|
||||
val projectVersion = project.version
|
||||
doLast {
|
||||
pomProps.get().asFile.writeText("version=$projectVersion")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
from(generateApiVersioningFile.map { it.outputs.files.singleFile }) {
|
||||
into("META-INF/maven/${project.group}/${project.name}")
|
||||
}
|
||||
manifest {
|
||||
attributes(
|
||||
"Automatic-Module-Name" to "org.bukkit"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Javadoc> {
|
||||
val options = options as StandardJavadocDocletOptions
|
||||
options.overview = "src/main/javadoc/overview.html"
|
||||
options.use()
|
||||
options.isDocFilesSubDirs = true
|
||||
options.links(
|
||||
"https://guava.dev/releases/32.1.2-jre/api/docs/",
|
||||
"https://javadoc.io/doc/org.yaml/snakeyaml/2.2/",
|
||||
"https://javadoc.io/doc/org.jetbrains/annotations/$annotationsVersion/", // Paper - we don't want Java 5 annotations
|
||||
// "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", // Paper - don't link to bungee chat
|
||||
// Paper start - add missing javadoc links
|
||||
"https://javadoc.io/doc/org.joml/joml/1.10.5/index.html",
|
||||
"https://www.javadoc.io/doc/com.google.code.gson/gson/2.10.1",
|
||||
// Paper end
|
||||
// Paper start
|
||||
"https://jd.advntr.dev/api/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-minimessage/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-serializer-gson/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
|
||||
"https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/",
|
||||
"https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/$log4jVersion/",
|
||||
// Paper end
|
||||
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper
|
||||
)
|
||||
options.tags("apiNote:a:API Note:")
|
||||
|
||||
inputs.files(apiAndDocs).ignoreEmptyDirectories().withPropertyName(apiAndDocs.name + "-configuration")
|
||||
doFirst {
|
||||
options.addStringOption(
|
||||
"sourcepath",
|
||||
apiAndDocs.resolvedConfiguration.files.joinToString(separator = File.pathSeparator, transform = File::getPath)
|
||||
)
|
||||
}
|
||||
|
||||
// workaround for https://github.com/gradle/gradle/issues/4046
|
||||
inputs.dir("src/main/javadoc").withPropertyName("javadoc-sourceset")
|
||||
doLast {
|
||||
copy {
|
||||
from("src/main/javadoc") {
|
||||
include("**/doc-files/**")
|
||||
}
|
||||
into("build/docs/javadoc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// Paper start - compile tests with -parameters for better junit parameterized test names
|
||||
tasks.compileTestJava {
|
||||
options.compilerArgs.add("-parameters")
|
||||
}
|
||||
// Paper end
|
||||
|
||||
// Paper start
|
||||
val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
|
||||
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
|
||||
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
|
||||
classpath.from(configurations.compileClasspath)
|
||||
}
|
||||
tasks.check {
|
||||
dependsOn(scanJar)
|
||||
}
|
||||
// Paper end
|
||||
// Paper start
|
||||
val scanJarForOldGeneratedCode = tasks.register("scanJarForOldGeneratedCode", io.papermc.paperweight.tasks.ScanJarForOldGeneratedCode::class) {
|
||||
mcVersion.set(providers.gradleProperty("mcVersion"))
|
||||
annotation.set("Lio/papermc/paper/generated/GeneratedFrom;")
|
||||
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
|
||||
classpath.from(configurations.compileClasspath)
|
||||
}
|
||||
tasks.check {
|
||||
dependsOn(scanJarForOldGeneratedCode)
|
||||
}
|
||||
// Paper end
|
101
paper-api/checkstyle.xml
Normal file
101
paper-api/checkstyle.xml
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<!-- See http://checkstyle.sourceforge.net/config_misc.html#NewlineAtEndOfFile -->
|
||||
<module name="NewlineAtEndOfFile">
|
||||
<property name="lineSeparator" value="lf_cr_crlf"/>
|
||||
</module>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_whitespace.html -->
|
||||
<module name="FileTabCharacter"/>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_misc.html -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="\s+$"/>
|
||||
<property name="minimum" value="0"/>
|
||||
<property name="maximum" value="0"/>
|
||||
<property name="message" value="Line has trailing spaces."/>
|
||||
</module>
|
||||
|
||||
<!-- See https://checkstyle.sourceforge.io/config_javadoc.html#JavadocPackage-->
|
||||
<module name="JavadocPackage"/>
|
||||
|
||||
<module name="SuppressionSingleFilter">
|
||||
<property name="message" value="'(implNote|implSpec|apiNote)'\."/>
|
||||
</module>
|
||||
<!-- Don't check for missing package-info in tests -->
|
||||
<module name="SuppressionSingleFilter">
|
||||
<property name="checks" value="JavadocPackage"/>
|
||||
<property name="files" value=".*[\\/]src[\\/]test[\\/].*\.java$"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<!-- See https://checkstyle.org/config_javadoc.html -->
|
||||
<module name="AtclauseOrder"/>
|
||||
<module name="InvalidJavadocPosition"/>
|
||||
<module name="JavadocBlockTagLocation"/>
|
||||
<module name="JavadocContentLocationCheck"/>
|
||||
<module name="JavadocMethod"/>
|
||||
<module name="JavadocType"/>
|
||||
<module name="MissingJavadocPackage"/>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_filters.html -->
|
||||
<module name="SuppressionCommentFilter"/>
|
||||
<module name="SuppressionCommentFilter">
|
||||
<property name="offCommentFormat" value="Spigot start"/>
|
||||
<property name="onCommentFormat" value="Spigot end"/>
|
||||
</module>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_imports.html -->
|
||||
<module name="AvoidStarImport">
|
||||
<property name="allowStaticMemberImports" value="true"/>
|
||||
</module>
|
||||
<module name="ImportOrder">
|
||||
<property name="option" value="above"/>
|
||||
<property name="ordered" value="true"/>
|
||||
<property name="separatedStaticGroups" value="true"/>
|
||||
<property name="sortStaticImportsAlphabetically" value="true"/>
|
||||
</module>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
|
||||
<!-- See https://checkstyle.org/config_whitespace.html -->
|
||||
<module name="GenericWhitespace"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="NoWhitespaceAfter"/>
|
||||
<module name="NoWhitespaceBefore">
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
</module>
|
||||
<module name="OperatorWrap"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="SingleSpaceSeparator"/>
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyCatches" value="true"/>
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
<property name="allowEmptyTypes" value="true"/>
|
||||
</module>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_modifiers.html -->
|
||||
<module name="ModifierOrder"/>
|
||||
|
||||
<!-- See https://checkstyle.org/config_blocks.html -->
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly"/>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_design.html -->
|
||||
<module name="FinalClass"/>
|
||||
|
||||
<!-- See http://checkstyle.sourceforge.net/config_misc.html -->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="UpperEll"/>
|
||||
</module>
|
||||
</module>
|
|
@ -0,0 +1,86 @@
|
|||
package co.aikar.timings;
|
||||
|
||||
import static co.aikar.timings.TimingsManager.*;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
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();
|
||||
}
|
||||
Bukkit.getUnsafe().reportTimings();
|
||||
}
|
||||
|
||||
boolean isViolated() {
|
||||
return record.getCurTickTotal() > 50000000;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
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() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
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, (verbose ? "## " : "") +
|
||||
"Event: " + id + " (" + eventName + ")");
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return "TimedEventExecutor['" + this.executor.toString() + "']";
|
||||
}
|
||||
}
|
86
paper-api/src/main/java/co/aikar/timings/Timing.java
Normal file
86
paper-api/src/main/java/co/aikar/timings/Timing.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* @deprecated Timings will likely be replaced with Spark in the future
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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();
|
||||
}
|
122
paper-api/src/main/java/co/aikar/timings/TimingData.java
Normal file
122
paper-api/src/main/java/co/aikar/timings/TimingData.java
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
226
paper-api/src/main/java/co/aikar/timings/TimingHandler.java
Normal file
226
paper-api/src/main/java/co/aikar/timings/TimingHandler.java
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* 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;
|
||||
if ("Minecraft".equalsIgnoreCase(last.identifier.group)) {
|
||||
Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Look above this for any errors and report this to Paper unless it has a plugin in the stack trace (" + last.identifier + " did not stopTiming)");
|
||||
} else {
|
||||
Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + 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;
|
||||
}
|
||||
}
|
355
paper-api/src/main/java/co/aikar/timings/TimingHistory.java
Normal file
355
paper-api/src/main/java/co/aikar/timings/TimingHistory.java
Normal file
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* 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.*;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
116
paper-api/src/main/java/co/aikar/timings/TimingIdentifier.java
Normal file
116
paper-api/src/main/java/co/aikar/timings/TimingIdentifier.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
337
paper-api/src/main/java/co/aikar/timings/Timings.java
Normal file
337
paper-api/src/main/java/co/aikar/timings/Timings.java
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* 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 com.google.common.collect.Lists;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.logging.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @deprecated Timings will likely be replaced with Spark in the future
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"})
|
||||
public final class Timings {
|
||||
|
||||
final static List<CommandSender> requestingReport = Lists.newArrayList();
|
||||
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 static boolean warnedAboutDeprecationOnEnable;
|
||||
|
||||
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");
|
||||
Bukkit.getLogger().warning(String.format("Plugin '%s' is creating timing '%s' - this is deprecated behavior, please report it to the authors: %s", plugin.getName(), name, String.join(", ", plugin.getDescription().getAuthors())));
|
||||
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;
|
||||
warnAboutDeprecationOnEnable();
|
||||
reset();
|
||||
}
|
||||
|
||||
private static void warnAboutDeprecationOnEnable() {
|
||||
if (timingsEnabled && !warnedAboutDeprecationOnEnable) {
|
||||
Bukkit.getLogger().warning(PlainTextComponentSerializer.plainText().serialize(deprecationMessage()));
|
||||
warnedAboutDeprecationOnEnable = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Component deprecationMessage() {
|
||||
return Component.text()
|
||||
.color(TextColor.color(0xf3ef91))
|
||||
.append(Component.text("[!] The timings profiler has been enabled but has been scheduled for removal from Paper in the future."))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.text(" We recommend installing the spark profiler as a replacement: ")
|
||||
.append(
|
||||
Component.text()
|
||||
.content("https://spark.lucko.me/")
|
||||
.clickEvent(ClickEvent.openUrl("https://spark.lucko.me/")))
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.text(" For more information please visit: ")
|
||||
.append(
|
||||
Component.text()
|
||||
.content("https://github.com/PaperMC/Paper/issues/8948")
|
||||
.clickEvent(ClickEvent.openUrl("https://github.com/PaperMC/Paper/issues/8948")))
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* <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();
|
||||
}
|
||||
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) {
|
||||
Preconditions.checkNotNull(sender);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
124
paper-api/src/main/java/co/aikar/timings/TimingsCommand.java
Normal file
124
paper-api/src/main/java/co/aikar/timings/TimingsCommand.java
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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.ImmutableList;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
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 static net.kyori.adventure.text.Component.text;
|
||||
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
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 (false) {
|
||||
sender.sendMessage(Timings.deprecationMessage());
|
||||
}
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
final String arg = args[0];
|
||||
if ("on".equalsIgnoreCase(arg)) {
|
||||
Timings.setTimingsEnabled(true);
|
||||
sender.sendMessage(text("Enabled Timings & Reset"));
|
||||
return true;
|
||||
} else if ("off".equalsIgnoreCase(arg)) {
|
||||
Timings.setTimingsEnabled(false);
|
||||
sender.sendMessage(text("Disabled Timings"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Timings.isTimingsEnabled()) {
|
||||
sender.sendMessage(text("Please enable timings by typing /timings on"));
|
||||
return true;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if ("verbon".equalsIgnoreCase(arg)) {
|
||||
Timings.setVerboseTimingsEnabled(true);
|
||||
sender.sendMessage(text("Enabled Verbose Timings"));
|
||||
return true;
|
||||
} else if ("verboff".equalsIgnoreCase(arg)) {
|
||||
Timings.setVerboseTimingsEnabled(false);
|
||||
sender.sendMessage(text("Disabled Verbose Timings"));
|
||||
return true;
|
||||
} else if ("reset".equalsIgnoreCase(arg)) {
|
||||
if (now - lastResetAttempt < 30000) {
|
||||
TimingsManager.reset();
|
||||
sender.sendMessage(text("Timings reset. Please wait 5-10 minutes before using /timings report.", NamedTextColor.RED));
|
||||
} else {
|
||||
lastResetAttempt = now;
|
||||
sender.sendMessage(text("WARNING: Timings v2 should not be reset. If you are experiencing 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.", NamedTextColor.RED));
|
||||
}
|
||||
} else if (
|
||||
"paste".equalsIgnoreCase(arg) ||
|
||||
"report".equalsIgnoreCase(arg) ||
|
||||
"get".equalsIgnoreCase(arg) ||
|
||||
"merged".equalsIgnoreCase(arg) ||
|
||||
"separate".equalsIgnoreCase(arg)
|
||||
) {
|
||||
Timings.generateReport(sender);
|
||||
} else {
|
||||
sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||
Preconditions.checkNotNull(sender, "Sender cannot be null");
|
||||
Preconditions.checkNotNull(args, "Arguments cannot be null");
|
||||
Preconditions.checkNotNull(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();
|
||||
}
|
||||
}
|
192
paper-api/src/main/java/co/aikar/timings/TimingsManager.java
Normal file
192
paper-api/src/main/java/co/aikar/timings/TimingsManager.java
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* @deprecated Timings will likely be replaced with Spark in the future
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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 String url = "https://timings.aikar.co/";
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package co.aikar.timings;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class TimingsReportListener implements net.kyori.adventure.audience.ForwardingAudience, 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) {
|
||||
Preconditions.checkNotNull(senders);
|
||||
Preconditions.checkArgument(!senders.isEmpty(), "senders is empty");
|
||||
|
||||
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(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) {
|
||||
net.kyori.adventure.audience.ForwardingAudience.super.sendMessage(source, message, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
|
||||
return this.senders;
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
39
paper-api/src/main/java/co/aikar/util/Counter.java
Normal file
39
paper-api/src/main/java/co/aikar/util/Counter.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
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;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
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 increment(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;
|
||||
}
|
||||
}
|
141
paper-api/src/main/java/co/aikar/util/JSONUtil.java
Normal file
141
paper-api/src/main/java/co/aikar/util/JSONUtil.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
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"})
|
||||
@Deprecated(forRemoval = true)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
77
paper-api/src/main/java/co/aikar/util/LoadingIntMap.java
Normal file
77
paper-api/src/main/java/co/aikar/util/LoadingIntMap.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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();
|
||||
}
|
||||
}
|
369
paper-api/src/main/java/co/aikar/util/LoadingMap.java
Normal file
369
paper-api/src/main/java/co/aikar/util/LoadingMap.java
Normal file
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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();
|
||||
}
|
||||
}
|
112
paper-api/src/main/java/co/aikar/util/MRUMapCache.java
Normal file
112
paper-api/src/main/java/co/aikar/util/MRUMapCache.java
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.destroystokyo.paper;
|
||||
|
||||
import net.kyori.adventure.translation.Translatable;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.bukkit.inventory.MainHand;
|
||||
|
||||
public final class ClientOption<T> {
|
||||
|
||||
public static final ClientOption<SkinParts> SKIN_PARTS = new ClientOption<>(SkinParts.class);
|
||||
public static final ClientOption<Boolean> CHAT_COLORS_ENABLED = new ClientOption<>(Boolean.class);
|
||||
public static final ClientOption<ChatVisibility> CHAT_VISIBILITY = new ClientOption<>(ChatVisibility.class);
|
||||
public static final ClientOption<String> LOCALE = new ClientOption<>(String.class);
|
||||
public static final ClientOption<MainHand> MAIN_HAND = new ClientOption<>(MainHand.class);
|
||||
public static final ClientOption<Integer> VIEW_DISTANCE = new ClientOption<>(Integer.class);
|
||||
public static final ClientOption<Boolean> ALLOW_SERVER_LISTINGS = new ClientOption<>(Boolean.class);
|
||||
public static final ClientOption<Boolean> TEXT_FILTERING_ENABLED = new ClientOption<>(Boolean.class);
|
||||
|
||||
private final Class<T> type;
|
||||
|
||||
private ClientOption(@NotNull Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public enum ChatVisibility implements Translatable {
|
||||
FULL("full"),
|
||||
SYSTEM("system"),
|
||||
HIDDEN("hidden"),
|
||||
UNKNOWN("unknown");
|
||||
|
||||
public static Index<String, ChatVisibility> NAMES = Index.create(ChatVisibility.class, chatVisibility -> chatVisibility.name);
|
||||
private final String name;
|
||||
|
||||
ChatVisibility(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String translationKey() {
|
||||
if (this == UNKNOWN) {
|
||||
throw new UnsupportedOperationException(this.name + " doesn't have a translation key");
|
||||
}
|
||||
return "options.chat.visibility." + this.name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.destroystokyo.paper;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @deprecated Upstream has added their own API for using the game heightmaps. See {@link org.bukkit.HeightMap} and the
|
||||
* non-deprecated getHighestBlock methods on World such as {@link org.bukkit.World#getHighestBlockAt(org.bukkit.Location, org.bukkit.HeightMap)}.
|
||||
*/
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
|
||||
public enum HeightmapType {
|
||||
|
||||
/**
|
||||
* The highest block used for lighting in the world. Also the block returned by {@link org.bukkit.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;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
||||
*/
|
||||
|
||||
package com.destroystokyo.paper;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.papermc.paper.tag.BaseTag;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
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 extends BaseTag<Material, MaterialSetTag> {
|
||||
|
||||
/**
|
||||
* @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 != null ? key : NamespacedKey.randomKey(), materials, ((Predicate<Material>) Material::isLegacy).negate());
|
||||
}
|
||||
|
||||
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection<Material> materials, @NotNull Predicate<Material>...globalPredicates) {
|
||||
super(Material.class, key != null ? key : NamespacedKey.randomKey(), materials, globalPredicates);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Set<Material> getAllPossibleValues() {
|
||||
return Stream.of(Material.values()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String getName(@NotNull Material value) {
|
||||
return value.name();
|
||||
}
|
||||
|
||||
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.tagged.contains(material);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,717 @@
|
|||
/*
|
||||
* 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.
|
||||
* <p>
|
||||
* All tags in this class are unmodifiable, attempting to modify them will throw an
|
||||
* {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@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).lock();
|
||||
|
||||
/**
|
||||
* Covers all colors of beds.
|
||||
*/
|
||||
public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds"))
|
||||
.endsWith("_BED")
|
||||
.ensureSize("BEDS", 16).lock();
|
||||
|
||||
/**
|
||||
* Covers all bucket items.
|
||||
*/
|
||||
public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets"))
|
||||
.endsWith("BUCKET")
|
||||
.ensureSize("BUCKETS", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers coal and charcoal.
|
||||
*/
|
||||
public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals"))
|
||||
.add(Material.COAL, Material.CHARCOAL).lock();
|
||||
|
||||
/**
|
||||
* Covers both cobblestone wall variants.
|
||||
*/
|
||||
public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls"))
|
||||
.endsWith("COBBLESTONE_WALL")
|
||||
.ensureSize("COBBLESTONE_WALLS", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers both cobblestone and mossy Cobblestone.
|
||||
*/
|
||||
public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones"))
|
||||
.add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE).lock();
|
||||
|
||||
/**
|
||||
* Covers all colors of concrete.
|
||||
*/
|
||||
public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes"))
|
||||
.endsWith("_CONCRETE")
|
||||
.ensureSize("CONCRETES", 16).lock();
|
||||
|
||||
/**
|
||||
* Covers all colors of concrete powder.
|
||||
*/
|
||||
public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder"))
|
||||
.endsWith("_CONCRETE_POWDER")
|
||||
.ensureSize("CONCRETE_POWDER", 16).lock();
|
||||
|
||||
/**
|
||||
* 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).lock();
|
||||
|
||||
/**
|
||||
* Covers all variants of doors.
|
||||
*/
|
||||
public static final MaterialSetTag DOORS = new MaterialSetTag(keyFor("doors"))
|
||||
.endsWith("_DOOR")
|
||||
.ensureSize("DOORS", 20).lock();
|
||||
|
||||
/**
|
||||
* Covers all dyes.
|
||||
*/
|
||||
public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes"))
|
||||
.endsWith("_DYE")
|
||||
.ensureSize("DYES", 16).lock();
|
||||
|
||||
/**
|
||||
* Covers all variants of gates.
|
||||
*/
|
||||
public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates"))
|
||||
.endsWith("_GATE")
|
||||
.ensureSize("FENCE_GATES", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers all variants of fences.
|
||||
*/
|
||||
public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences"))
|
||||
.endsWith("_FENCE")
|
||||
.ensureSize("FENCES", 12).lock();
|
||||
|
||||
/**
|
||||
* Covers all 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).lock();
|
||||
|
||||
/**
|
||||
* 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", 18).lock();
|
||||
|
||||
/**
|
||||
* Covers the non-colored glass panes and stained glass panes (panes only).
|
||||
*/
|
||||
public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes"))
|
||||
.endsWith("GLASS_PANE")
|
||||
.ensureSize("GLASS_PANES", 17).lock();
|
||||
|
||||
/**
|
||||
* Covers all glazed terracotta blocks.
|
||||
*/
|
||||
public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta"))
|
||||
.endsWith("GLAZED_TERRACOTTA")
|
||||
.ensureSize("GLAZED_TERRACOTTA", 16).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* Covers terracotta along with the stained variants.
|
||||
*/
|
||||
public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta"))
|
||||
.endsWith("TERRACOTTA")
|
||||
.ensureSize("TERRACOTTA", 33).lock();
|
||||
|
||||
/**
|
||||
* Covers both golden apples.
|
||||
*/
|
||||
public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples"))
|
||||
.endsWith("GOLDEN_APPLE")
|
||||
.ensureSize("GOLDEN_APPLES", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of horse armor.
|
||||
*/
|
||||
public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors"))
|
||||
.endsWith("_HORSE_ARMOR")
|
||||
.ensureSize("HORSE_ARMORS", 4).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of infested blocks.
|
||||
*/
|
||||
public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks"))
|
||||
.startsWith("INFESTED_")
|
||||
.ensureSize("INFESTED_BLOCKS", 7).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* Covers all mushrooms.
|
||||
*/
|
||||
public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms"))
|
||||
.add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM).lock();
|
||||
|
||||
/**
|
||||
* Covers all music disc items.
|
||||
*/
|
||||
public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs"))
|
||||
.startsWith("MUSIC_DISC_").lock();
|
||||
|
||||
/**
|
||||
* Covers all ores.
|
||||
*/
|
||||
public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores"))
|
||||
.add(Material.ANCIENT_DEBRIS)
|
||||
.endsWith("_ORE")
|
||||
.ensureSize("ORES", 19).lock();
|
||||
|
||||
/**
|
||||
* 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).lock();
|
||||
|
||||
/**
|
||||
* Covers all potato items.
|
||||
*/
|
||||
public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes"))
|
||||
.endsWith("POTATO")
|
||||
.ensureSize("POTATOES", 3).lock();
|
||||
|
||||
/**
|
||||
* Covers all wooden pressure plates and the weighted pressure plates and the stone pressure plate.
|
||||
*/
|
||||
public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates"))
|
||||
.endsWith("_PRESSURE_PLATE")
|
||||
.ensureSize("PRESSURE_PLATES", 15).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of prismarine blocks.
|
||||
*/
|
||||
public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine"))
|
||||
.add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of pumpkins.
|
||||
*/
|
||||
public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins"))
|
||||
.add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* 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).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of red sandstone blocks.
|
||||
*/
|
||||
public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones"))
|
||||
.endsWith("RED_SANDSTONE")
|
||||
.ensureSize("RED_SANDSTONES", 4).lock();
|
||||
|
||||
/**
|
||||
* Covers the 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).lock();
|
||||
|
||||
/**
|
||||
* Covers sponge and wet sponge.
|
||||
*/
|
||||
public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges"))
|
||||
.endsWith("SPONGE")
|
||||
.ensureSize("SPONGES", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the non-colored and colored shulker boxes.
|
||||
*/
|
||||
public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes"))
|
||||
.endsWith("SHULKER_BOX")
|
||||
.ensureSize("SHULKER_BOXES", 17).lock();
|
||||
|
||||
/**
|
||||
* 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", 14).lock();
|
||||
|
||||
/**
|
||||
* Covers all spawn egg items.
|
||||
*/
|
||||
public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs"))
|
||||
.endsWith("_SPAWN_EGG")
|
||||
.ensureSize("SPAWN_EGGS", 78).lock();
|
||||
|
||||
/**
|
||||
* Covers all colors of stained glass.
|
||||
*/
|
||||
public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass"))
|
||||
.endsWith("_STAINED_GLASS")
|
||||
.ensureSize("STAINED_GLASS", 16).lock();
|
||||
|
||||
/**
|
||||
* Covers all 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).lock();
|
||||
|
||||
/**
|
||||
* Covers all variants of trapdoors.
|
||||
*/
|
||||
public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors"))
|
||||
.endsWith("_TRAPDOOR")
|
||||
.ensureSize("TRAPDOORS", 20).lock();
|
||||
|
||||
/**
|
||||
* Covers all wood variants of doors.
|
||||
*/
|
||||
public static final MaterialSetTag WOODEN_DOORS = new MaterialSetTag(keyFor("wooden_doors"))
|
||||
.endsWith("_DOOR")
|
||||
.not(Material.IRON_DOOR)
|
||||
.notContains("COPPER")
|
||||
.ensureSize("WOODEN_DOORS", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers all 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", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers all wood variants of trapdoors.
|
||||
*/
|
||||
public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors"))
|
||||
.endsWith("_TRAPDOOR")
|
||||
.not(Material.IRON_TRAPDOOR)
|
||||
.notContains("COPPER")
|
||||
.ensureSize("WOODEN_TRAPDOORS", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers the wood variants of gates.
|
||||
*/
|
||||
public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates"))
|
||||
.endsWith("_GATE")
|
||||
.ensureSize("WOODEN_GATES", 11).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of purpur.
|
||||
*/
|
||||
public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur"))
|
||||
.startsWith("PURPUR_")
|
||||
.ensureSize("PURPUR", 4).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of signs.
|
||||
*/
|
||||
public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs"))
|
||||
.endsWith("_SIGN")
|
||||
.ensureSize("SIGNS", 44).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of a regular torch.
|
||||
*/
|
||||
public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch"))
|
||||
.add(Material.TORCH, Material.WALL_TORCH)
|
||||
.ensureSize("TORCH", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of a redstone torch.
|
||||
*/
|
||||
public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch"))
|
||||
.add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH)
|
||||
.ensureSize("REDSTONE_TORCH", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of a soul torch.
|
||||
*/
|
||||
public static final MaterialSetTag SOUL_TORCH = new MaterialSetTag(keyFor("soul_torch"))
|
||||
.add(Material.SOUL_TORCH, Material.SOUL_WALL_TORCH)
|
||||
.ensureSize("SOUL_TORCH", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of torches.
|
||||
*/
|
||||
public static final MaterialSetTag TORCHES = new MaterialSetTag(keyFor("torches"))
|
||||
.add(TORCH, REDSTONE_TORCH, SOUL_TORCH)
|
||||
.ensureSize("TORCHES", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of lanterns.
|
||||
*/
|
||||
public static final MaterialSetTag LANTERNS = new MaterialSetTag(keyFor("lanterns"))
|
||||
.add(Material.LANTERN, Material.SOUL_LANTERN)
|
||||
.ensureSize("LANTERNS", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of rails.
|
||||
*/
|
||||
public static final MaterialSetTag RAILS = new MaterialSetTag(keyFor("rails"))
|
||||
.endsWith("RAIL")
|
||||
.ensureSize("RAILS", 4).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of swords.
|
||||
*/
|
||||
public static final MaterialSetTag SWORDS = new MaterialSetTag(keyFor("swords"))
|
||||
.endsWith("_SWORD")
|
||||
.ensureSize("SWORDS", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of shovels.
|
||||
*/
|
||||
public static final MaterialSetTag SHOVELS = new MaterialSetTag(keyFor("shovels"))
|
||||
.endsWith("_SHOVEL")
|
||||
.ensureSize("SHOVELS", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of pickaxes.
|
||||
*/
|
||||
public static final MaterialSetTag PICKAXES = new MaterialSetTag(keyFor("pickaxes"))
|
||||
.endsWith("_PICKAXE")
|
||||
.ensureSize("PICKAXES", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of axes.
|
||||
*/
|
||||
public static final MaterialSetTag AXES = new MaterialSetTag(keyFor("axes"))
|
||||
.endsWith("_AXE")
|
||||
.ensureSize("AXES", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of hoes.
|
||||
*/
|
||||
public static final MaterialSetTag HOES = new MaterialSetTag(keyFor("hoes"))
|
||||
.endsWith("_HOE")
|
||||
.ensureSize("HOES", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of helmets.
|
||||
*/
|
||||
public static final MaterialSetTag HELMETS = new MaterialSetTag(keyFor("helmets"))
|
||||
.endsWith("_HELMET")
|
||||
.ensureSize("HELMETS", 7).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of items that can be equipped in the helmet slot.
|
||||
*/
|
||||
public static final MaterialSetTag HEAD_EQUIPPABLE = new MaterialSetTag(keyFor("head_equippable"))
|
||||
.endsWith("_HELMET")
|
||||
.add(SKULLS)
|
||||
.add(Material.CARVED_PUMPKIN)
|
||||
.ensureSize("HEAD_EQUIPPABLE", 22).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of chestplate.
|
||||
*/
|
||||
public static final MaterialSetTag CHESTPLATES = new MaterialSetTag(keyFor("chestplates"))
|
||||
.endsWith("_CHESTPLATE")
|
||||
.ensureSize("CHESTPLATES", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of items that can be equipped in the chest slot.
|
||||
*/
|
||||
public static final MaterialSetTag CHEST_EQUIPPABLE = new MaterialSetTag(keyFor("chest_equippable"))
|
||||
.endsWith("_CHESTPLATE")
|
||||
.add(Material.ELYTRA)
|
||||
.ensureSize("CHEST_EQUIPPABLE", 7).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of leggings.
|
||||
*/
|
||||
public static final MaterialSetTag LEGGINGS = new MaterialSetTag(keyFor("leggings"))
|
||||
.endsWith("_LEGGINGS")
|
||||
.ensureSize("LEGGINGS", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of boots.
|
||||
*/
|
||||
public static final MaterialSetTag BOOTS = new MaterialSetTag(keyFor("boots"))
|
||||
.endsWith("_BOOTS")
|
||||
.ensureSize("BOOTS", 6).lock();
|
||||
|
||||
/**
|
||||
* Covers all variants of armor.
|
||||
*/
|
||||
public static final MaterialSetTag ARMOR = new MaterialSetTag(keyFor("armor")).add(HELMETS, CHESTPLATES, LEGGINGS, BOOTS)
|
||||
.ensureSize("ARMOR", 25).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of bows.
|
||||
*/
|
||||
public static final MaterialSetTag BOWS = new MaterialSetTag(keyFor("bows"))
|
||||
.add(Material.BOW)
|
||||
.add(Material.CROSSBOW)
|
||||
.ensureSize("BOWS", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of player-throwable projectiles (not requiring a bow or any other "assistance").
|
||||
*/
|
||||
public static final MaterialSetTag THROWABLE_PROJECTILES = new MaterialSetTag(keyFor("throwable_projectiles"))
|
||||
.add(Material.EGG, Material.SNOWBALL, Material.SPLASH_POTION, Material.TRIDENT, Material.ENDER_PEARL, Material.EXPERIENCE_BOTTLE, Material.FIREWORK_ROCKET).lock();
|
||||
|
||||
/**
|
||||
* Covers materials that can be colored, such as wool, shulker boxes, stained glass etc.
|
||||
*/
|
||||
@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).lock();
|
||||
//.ensureSize("COLORABLE", 81).lock(); unit test don't have the vanilla item tags, so counts don't line up for real
|
||||
|
||||
/**
|
||||
* Covers the variants of coral.
|
||||
*/
|
||||
public static final MaterialSetTag CORAL = new MaterialSetTag(keyFor("coral"))
|
||||
.endsWith("_CORAL")
|
||||
.ensureSize("CORAL", 10).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of coral fans.
|
||||
*/
|
||||
public static final MaterialSetTag CORAL_FANS = new MaterialSetTag(keyFor("coral_fans"))
|
||||
.endsWith("_CORAL_FAN")
|
||||
.endsWith("_CORAL_WALL_FAN")
|
||||
.ensureSize("CORAL_FANS", 20).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of coral blocks.
|
||||
*/
|
||||
public static final MaterialSetTag CORAL_BLOCKS = new MaterialSetTag(keyFor("coral_blocks"))
|
||||
.endsWith("_CORAL_BLOCK")
|
||||
.ensureSize("CORAL_BLOCKS", 10).lock();
|
||||
|
||||
/**
|
||||
* Covers all items that can be enchanted from the enchantment table or anvil.
|
||||
*/
|
||||
public static final MaterialSetTag ENCHANTABLE = new MaterialSetTag(keyFor("enchantable"))
|
||||
.add(PICKAXES, SWORDS, SHOVELS, AXES, HOES, HELMETS, CHEST_EQUIPPABLE, LEGGINGS, BOOTS, BOWS)
|
||||
.add(Material.TRIDENT, Material.SHIELD, Material.FISHING_ROD, Material.SHEARS,
|
||||
Material.FLINT_AND_STEEL, Material.CARROT_ON_A_STICK, Material.WARPED_FUNGUS_ON_A_STICK,
|
||||
Material.BRUSH, Material.CARVED_PUMPKIN, Material.COMPASS, Material.SKELETON_SKULL,
|
||||
Material.WITHER_SKELETON_SKULL, Material.PLAYER_HEAD, Material.ZOMBIE_HEAD,
|
||||
Material.CREEPER_HEAD, Material.DRAGON_HEAD, Material.PIGLIN_HEAD)
|
||||
.ensureSize("ENCHANTABLE", 75).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of raw ores.
|
||||
*/
|
||||
public static final MaterialSetTag RAW_ORES = new MaterialSetTag(keyFor("raw_ores"))
|
||||
.add(Material.RAW_COPPER, Material.RAW_GOLD, Material.RAW_IRON).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of deepslate ores.
|
||||
*/
|
||||
public static final MaterialSetTag DEEPSLATE_ORES = new MaterialSetTag(keyFor("deepslate_ores"))
|
||||
.add(material -> material.name().startsWith("DEEPSLATE_") && material.name().endsWith("_ORE"))
|
||||
.ensureSize("DEEPSLATE_ORES", 8).lock();
|
||||
|
||||
/**
|
||||
* Covers the variants of raw ore blocks.
|
||||
*/
|
||||
public static final MaterialSetTag RAW_ORE_BLOCKS = new MaterialSetTag(keyFor("raw_ore_blocks"))
|
||||
.add(Material.RAW_COPPER_BLOCK, Material.RAW_GOLD_BLOCK, Material.RAW_IRON_BLOCK).lock();
|
||||
|
||||
/**
|
||||
* Covers all oxidized copper blocks.
|
||||
*/
|
||||
public static final MaterialSetTag OXIDIZED_COPPER_BLOCKS = new MaterialSetTag(keyFor("oxidized_copper_blocks"))
|
||||
.startsWith("OXIDIZED_").startsWith("WAXED_OXIDIZED_").ensureSize("OXIDIZED_COPPER_BLOCKS", 18).lock();
|
||||
|
||||
/**
|
||||
* Covers all weathered copper blocks.
|
||||
*/
|
||||
public static final MaterialSetTag WEATHERED_COPPER_BLOCKS = new MaterialSetTag(keyFor("weathered_copper_blocks"))
|
||||
.startsWith("WEATHERED_").startsWith("WAXED_WEATHERED_").ensureSize("WEATHERED_COPPER_BLOCKS", 18).lock();
|
||||
|
||||
/**
|
||||
* Covers all exposed copper blocks.
|
||||
*/
|
||||
public static final MaterialSetTag EXPOSED_COPPER_BLOCKS = new MaterialSetTag(keyFor("exposed_copper_blocks"))
|
||||
.startsWith("EXPOSED_").startsWith("WAXED_EXPOSED_").ensureSize("EXPOSED_COPPER_BLOCKS", 18).lock();
|
||||
|
||||
/**
|
||||
* Covers all un-weathered copper blocks.
|
||||
*/
|
||||
public static final MaterialSetTag UNAFFECTED_COPPER_BLOCKS = new MaterialSetTag(keyFor("unaffected_copper_blocks"))
|
||||
.startsWith("CUT_COPPER").startsWith("WAXED_CUT_COPPER")
|
||||
.startsWith("WAXED_COPPER_").startsWith("COPPER_")
|
||||
.add(Material.CHISELED_COPPER, Material.WAXED_CHISELED_COPPER)
|
||||
.not(Material.COPPER_INGOT, Material.COPPER_ORE)
|
||||
.ensureSize("UNAFFECTED_COPPER_BLOCKS", 18).lock();
|
||||
|
||||
/**
|
||||
* Covers all waxed copper blocks.
|
||||
* <p>
|
||||
* Combine with other copper-related tags to filter is-waxed or not.
|
||||
*/
|
||||
public static final MaterialSetTag WAXED_COPPER_BLOCKS = new MaterialSetTag(keyFor("waxed_copper_blocks"))
|
||||
.add(m -> m.name().startsWith("WAXED_") && m.name().contains("COPPER")).ensureSize("WAXED_COPPER_BLOCKS", 36).lock();
|
||||
|
||||
/**
|
||||
* Covers all un-waxed copper blocks.
|
||||
* <p>
|
||||
* Combine with other copper-related tags to filter is-un-waxed or not.
|
||||
*/
|
||||
public static final MaterialSetTag UNWAXED_COPPER_BLOCKS = new MaterialSetTag(keyFor("unwaxed_copper_blocks"))
|
||||
.startsWith("EXPOSED_").startsWith("WEATHERED_").startsWith("OXIDIZED_")
|
||||
.startsWith("CUT_COPPER")
|
||||
.add(Material.COPPER_BLOCK, Material.CHISELED_COPPER, Material.COPPER_DOOR, Material.COPPER_TRAPDOOR, Material.COPPER_GRATE, Material.COPPER_BULB)
|
||||
.ensureSize("UNWAXED_COPPER_BLOCKS", 36).lock();
|
||||
|
||||
/**
|
||||
* Covers all copper block variants.
|
||||
*/
|
||||
public static final MaterialSetTag COPPER_BLOCKS = new MaterialSetTag(keyFor("copper_blocks"))
|
||||
.add(WAXED_COPPER_BLOCKS).add(UNWAXED_COPPER_BLOCKS).ensureSize("COPPER_BLOCKS", 72).lock();
|
||||
|
||||
/**
|
||||
* Covers all weathering/waxed states of the plain copper block.
|
||||
*/
|
||||
public static final MaterialSetTag FULL_COPPER_BLOCKS = new MaterialSetTag(keyFor("full_copper_blocks"))
|
||||
.endsWith("OXIDIZED_COPPER")
|
||||
.endsWith("WEATHERED_COPPER")
|
||||
.endsWith("EXPOSED_COPPER")
|
||||
.endsWith("COPPER_BLOCK")
|
||||
.not(Material.RAW_COPPER_BLOCK)
|
||||
.ensureSize("FULL_COPPER_BLOCKS", 8).lock();
|
||||
|
||||
/**
|
||||
* Covers all weathering/waxed states of the cut copper block.
|
||||
*/
|
||||
public static final MaterialSetTag CUT_COPPER_BLOCKS = new MaterialSetTag(keyFor("cut_copper_blocks"))
|
||||
.endsWith("CUT_COPPER").ensureSize("CUT_COPPER_BLOCKS", 8).lock();
|
||||
|
||||
/**
|
||||
* Covers all weathering/waxed states of the cut copper stairs.
|
||||
*/
|
||||
public static final MaterialSetTag CUT_COPPER_STAIRS = new MaterialSetTag(keyFor("cut_copper_stairs"))
|
||||
.endsWith("CUT_COPPER_STAIRS").ensureSize("CUT_COPPER_STAIRS", 8).lock();
|
||||
|
||||
/**
|
||||
* Covers all weathering/waxed states of the cut copper slab.
|
||||
*/
|
||||
public static final MaterialSetTag CUT_COPPER_SLABS = new MaterialSetTag(keyFor("cut_copper_slabs"))
|
||||
.endsWith("CUT_COPPER_SLAB").ensureSize("CUT_COPPER_SLABS", 8).lock();
|
||||
|
||||
/**
|
||||
* Covers all Wooden Tools.
|
||||
*/
|
||||
public static final MaterialSetTag WOODEN_TOOLS = new MaterialSetTag(keyFor("wooden_tools"))
|
||||
.add(Material.WOODEN_AXE, Material.WOODEN_HOE, Material.WOODEN_PICKAXE, Material.WOODEN_SHOVEL, Material.WOODEN_SWORD)
|
||||
.ensureSize("WOODEN_TOOLS", 5).lock();
|
||||
|
||||
/**
|
||||
* Covers all Stone Tools.
|
||||
*/
|
||||
public static final MaterialSetTag STONE_TOOLS = new MaterialSetTag(keyFor("stone_tools"))
|
||||
.add(Material.STONE_AXE, Material.STONE_HOE, Material.STONE_PICKAXE, Material.STONE_SHOVEL, Material.STONE_SWORD)
|
||||
.ensureSize("STONE_TOOLS", 5).lock();
|
||||
|
||||
/**
|
||||
* Covers all Iron Tools.
|
||||
*/
|
||||
public static final MaterialSetTag IRON_TOOLS = new MaterialSetTag(keyFor("iron_tools"))
|
||||
.add(Material.IRON_AXE, Material.IRON_HOE, Material.IRON_PICKAXE, Material.IRON_SHOVEL, Material.IRON_SWORD)
|
||||
.ensureSize("IRON_TOOLS", 5).lock();
|
||||
|
||||
/**
|
||||
* Covers all Gold Tools.
|
||||
*/
|
||||
public static final MaterialSetTag GOLDEN_TOOLS = new MaterialSetTag(keyFor("golden_tools"))
|
||||
.add(Material.GOLDEN_AXE, Material.GOLDEN_HOE, Material.GOLDEN_PICKAXE, Material.GOLDEN_SHOVEL, Material.GOLDEN_SWORD)
|
||||
.ensureSize("GOLDEN_TOOLS", 5).lock();
|
||||
|
||||
/**
|
||||
* Covers all Diamond Tools.
|
||||
*/
|
||||
public static final MaterialSetTag DIAMOND_TOOLS = new MaterialSetTag(keyFor("diamond_tools"))
|
||||
.add(Material.DIAMOND_AXE, Material.DIAMOND_HOE, Material.DIAMOND_PICKAXE, Material.DIAMOND_SHOVEL, Material.DIAMOND_SWORD)
|
||||
.ensureSize("DIAMOND_TOOLS", 5).lock();
|
||||
|
||||
/**
|
||||
* Covers all Netherite Tools.
|
||||
*/
|
||||
public static final MaterialSetTag NETHERITE_TOOLS = new MaterialSetTag(keyFor("netherite_tools"))
|
||||
.add(Material.NETHERITE_AXE, Material.NETHERITE_HOE, Material.NETHERITE_PICKAXE, Material.NETHERITE_SHOVEL, Material.NETHERITE_SWORD)
|
||||
.ensureSize("NETHERITE_TOOLS", 5).lock();
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
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();
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,485 @@
|
|||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the particle is forcefully shown to players.
|
||||
*/
|
||||
public boolean force() {
|
||||
return force;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.destroystokyo.paper;
|
||||
|
||||
public interface SkinParts {
|
||||
|
||||
boolean hasCapeEnabled();
|
||||
|
||||
boolean hasJacketEnabled();
|
||||
|
||||
boolean hasLeftSleeveEnabled();
|
||||
|
||||
boolean hasRightSleeveEnabled();
|
||||
|
||||
boolean hasLeftPantsEnabled();
|
||||
|
||||
boolean hasRightPantsEnabled();
|
||||
|
||||
boolean hasHatsEnabled();
|
||||
|
||||
int getRaw();
|
||||
}
|
420
paper-api/src/main/java/com/destroystokyo/paper/Title.java
Normal file
420
paper-api/src/main/java/com/destroystokyo/paper/Title.java
Normal file
|
@ -0,0 +1,420 @@
|
|||
package com.destroystokyo.paper;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
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>
|
||||
*
|
||||
* @deprecated use {@link net.kyori.adventure.title.Title}
|
||||
*/
|
||||
@Deprecated
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the title directly to an player
|
||||
*
|
||||
* @param player the receiver of the title
|
||||
*/
|
||||
public void send(@NotNull Player player) {
|
||||
player.sendTitle(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the title directly to the defined players
|
||||
*
|
||||
* @param players the receivers of the title
|
||||
*/
|
||||
public void send(@NotNull Collection<? extends Player> players) {
|
||||
for (Player player : players) {
|
||||
player.sendTitle(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the title directly to the defined players
|
||||
*
|
||||
* @param players the receivers of the title
|
||||
*/
|
||||
public void send(@NotNull Player[] players) {
|
||||
for (Player player : players) {
|
||||
player.sendTitle(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the title directly to all online players
|
||||
*/
|
||||
public void broadcast() {
|
||||
send(Bukkit.getOnlinePlayers());
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
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.
|
||||
* @deprecated use {@link org.bukkit.SoundGroup}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public interface BlockSoundGroup {
|
||||
/**
|
||||
* Gets the sound that plays when breaking this block
|
||||
*
|
||||
* @return The break sound
|
||||
* @deprecated use {@link org.bukkit.SoundGroup#getBreakSound()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
Sound getBreakSound();
|
||||
|
||||
/**
|
||||
* Gets the sound that plays when stepping on this block
|
||||
*
|
||||
* @return The step sound
|
||||
* @deprecated use {@link org.bukkit.SoundGroup#getStepSound()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
Sound getStepSound();
|
||||
|
||||
/**
|
||||
* Gets the sound that plays when placing this block
|
||||
*
|
||||
* @return The place sound
|
||||
* @deprecated use {@link org.bukkit.SoundGroup#getPlaceSound()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
Sound getPlaceSound();
|
||||
|
||||
/**
|
||||
* Gets the sound that plays when hitting this block
|
||||
*
|
||||
* @return The hit sound
|
||||
* @deprecated use {@link org.bukkit.SoundGroup#getHitSound()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
Sound getHitSound();
|
||||
|
||||
/**
|
||||
* Gets the sound that plays when this block falls
|
||||
*
|
||||
* @return The fall sound
|
||||
* @deprecated use {@link org.bukkit.SoundGroup#getFallSound()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
Sound getFallSound();
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.destroystokyo.paper.block;
|
||||
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents information about a targeted block
|
||||
* @deprecated use {@link org.bukkit.util.RayTraceResult}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link org.bukkit.FluidCollisionMode}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public enum FluidMode {
|
||||
NEVER(FluidCollisionMode.NEVER),
|
||||
SOURCE_ONLY(FluidCollisionMode.SOURCE_ONLY),
|
||||
ALWAYS(FluidCollisionMode.ALWAYS);
|
||||
|
||||
public final FluidCollisionMode bukkit;
|
||||
|
||||
FluidMode(FluidCollisionMode bukkit) {
|
||||
this.bukkit = bukkit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
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);
|
||||
|
||||
/**
|
||||
* Checks if this pathfinder allows passing through closed doors.
|
||||
*
|
||||
* @return if this pathfinder allows passing through closed doors
|
||||
*/
|
||||
boolean canOpenDoors();
|
||||
|
||||
/**
|
||||
* Allows this pathfinder to pass through closed doors, or not
|
||||
*
|
||||
* @param canOpenDoors if the mob can pass through closed doors, or not
|
||||
*/
|
||||
void setCanOpenDoors(boolean canOpenDoors);
|
||||
|
||||
/**
|
||||
* Checks if this pathfinder allows passing through open doors.
|
||||
*
|
||||
* @return if this pathfinder allows passing through open doors
|
||||
*/
|
||||
boolean canPassDoors();
|
||||
|
||||
/**
|
||||
* Allows this pathfinder to pass through open doors, or not
|
||||
*
|
||||
* @param canPassDoors if the mob can pass through open doors, or not
|
||||
*/
|
||||
void setCanPassDoors(boolean canPassDoors);
|
||||
|
||||
/**
|
||||
* Checks if this pathfinder assumes that the mob can float
|
||||
*
|
||||
* @return if this pathfinder assumes that the mob can float
|
||||
*/
|
||||
boolean canFloat();
|
||||
|
||||
/**
|
||||
* Makes this pathfinder assume that the mob can float, or not
|
||||
*
|
||||
* @param canFloat if the mob can float, or not
|
||||
*/
|
||||
void setCanFloat(boolean canFloat);
|
||||
|
||||
/**
|
||||
* 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. This value will be higher than the maximum index of {@link #getPoints()} if this path finding is done.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
* @deprecated use {@link #setAggressive(boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setChargingAttack(boolean raiseHands);
|
||||
|
||||
/**
|
||||
* Alias to {@link LivingEntity#isHandRaised()}, if the entity is charging an attack
|
||||
* @return If entities hands are raised
|
||||
* @deprecated use {@link #isHandRaised()}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean isChargingAttack() {
|
||||
return isHandRaised();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
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
|
||||
* @deprecated use {@link org.bukkit.util.RayTraceResult}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.destroystokyo.paper.entity.ai;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
|
||||
/**
|
||||
* Represents an AI goal of an entity
|
||||
*/
|
||||
public interface Goal<T extends Mob> {
|
||||
|
||||
/**
|
||||
* Checks if this goal should be activated
|
||||
*
|
||||
* @return if this goal should be activated
|
||||
*/
|
||||
boolean shouldActivate();
|
||||
|
||||
/**
|
||||
* Checks if this goal should stay active, defaults to {@link Goal#shouldActivate()}
|
||||
*
|
||||
* @return if this goal should stay active
|
||||
*/
|
||||
default boolean shouldStayActive() {
|
||||
return shouldActivate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this goal gets activated
|
||||
*/
|
||||
default void start() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this goal gets stopped
|
||||
*/
|
||||
default void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called each tick the goal is activated
|
||||
*/
|
||||
default void tick() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A unique key that identifies this type of goal. Plugins should use their own namespace, not the minecraft
|
||||
* namespace. Additionally, this key also specifies to what mobs this goal can be applied to
|
||||
*
|
||||
* @return the goal key
|
||||
*/
|
||||
@NotNull
|
||||
GoalKey<T> getKey();
|
||||
|
||||
/**
|
||||
* Returns a list of all applicable flags for this goal.<br>
|
||||
*
|
||||
* This method is only called on construction.
|
||||
*
|
||||
* @return the subtypes.
|
||||
*/
|
||||
@NotNull
|
||||
EnumSet<GoalType> getTypes();
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.destroystokyo.paper.entity.ai;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
|
||||
/**
|
||||
*
|
||||
* Used to identify a Goal. Consists of a {@link NamespacedKey} and the type of mob the goal can be applied to
|
||||
*
|
||||
* @param <T> the type of mob the goal can be applied to
|
||||
*/
|
||||
public class GoalKey<T extends Mob> {
|
||||
|
||||
private final Class<T> entityClass;
|
||||
private final NamespacedKey namespacedKey;
|
||||
|
||||
private GoalKey(@NotNull Class<T> entityClass, @NotNull NamespacedKey namespacedKey) {
|
||||
this.entityClass = entityClass;
|
||||
this.namespacedKey = namespacedKey;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Class<T> getEntityClass() {
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public NamespacedKey getNamespacedKey() {
|
||||
return namespacedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
GoalKey<?> goalKey = (GoalKey<?>) o;
|
||||
return Objects.equal(entityClass, goalKey.entityClass) &&
|
||||
Objects.equal(namespacedKey, goalKey.namespacedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(entityClass, namespacedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringJoiner(", ", GoalKey.class.getSimpleName() + "[", "]")
|
||||
.add("entityClass=" + entityClass)
|
||||
.add("namespacedKey=" + namespacedKey)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <A extends Mob> GoalKey<A> of(@NotNull Class<A> entityClass, @NotNull NamespacedKey namespacedKey) {
|
||||
return new GoalKey<>(entityClass, namespacedKey);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.destroystokyo.paper.entity.ai;
|
||||
|
||||
/**
|
||||
* Represents the subtype of a goal. Used by minecraft to disable certain types of goals if needed.
|
||||
*/
|
||||
public enum GoalType {
|
||||
|
||||
MOVE,
|
||||
LOOK,
|
||||
JUMP,
|
||||
TARGET,
|
||||
/**
|
||||
* Used to map vanilla goals, that are a behavior goal but don't have a type set...
|
||||
*/
|
||||
UNKNOWN_BEHAVIOR,
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.destroystokyo.paper.entity.ai;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
|
||||
/**
|
||||
* Represents a part of the "brain" of a mob. It tracks all tasks (running or not), allows adding and removing goals
|
||||
*/
|
||||
public interface MobGoals {
|
||||
|
||||
<T extends Mob> void addGoal(@NotNull T mob, int priority, @NotNull Goal<T> goal);
|
||||
|
||||
<T extends Mob> void removeGoal(@NotNull T mob, @NotNull Goal<T> goal);
|
||||
|
||||
<T extends Mob> void removeAllGoals(@NotNull T mob);
|
||||
|
||||
<T extends Mob> void removeAllGoals(@NotNull T mob, @NotNull GoalType type);
|
||||
|
||||
<T extends Mob> void removeGoal(@NotNull T mob, @NotNull GoalKey<T> key);
|
||||
|
||||
<T extends Mob> boolean hasGoal(@NotNull T mob, @NotNull GoalKey<T> key);
|
||||
|
||||
@Nullable
|
||||
<T extends Mob> Goal<T> getGoal(@NotNull T mob, @NotNull GoalKey<T> key);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getGoals(@NotNull T mob, @NotNull GoalKey<T> key);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getAllGoals(@NotNull T mob);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getAllGoals(@NotNull T mob, @NotNull GoalType type);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getRunningGoals(@NotNull T mob);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getRunningGoals(@NotNull T mob, @NotNull GoalType type);
|
||||
|
||||
@NotNull
|
||||
<T extends Mob> Collection<Goal<T>> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type);
|
||||
}
|
|
@ -0,0 +1,303 @@
|
|||
package com.destroystokyo.paper.entity.ai;
|
||||
|
||||
import com.destroystokyo.paper.entity.RangedEntity;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.*;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Represents a vanilla goal. Plugins should never implement this.<br>
|
||||
* Generated by VanillaPathfinderTest in paper-server
|
||||
*/
|
||||
public interface VanillaGoal<T extends Mob> extends Goal<T> {
|
||||
|
||||
GoalKey<Creature> AVOID_ENTITY = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_entity"));
|
||||
GoalKey<Wolf> BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg"));
|
||||
GoalKey<Mob> BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door"));
|
||||
GoalKey<Creature> BREATH_AIR = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath_air"));
|
||||
GoalKey<Animals> BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed"));
|
||||
GoalKey<Cat> CAT_LIE_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_lie_on_bed"));
|
||||
GoalKey<Cat> CAT_SIT_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_block"));
|
||||
GoalKey<Dolphin> DOLPHIN_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_jump"));
|
||||
GoalKey<Mob> EAT_BLOCK = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_block"));
|
||||
GoalKey<Creature> FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun"));
|
||||
GoalKey<Mob> FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float"));
|
||||
GoalKey<Creature> FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat"));
|
||||
GoalKey<io.papermc.paper.entity.SchoolableFish> FOLLOW_FLOCK_LEADER = GoalKey.of(io.papermc.paper.entity.SchoolableFish.class, NamespacedKey.minecraft("follow_flock_leader"));
|
||||
GoalKey<Mob> FOLLOW_MOB = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_mob"));
|
||||
GoalKey<Tameable> FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner"));
|
||||
GoalKey<Animals> FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent"));
|
||||
GoalKey<Creature> GOLEM_RANDOM_STROLL_IN_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("golem_random_stroll_in_village"));
|
||||
GoalKey<Mob> INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact"));
|
||||
GoalKey<Parrot> LAND_ON_OWNERS_SHOULDER = GoalKey.of(Parrot.class, NamespacedKey.minecraft("land_on_owners_shoulder"));
|
||||
GoalKey<Mob> LEAP_AT = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at"));
|
||||
GoalKey<Llama> LLAMA_FOLLOW_CARAVAN = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow_caravan"));
|
||||
GoalKey<Mob> LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player"));
|
||||
GoalKey<AbstractVillager> LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player"));
|
||||
GoalKey<Creature> MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack"));
|
||||
GoalKey<Creature> MOVE_BACK_TO_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_back_to_village"));
|
||||
GoalKey<Creature> MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village"));
|
||||
GoalKey<Creature> MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction"));
|
||||
GoalKey<Creature> MOVE_TOWARDS = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards"));
|
||||
GoalKey<Mob> OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack"));
|
||||
GoalKey<IronGolem> OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower"));
|
||||
GoalKey<Mob> OPEN_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("open_door"));
|
||||
GoalKey<Creature> PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic"));
|
||||
GoalKey<Raider> PATHFIND_TO_RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("pathfind_to_raid"));
|
||||
GoalKey<Mob> RANDOM_LOOK_AROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_look_around"));
|
||||
GoalKey<AbstractHorse> RANDOM_STAND = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("random_stand"));
|
||||
GoalKey<Creature> RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll"));
|
||||
GoalKey<Creature> RANDOM_SWIMMING = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swimming"));
|
||||
GoalKey<RangedEntity> RANGED_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("ranged_attack"));
|
||||
GoalKey<Monster> RANGED_BOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_bow_attack"));
|
||||
GoalKey<Monster> RANGED_CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_crossbow_attack"));
|
||||
GoalKey<Creature> REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block"));
|
||||
GoalKey<Creature> RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun"));
|
||||
GoalKey<AbstractHorse> RUN_AROUND_LIKE_CRAZY = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("run_around_like_crazy"));
|
||||
GoalKey<Tameable> SIT_WHEN_ORDERED_TO = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit_when_ordered_to"));
|
||||
GoalKey<Creature> STROLL_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_through_village"));
|
||||
GoalKey<Creeper> SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell"));
|
||||
GoalKey<Creature> TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt"));
|
||||
GoalKey<AbstractVillager> TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player"));
|
||||
GoalKey<Creature> TRY_FIND_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("try_find_water"));
|
||||
GoalKey<Mob> USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item"));
|
||||
GoalKey<Creature> WATER_AVOIDING_RANDOM_FLYING = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_flying"));
|
||||
GoalKey<Creature> WATER_AVOIDING_RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_stroll"));
|
||||
GoalKey<Zombie> ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack"));
|
||||
GoalKey<IronGolem> DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village"));
|
||||
GoalKey<Creature> HURT_BY = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by"));
|
||||
GoalKey<Mob> NEAREST_ATTACKABLE = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable"));
|
||||
GoalKey<Raider> NEAREST_ATTACKABLE_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_witch"));
|
||||
GoalKey<Raider> NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider"));
|
||||
GoalKey<Tameable> NON_TAME_RANDOM = GoalKey.of(Tameable.class, NamespacedKey.minecraft("non_tame_random"));
|
||||
GoalKey<Tameable> OWNER_HURT_BY = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by"));
|
||||
GoalKey<Tameable> OWNER_HURT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt"));
|
||||
GoalKey<Mob> RESET_UNIVERSAL_ANGER = GoalKey.of(Mob.class, NamespacedKey.minecraft("reset_universal_anger"));
|
||||
GoalKey<Fish> FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim"));
|
||||
GoalKey<Bee> BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack"));
|
||||
GoalKey<Bee> BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry"));
|
||||
GoalKey<Bee> BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive"));
|
||||
GoalKey<Bee> BEE_GO_TO_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_hive"));
|
||||
GoalKey<Bee> BEE_GO_TO_KNOWN_FLOWER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_known_flower"));
|
||||
GoalKey<Bee> BEE_GROW_CROP = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_grow_crop"));
|
||||
GoalKey<Bee> BEE_HURT_BY_OTHER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_hurt_by_other"));
|
||||
GoalKey<Bee> BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive"));
|
||||
GoalKey<Bee> BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate"));
|
||||
GoalKey<Bee> BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander"));
|
||||
GoalKey<Cat> CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity"));
|
||||
GoalKey<Cat> CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner"));
|
||||
GoalKey<Cat> CAT_TEMPT = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_tempt"));
|
||||
GoalKey<Dolphin> DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure"));
|
||||
GoalKey<Dolphin> DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player"));
|
||||
GoalKey<Dolphin> PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("play_with_items"));
|
||||
GoalKey<Fox> DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("defend_trusted"));
|
||||
GoalKey<Fox> FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("faceplant"));
|
||||
GoalKey<Fox> FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed"));
|
||||
GoalKey<Fox> FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries"));
|
||||
GoalKey<Fox> FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float"));
|
||||
GoalKey<Fox> FOX_FOLLOW_PARENT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_follow_parent"));
|
||||
GoalKey<Fox> FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player"));
|
||||
GoalKey<Fox> FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack"));
|
||||
GoalKey<Fox> FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic"));
|
||||
GoalKey<Fox> FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce"));
|
||||
GoalKey<Fox> FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items"));
|
||||
GoalKey<Fox> FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village"));
|
||||
GoalKey<Fox> PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("perch_and_search"));
|
||||
GoalKey<Fox> SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("seek_shelter"));
|
||||
GoalKey<Fox> SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("sleep"));
|
||||
GoalKey<Fox> STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("stalk_prey"));
|
||||
GoalKey<Ocelot> OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity"));
|
||||
GoalKey<Ocelot> OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt"));
|
||||
GoalKey<Panda> PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack"));
|
||||
GoalKey<Panda> PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid"));
|
||||
GoalKey<Panda> PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed"));
|
||||
GoalKey<Panda> PANDA_HURT_BY = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by"));
|
||||
GoalKey<Panda> PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back"));
|
||||
GoalKey<Panda> PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player"));
|
||||
GoalKey<Panda> PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic"));
|
||||
GoalKey<Panda> PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll"));
|
||||
GoalKey<Panda> PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit"));
|
||||
GoalKey<Panda> PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze"));
|
||||
GoalKey<PolarBear> POLAR_BEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_attack_players"));
|
||||
GoalKey<PolarBear> POLAR_BEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_hurt_by"));
|
||||
GoalKey<PolarBear> POLAR_BEAR_MELEE_ATTACK = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_melee_attack"));
|
||||
GoalKey<PolarBear> POLAR_BEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_panic"));
|
||||
GoalKey<PufferFish> PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff"));
|
||||
GoalKey<Rabbit> RABBIT_AVOID_ENTITY = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_entity"));
|
||||
GoalKey<Rabbit> RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic"));
|
||||
GoalKey<Rabbit> RAID_GARDEN = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("raid_garden"));
|
||||
GoalKey<Squid> SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee"));
|
||||
GoalKey<Squid> SQUID_RANDOM_MOVEMENT = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_random_movement"));
|
||||
GoalKey<Turtle> TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed"));
|
||||
GoalKey<Turtle> TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home"));
|
||||
GoalKey<Turtle> TURTLE_GO_TO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_to_water"));
|
||||
GoalKey<Turtle> TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg"));
|
||||
GoalKey<Turtle> TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic"));
|
||||
GoalKey<Turtle> TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll"));
|
||||
GoalKey<Turtle> TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel"));
|
||||
GoalKey<Wolf> WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity"));
|
||||
GoalKey<Llama> LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf"));
|
||||
GoalKey<Llama> LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by"));
|
||||
GoalKey<SkeletonHorse> SKELETON_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("skeleton_trap"));
|
||||
GoalKey<Llama> TRADER_LLAMA_DEFEND_WANDERING_TRADER = GoalKey.of(Llama.class, NamespacedKey.minecraft("trader_llama_defend_wandering_trader"));
|
||||
GoalKey<Wither> WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing"));
|
||||
GoalKey<Illager> RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door"));
|
||||
GoalKey<AbstractSkeleton> SKELETON_MELEE = GoalKey.of(AbstractSkeleton.class, NamespacedKey.minecraft("abstract_skeleton_melee"));
|
||||
GoalKey<Blaze> BLAZE_ATTACK = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_attack"));
|
||||
GoalKey<Drowned> DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack"));
|
||||
GoalKey<Drowned> DROWNED_GO_TO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_go_to_beach"));
|
||||
GoalKey<Creature> DROWNED_GO_TO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_go_to_water"));
|
||||
GoalKey<Drowned> DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up"));
|
||||
GoalKey<RangedEntity> DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack"));
|
||||
GoalKey<Enderman> ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at"));
|
||||
GoalKey<Enderman> ENDERMAN_LEAVE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_leave_block"));
|
||||
GoalKey<Enderman> ENDERMAN_LOOK_FOR_PLAYER = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_look_for_player"));
|
||||
GoalKey<Enderman> ENDERMAN_TAKE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_take_block"));
|
||||
GoalKey<Evoker> EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell"));
|
||||
GoalKey<Evoker> EVOKER_CASTING_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_casting_spell"));
|
||||
GoalKey<Evoker> EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell"));
|
||||
GoalKey<Evoker> EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell"));
|
||||
GoalKey<Ghast> GHAST_LOOK = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_look"));
|
||||
GoalKey<Ghast> GHAST_SHOOT_FIREBALL = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_shoot_fireball"));
|
||||
GoalKey<Ghast> RANDOM_FLOAT_AROUND = GoalKey.of(Ghast.class, NamespacedKey.minecraft("random_float_around"));
|
||||
GoalKey<Guardian> GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack"));
|
||||
GoalKey<Illusioner> ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell"));
|
||||
GoalKey<Illusioner> ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell"));
|
||||
GoalKey<Raider> LONG_DISTANCE_PATROL = GoalKey.of(Raider.class, NamespacedKey.minecraft("long_distance_patrol"));
|
||||
GoalKey<Phantom> PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player"));
|
||||
GoalKey<Phantom> PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy"));
|
||||
GoalKey<Phantom> PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor"));
|
||||
GoalKey<Phantom> PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack"));
|
||||
GoalKey<Shulker> SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack"));
|
||||
GoalKey<Shulker> SHULKER_DEFENSE_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense_attack"));
|
||||
GoalKey<Shulker> SHULKER_NEAREST_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest_attack"));
|
||||
GoalKey<Shulker> SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek"));
|
||||
GoalKey<Silverfish> SILVERFISH_MERGE_WITH_STONE = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_merge_with_stone"));
|
||||
GoalKey<Silverfish> SILVERFISH_WAKE_UP_FRIENDS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_up_friends"));
|
||||
GoalKey<Slime> SLIME_ATTACK = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_attack"));
|
||||
GoalKey<Slime> SLIME_FLOAT = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_float"));
|
||||
GoalKey<Slime> SLIME_KEEP_ON_JUMPING = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_keep_on_jumping"));
|
||||
GoalKey<Slime> SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction"));
|
||||
GoalKey<Spellcaster> SPELLCASTER_CASTING_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_casting_spell"));
|
||||
GoalKey<Spider> SPIDER_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_attack"));
|
||||
GoalKey<Spider> SPIDER = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider"));
|
||||
GoalKey<Strider> STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava"));
|
||||
GoalKey<Vex> VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack"));
|
||||
GoalKey<Vex> VEX_COPY_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_owner"));
|
||||
GoalKey<Vex> VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move"));
|
||||
GoalKey<Mob> VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door"));
|
||||
GoalKey<Vindicator> VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack"));
|
||||
GoalKey<Zombie> ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg"));
|
||||
GoalKey<WanderingTrader> WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("wander_to_position"));
|
||||
GoalKey<Raider> HOLD_GROUND_ATTACK = GoalKey.of(Raider.class, NamespacedKey.minecraft("hold_ground_attack"));
|
||||
GoalKey<Raider> OBTAIN_RAID_LEADER_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("obtain_raid_leader_banner"));
|
||||
GoalKey<Raider> RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration"));
|
||||
GoalKey<Raider> RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village"));
|
||||
GoalKey<Creature> PARROT_WANDER = GoalKey.of(Creature.class, NamespacedKey.minecraft("parrot_wander"));
|
||||
GoalKey<Mob> CLIMB_ON_TOP_OF_POWDER_SNOW = GoalKey.of(Mob.class, NamespacedKey.minecraft("climb_on_top_of_powder_snow"));
|
||||
GoalKey<Wolf> WOLF_PANIC = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_panic"));
|
||||
|
||||
/**
|
||||
* @deprecated removed in 1.20.2
|
||||
*/
|
||||
@Deprecated GoalKey<Vindicator> VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack"));
|
||||
/**
|
||||
* @deprecated removed in 1.20.2
|
||||
*/
|
||||
@Deprecated GoalKey<Ravager> RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack"));
|
||||
/**
|
||||
* @deprecated removed in 1.20.2
|
||||
*/
|
||||
@Deprecated GoalKey<Rabbit> EVIL_RABBIT_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("evil_rabbit_attack"));
|
||||
|
||||
/**
|
||||
* @deprecated removed in 1.16
|
||||
*/
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PigZombie> ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger"));
|
||||
/**
|
||||
* @deprecated removed in 1.16
|
||||
*/
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PigZombie> ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other"));
|
||||
|
||||
// the constants below use spigot names, they no longer work
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Blaze> BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Cat> TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Dolphin> DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Drowned> DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Enderman> ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Enderman> ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Enderman> PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Evoker> EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fox> FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Ghast> GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Ghast> GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Ghast> GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Spellcaster> SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<TraderLlama> LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Panda> PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PolarBear> POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PolarBear> POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PolarBear> POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<PolarBear> POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Rabbit> EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Rabbit> KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Rabbit> RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Raider> RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Raider> RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Shulker> SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Shulker> SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Silverfish> SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Silverfish> SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Slime> SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Slime> SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Slime> SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Spider> SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Spider> SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Squid> SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Turtle> TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Turtle> TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Vex> VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<WanderingTrader> VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<RangedEntity> ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Monster> BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Cat> CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Monster> CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Fish> FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<SkeletonHorse> HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Cat> JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Llama> LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Raider> NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Tameable> OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Tameable> OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Parrot> PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Raider> RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Tameable> RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Tameable> SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<AbstractHorse> TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Dolphin> WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Creature> STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem"));
|
||||
@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21") GoalKey<Mob> UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset"));
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.destroystokyo.paper.entity.villager;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A reputation score for a player on a villager.
|
||||
*/
|
||||
public final class Reputation {
|
||||
|
||||
@NotNull
|
||||
private final Map<ReputationType, Integer> reputation;
|
||||
|
||||
public Reputation() {
|
||||
this(new EnumMap<>(ReputationType.class));
|
||||
}
|
||||
|
||||
public Reputation(@NotNull Map<ReputationType, Integer> reputation) {
|
||||
Preconditions.checkNotNull(reputation, "reputation cannot be null");
|
||||
this.reputation = reputation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reputation value for a specific {@link ReputationType}.
|
||||
*
|
||||
* @param type The {@link ReputationType type} of reputation to get.
|
||||
* @return The value of the {@link ReputationType type}.
|
||||
*/
|
||||
public int getReputation(@NotNull ReputationType type) {
|
||||
Preconditions.checkNotNull(type, "the reputation type cannot be null");
|
||||
return this.reputation.getOrDefault(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reputation value for a specific {@link ReputationType}.
|
||||
*
|
||||
* @param type The {@link ReputationType type} of reputation to set.
|
||||
* @param value The value of the {@link ReputationType type}.
|
||||
*/
|
||||
public void setReputation(@NotNull ReputationType type, int value) {
|
||||
Preconditions.checkNotNull(type, "the reputation type cannot be null");
|
||||
this.reputation.put(type, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if a reputation value is currently set for a specific {@link ReputationType}.
|
||||
*
|
||||
* @param type The {@link ReputationType type} to check
|
||||
* @return If there is a value for this {@link ReputationType type} set.
|
||||
*/
|
||||
public boolean hasReputationSet(@NotNull ReputationType type) {
|
||||
return this.reputation.containsKey(type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.destroystokyo.paper.entity.villager;
|
||||
|
||||
/**
|
||||
* A type of reputation gained with a {@link org.bukkit.entity.Villager Villager}.
|
||||
* <p>
|
||||
* All types but {@link #MAJOR_POSITIVE} are shared to other villagers.
|
||||
*/
|
||||
public enum ReputationType {
|
||||
/**
|
||||
* A gossip with a majorly negative effect. This is only gained through killing a nearby
|
||||
* villager.
|
||||
*/
|
||||
MAJOR_NEGATIVE,
|
||||
|
||||
/**
|
||||
* A gossip with a minor negative effect. This is only gained through damaging a villager.
|
||||
*/
|
||||
MINOR_NEGATIVE,
|
||||
|
||||
/**
|
||||
* A gossip with a minor positive effect. This is only gained through curing a zombie
|
||||
* villager.
|
||||
*/
|
||||
MINOR_POSITIVE,
|
||||
|
||||
/**
|
||||
* A gossip with a major positive effect. This is only gained through curing a zombie
|
||||
* villager.
|
||||
*/
|
||||
MAJOR_POSITIVE,
|
||||
|
||||
/**
|
||||
* A gossip with a minor positive effect. This is only gained through trading with a villager.
|
||||
*/
|
||||
TRADING,
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
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.ApiStatus;
|
||||
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 HANDLER_LIST = new HandlerList();
|
||||
|
||||
private boolean cancel;
|
||||
private DamageState damageState;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public AnvilDamagedEvent(@NotNull InventoryView inventory, @Nullable 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 HANDLER_LIST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final 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 is not an anvil state");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
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 boolean willDrop;
|
||||
private boolean playEffect = true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param willDrop If the server is going to drop the block in question with this destroy event
|
||||
*/
|
||||
public void setWillDrop(boolean willDrop) {
|
||||
this.willDrop = 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
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
|
||||
* @deprecated use {@link org.bukkit.event.block.TNTPrimeEvent}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
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 ignited either by a
|
||||
* flint and steel, {@link Creeper#ignite()} or
|
||||
* {@link Creeper#setIgnited(boolean)}.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
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.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud
|
||||
*/
|
||||
public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable {
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
@NotNull private final Collection<LivingEntity> targets;
|
||||
@NotNull private final AreaEffectCloud areaEffectCloud;
|
||||
private boolean cancelled = false;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @NotNull 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
|
||||
*
|
||||
* @return the targets
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<LivingEntity> getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The area effect cloud spawned in this collision
|
||||
*/
|
||||
@NotNull
|
||||
public AreaEffectCloud getAreaEffectCloud() {
|
||||
return areaEffectCloud;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
cancelled = cancel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.destroystokyo.paper.event.entity;
|
||||
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.entity.EntityEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when an entity jumps
|
||||
* <p>
|
||||
* Cancelling the event will stop the entity from jumping
|
||||
*/
|
||||
public class EntityJumpEvent extends EntityEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private boolean canceled;
|
||||
|
||||
public EntityJumpEvent(@NotNull LivingEntity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LivingEntity getEntity() {
|
||||
return (LivingEntity) entity;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.destroystokyo.paper.event.entity;
|
||||
|
||||
import io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
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 EntityPushedByEntityAttackEvent {
|
||||
private final float knockbackStrength;
|
||||
|
||||
public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) {
|
||||
super(entity, hitBy, acceleration);
|
||||
this.knockbackStrength = knockbackStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 super.getPushedBy();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
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;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* 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(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
|
||||
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
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.destroystokyo.paper.event.entity;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
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.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);
|
||||
Preconditions.checkNotNull(bolt);
|
||||
Preconditions.checkNotNull(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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
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.ApiStatus;
|
||||
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;
|
||||
|
||||
@ApiStatus.Internal
|
||||
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
|
||||
*/
|
||||
@NotNull
|
||||
public Entity getSpawningEntity() {
|
||||
return entity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
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 it fires even if the spawning might fail later, for
|
||||
* example when the entity would be unable to spawn due to limited space or lighting.
|
||||
*
|
||||
* 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");
|
||||
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 efficient 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
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 a 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
|
||||
* @deprecated Deprecated, use {@link org.bukkit.event.entity.ProjectileHitEvent} and check if there is a hit entity
|
||||
*/
|
||||
@Deprecated
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.destroystokyo.paper.event.entity;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private final List<HumanEntity> eligibleHumans;
|
||||
|
||||
public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) {
|
||||
this(horse, ImmutableList.of());
|
||||
}
|
||||
|
||||
public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse, @NotNull List<HumanEntity> eligibleHumans) {
|
||||
super(horse);
|
||||
this.eligibleHumans = eligibleHumans;
|
||||
}
|
||||
|
||||
@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
|
||||
public List<HumanEntity> getEligibleHumans() {
|
||||
return eligibleHumans;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
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 its 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package com.destroystokyo.paper.event.entity;
|
||||
|
||||
import org.bukkit.entity.Egg;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a thrown egg might hatch.
|
||||
* <p>
|
||||
* This event fires for all thrown eggs that may hatch, players, dispensers, etc.
|
||||
*/
|
||||
public class ThrownEggHatchEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final Egg egg;
|
||||
private boolean hatching;
|
||||
private EntityType hatchType;
|
||||
private byte numHatches;
|
||||
|
||||
public ThrownEggHatchEvent(@NotNull final Egg egg, final boolean hatching, final byte numHatches, @NotNull final EntityType hatchingType) {
|
||||
this.egg = egg;
|
||||
this.hatching = hatching;
|
||||
this.numHatches = numHatches;
|
||||
this.hatchType = hatchingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the egg involved in this event.
|
||||
*
|
||||
* @return the egg involved in this event
|
||||
*/
|
||||
@NotNull
|
||||
public Egg getEgg() {
|
||||
return egg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the egg is hatching or not. Will be what the server
|
||||
* would've done without interaction.
|
||||
*
|
||||
* @return boolean Whether the egg is going to hatch or not
|
||||
*/
|
||||
public boolean isHatching() {
|
||||
return hatching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the egg will hatch or not.
|
||||
*
|
||||
* @param hatching true if you want the egg to hatch, false if you want it
|
||||
* not to
|
||||
*/
|
||||
public void setHatching(boolean hatching) {
|
||||
this.hatching = hatching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the mob being hatched (EntityType.CHICKEN by default)
|
||||
*
|
||||
* @return The type of the mob being hatched by the egg
|
||||
*/
|
||||
@NotNull
|
||||
public EntityType getHatchingType() {
|
||||
return hatchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the type of mob being hatched by the egg
|
||||
*
|
||||
* @param hatchType The type of the mob being hatched by the egg
|
||||
*/
|
||||
public void setHatchingType(@NotNull EntityType hatchType) {
|
||||
if (!hatchType.isSpawnable()) throw new IllegalArgumentException("Can't spawn that entity type from an egg!");
|
||||
this.hatchType = hatchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of mob hatches from the egg. By default the number will
|
||||
* be the number the server would've done
|
||||
* <ul>
|
||||
* <li>7/8 chance of being 0
|
||||
* <li>31/256 ~= 1/8 chance to be 1
|
||||
* <li>1/256 chance to be 4
|
||||
* </ul>
|
||||
*
|
||||
* @return The number of mobs going to be hatched by the egg
|
||||
*/
|
||||
public byte getNumHatches() {
|
||||
return numHatches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the number of mobs coming out of the hatched egg
|
||||
* <p>
|
||||
* The boolean hatching will override this number. Ie. If hatching =
|
||||
* false, this number will not matter
|
||||
*
|
||||
* @param numHatches The number of mobs coming out of the egg
|
||||
*/
|
||||
public void setNumHatches(byte numHatches) {
|
||||
this.numHatches = numHatches;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
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;
|
||||
}
|
||||
this.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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
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 the 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
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;
|
||||
private final Method method;
|
||||
|
||||
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
|
||||
this.eventClass = eventClass;
|
||||
this.handle = handle;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
this.method = m;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return "MethodHandleEventExecutor['" + this.method + "']";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
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;
|
||||
private final Method method;
|
||||
|
||||
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);
|
||||
}
|
||||
this.method = m;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return "StaticMethodHandleEventExecutor['" + this.method + "']";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
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 {
|
||||
|
||||
private static final String EXECUTE_DESCRIPTOR = "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V";
|
||||
|
||||
@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", EXECUTE_DESCRIPTOR, null, null), ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR);
|
||||
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());
|
||||
// The only purpose of this switch statement is to generate the correct pop instruction, should the event handler method return something other than void.
|
||||
// Non-void event handlers will be unsupported in a future release.
|
||||
switch (Type.getType(m.getReturnType()).getSize()) {
|
||||
// case 0 is omitted because the only type that has size 0 is void - no pop instruction needed.
|
||||
case 1 -> methodGenerator.pop(); // handles reference types and most primitives
|
||||
case 2 -> methodGenerator.pop2(); // handles long and double
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.destroystokyo.paper.event.executor.asm;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.destroystokyo.paper.event.inventory;
|
||||
|
||||
import org.bukkit.Warning;
|
||||
import org.bukkit.inventory.GrindstoneInventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Called when an item is put in a slot for grinding in a Grindstone
|
||||
* @deprecated use {@link org.bukkit.event.inventory.PrepareGrindstoneEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
@Warning(false)
|
||||
public class PrepareGrindstoneEvent extends PrepareResultEvent {
|
||||
|
||||
public PrepareGrindstoneEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
|
||||
super(inventory, result);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GrindstoneInventory getInventory() {
|
||||
return (GrindstoneInventory) super.getInventory();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.destroystokyo.paper.event.inventory;
|
||||
|
||||
import org.bukkit.event.inventory.PrepareInventoryResultEvent;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Called when an item is put in an inventory containing a result slot
|
||||
*/
|
||||
public class PrepareResultEvent extends PrepareInventoryResultEvent {
|
||||
|
||||
// HandlerList on PrepareInventoryResultEvent to ensure api compat
|
||||
public PrepareResultEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
|
||||
super(inventory, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result item, may be null.
|
||||
*
|
||||
* @return result item
|
||||
*/
|
||||
@Nullable
|
||||
public ItemStack getResult() {
|
||||
return super.getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set result item, may be null.
|
||||
*
|
||||
* @param result result item
|
||||
*/
|
||||
public void setResult(@Nullable ItemStack result) {
|
||||
super.setResult(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* @deprecated Not used
|
||||
*/
|
||||
@Deprecated
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.destroystokyo.paper.event.player;
|
||||
|
||||
import org.bukkit.advancement.Advancement;
|
||||
import org.bukkit.advancement.AdvancementProgress;
|
||||
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 after a player is granted a criteria in an advancement.
|
||||
* If cancelled the criteria will be revoked.
|
||||
*/
|
||||
public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@NotNull private final Advancement advancement;
|
||||
@NotNull private final String criterion;
|
||||
@NotNull private final AdvancementProgress advancementProgress;
|
||||
private boolean cancel = false;
|
||||
|
||||
public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) {
|
||||
super(who);
|
||||
this.advancement = advancement;
|
||||
this.criterion = criterion;
|
||||
this.advancementProgress = who.getAdvancementProgress(advancement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current AdvancementProgress.
|
||||
* See {@link PlayerAdvancementCriterionGrantEvent}
|
||||
*
|
||||
* @return advancement progress
|
||||
*/
|
||||
@NotNull
|
||||
public AdvancementProgress getAdvancementProgress() {
|
||||
return advancementProgress;
|
||||
}
|
||||
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
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.ApiStatus;
|
||||
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;
|
||||
@NotNull private final ItemStack oldItem;
|
||||
@NotNull private final ItemStack newItem;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @NotNull ItemStack oldItem, @NotNull 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
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStack getOldItem() {
|
||||
return this.oldItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new item that's replacing the old
|
||||
*
|
||||
* @return new item
|
||||
*/
|
||||
@NotNull
|
||||
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(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, CARVED_PUMPKIN, PLAYER_HEAD, SKELETON_SKULL, ZOMBIE_HEAD, CREEPER_HEAD, WITHER_SKELETON_SKULL, TURTLE_HELMET, DRAGON_HEAD, PIGLIN_HEAD),
|
||||
CHEST(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA),
|
||||
LEGS(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS),
|
||||
FEET(NETHERITE_BOOTS, 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 this material can be equipped to a slot
|
||||
*
|
||||
* @param material material to check
|
||||
* @return whether this material can be equipped
|
||||
*/
|
||||
public static boolean isEquipable(@NotNull Material material) {
|
||||
return getByMaterial(material) != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.destroystokyo.paper.event.player;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
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 processing a player's attack on an entity when the player's attack strength cooldown is reset
|
||||
*/
|
||||
public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private final float cooledAttackStrength;
|
||||
private boolean cancel = false;
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@NotNull private final Entity attackedEntity;
|
||||
|
||||
public PlayerAttackEntityCooldownResetEvent(@NotNull Player who, @NotNull Entity attackedEntity, float cooledAttackStrength) {
|
||||
super(who);
|
||||
this.attackedEntity = attackedEntity;
|
||||
this.cooledAttackStrength = cooledAttackStrength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static @NotNull HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 an attack cooldown event is cancelled, the players attack strength will remain at the same value instead of being reset.
|
||||
*
|
||||
* @return true if this event is cancelled
|
||||
*/
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancelling this event will prevent the target player from having their cooldown reset from attacking this entity
|
||||
*
|
||||
* @param cancel true if you wish to cancel this event
|
||||
*/
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the players cooldown attack strength when they initiated the attack
|
||||
*
|
||||
* @return returns the original player cooldown value
|
||||
*/
|
||||
public float getCooledAttackStrength() {
|
||||
return cooledAttackStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity attacked by the player
|
||||
*
|
||||
* @return the entity attacked by the player
|
||||
*/
|
||||
@NotNull
|
||||
public Entity getAttackedEntity() {
|
||||
return attackedEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package com.destroystokyo.paper.event.player;
|
||||
|
||||
import com.destroystokyo.paper.ClientOption;
|
||||
import com.destroystokyo.paper.ClientOption.ChatVisibility;
|
||||
import com.destroystokyo.paper.SkinParts;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.inventory.MainHand;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Called when the player changes their client settings
|
||||
*/
|
||||
public class PlayerClientOptionsChangeEvent extends PlayerEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final String locale;
|
||||
private final int viewDistance;
|
||||
private final ChatVisibility chatVisibility;
|
||||
private final boolean chatColors;
|
||||
private final SkinParts skinparts;
|
||||
private final MainHand mainHand;
|
||||
private final boolean allowsServerListings;
|
||||
private final boolean textFilteringEnabled;
|
||||
|
||||
@Deprecated
|
||||
public PlayerClientOptionsChangeEvent(@NotNull Player player, @NotNull String locale, int viewDistance, @NotNull ChatVisibility chatVisibility, boolean chatColors, @NotNull SkinParts skinParts, @NotNull MainHand mainHand) {
|
||||
super(player);
|
||||
this.locale = locale;
|
||||
this.viewDistance = viewDistance;
|
||||
this.chatVisibility = chatVisibility;
|
||||
this.chatColors = chatColors;
|
||||
this.skinparts = skinParts;
|
||||
this.mainHand = mainHand;
|
||||
this.allowsServerListings = false;
|
||||
this.textFilteringEnabled = false;
|
||||
}
|
||||
|
||||
public PlayerClientOptionsChangeEvent(@NotNull Player player, @NotNull Map<ClientOption<?>, ?> options) {
|
||||
super(player);
|
||||
|
||||
this.locale = (String) options.get(ClientOption.LOCALE);
|
||||
this.viewDistance = (int) options.get(ClientOption.VIEW_DISTANCE);
|
||||
this.chatVisibility = (ChatVisibility) options.get(ClientOption.CHAT_VISIBILITY);
|
||||
this.chatColors = (boolean) options.get(ClientOption.CHAT_COLORS_ENABLED);
|
||||
this.skinparts = (SkinParts) options.get(ClientOption.SKIN_PARTS);
|
||||
this.mainHand = (MainHand) options.get(ClientOption.MAIN_HAND);
|
||||
this.allowsServerListings = (boolean) options.get(ClientOption.ALLOW_SERVER_LISTINGS);
|
||||
this.textFilteringEnabled = (boolean) options.get(ClientOption.TEXT_FILTERING_ENABLED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public boolean hasLocaleChanged() {
|
||||
return !locale.equals(player.getClientOption(ClientOption.LOCALE));
|
||||
}
|
||||
|
||||
public int getViewDistance() {
|
||||
return viewDistance;
|
||||
}
|
||||
|
||||
public boolean hasViewDistanceChanged() {
|
||||
return viewDistance != player.getClientOption(ClientOption.VIEW_DISTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ChatVisibility getChatVisibility() {
|
||||
return chatVisibility;
|
||||
}
|
||||
|
||||
public boolean hasChatVisibilityChanged() {
|
||||
return chatVisibility != player.getClientOption(ClientOption.CHAT_VISIBILITY);
|
||||
}
|
||||
|
||||
public boolean hasChatColorsEnabled() {
|
||||
return chatColors;
|
||||
}
|
||||
|
||||
public boolean hasChatColorsEnabledChanged() {
|
||||
return chatColors != player.getClientOption(ClientOption.CHAT_COLORS_ENABLED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SkinParts getSkinParts() {
|
||||
return skinparts;
|
||||
}
|
||||
|
||||
public boolean hasSkinPartsChanged() {
|
||||
return skinparts.getRaw() != player.getClientOption(ClientOption.SKIN_PARTS).getRaw();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MainHand getMainHand() {
|
||||
return mainHand;
|
||||
}
|
||||
|
||||
public boolean hasMainHandChanged() {
|
||||
return mainHand != player.getClientOption(ClientOption.MAIN_HAND);
|
||||
}
|
||||
|
||||
public boolean allowsServerListings() {
|
||||
return allowsServerListings;
|
||||
}
|
||||
|
||||
public boolean hasAllowServerListingsChanged() {
|
||||
return allowsServerListings != player.getClientOption(ClientOption.ALLOW_SERVER_LISTINGS);
|
||||
}
|
||||
|
||||
public boolean hasTextFilteringEnabled() {
|
||||
return textFilteringEnabled;
|
||||
}
|
||||
|
||||
public boolean hasTextFilteringChanged() {
|
||||
return textFilteringEnabled != player.getClientOption(ClientOption.TEXT_FILTERING_ENABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
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;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue