Compare commits

...

162 commits

Author SHA1 Message Date
Pedro
4430e96e1b
Add AnvilView#bypassEnchantmentLevelRestriction (#11475) 2024-10-12 23:10:05 +02:00
Lulu13022002
b16c0ae023
Add offline PDC API (#8117) 2024-10-12 21:38:18 +02:00
TonytheMacaroni
57c75a4b67
Fix CraftMagicNumbers#getTag (#11484) 2024-10-09 21:58:13 +01:00
Nassim Jahnke
7cd4f2c15f
Check if leash tag has a uuid 2024-10-03 17:10:27 +02:00
Nassim Jahnke
fb768404aa
[ci skip] Add section on nullability annotations (#11461) 2024-10-02 14:32:20 +02:00
Jake Potrebic
709f0f2919
Use components properly in ProfileWhitelistVerifyEvent (#11456) 2024-10-02 14:32:05 +02:00
Nassim Jahnke
69ffbec34a
Fix hex color check 2024-10-02 13:49:39 +02:00
Jake Potrebic
e7e1ab56ca
Finish converting most of the undeprecated api to jspecify 2024-09-30 16:02:52 -07:00
Jake Potrebic
ba3c29b92e
Finish converting all events to jspecify annotations 2024-09-29 19:13:41 -07:00
Bjarne Koll
ea00be3aaa
Do not NPE on uuid resolution in player profile (#11449)
Band-aid fix for the player profile api resolution for a profile with
name but without uuid. The real solution is a proper refactoring of the
completeFromCache and complete method internally, however this needs
further consideration regarding existing faulty behaviour around name
lookups from uuid-only profiles.
2024-09-30 00:26:44 +02:00
Axionize
b410fe8697
Configurable per-world void damage offset/damage(#11436) 2024-09-30 00:06:13 +02:00
Noah van der Aa
e3c8a8eef1
Add PlayerInsertLecternBookEvent [1.20 port] (#7305)
* Add PlayerInsertLecternBookEvent

* Rebase

Additionally, moves the event call higher up and removes the lectern
block state clone from the event.

* jSpecify

* Shrink correctly

* style fixups

* move methods

* rename param to cancel

* fix javadocs

* more javadoc fixes

* fix co-author on patch from yesterday

* last fix

---------

Co-authored-by: Mariell Hoversholm <proximyst@proximyst.com>
Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-09-29 14:28:48 -07:00
Jake Potrebic
f9c7f2a5c1
Begin switching to JSpecify annotations (#11448)
* Begin switching to JSpecify annotations

* more

* fixes
2024-09-29 12:52:13 -07:00
Jake Potrebic
6d7a438fad
Call bucket events for cauldrons (#7486) 2024-09-29 00:04:11 +02:00
Esoteric Enderman
355b1cbaf6
Add API for explosions to damage the explosion cause (#11180)
This intends to give plugin developers more control over explosions created using the World#createExplosion method, specifically by adding the option for explosions to damage the explosion cause (not the default behavior, and previously impossible to do, as far as I know). This is done by overloading existing methods with an extra `excludeSourceFromDamage` parameter.

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-09-28 21:32:56 +02:00
Tamion
7b03141498
Add startingBrewTime (#11406)
* add startingBrewTime

* casting

* requests

* comments and fix setBrewTime

* a

* b

* move to own class

* rename

* missing Paper comment

* missing experimentals

* rebased

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-09-28 12:14:20 -07:00
Jake Potrebic
e17eb6be0c
Improve entity effect API (#11444) 2024-09-28 20:05:45 +02:00
Jason Penilla
41bc31b79b
Update paperweight to 1.7.3 (#11445) 2024-09-28 17:03:58 +02:00
Jake Potrebic
b7ab22dee1
Fix console completions on invalid commands (#7603) 2024-09-27 11:05:15 -07:00
masmc05
8f56db871b
Add enchantWithLevels with tag specification (#11438)
* Add enchantWithLevels with tag specification

* Finalise

---------

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-09-27 11:04:57 -07:00
Jake Potrebic
f33611cbc3
fix ItemStack#removeEnchantments creating non-stackable items (#11442) 2024-09-27 10:58:11 -07:00
Jake Potrebic
dd6d1842bb
Remove redundant fillUsableCommands call (#11425) 2024-09-27 18:49:18 +02:00
Jake Potrebic
9c76642f99
Deprecate for removal Block#isValidTool (#11439)
The method's implementation uses Block#getDrops
which re-computes the drops from the loot table each
call leading to isValidTool returning different values
with subsequent calls.
2024-09-27 18:28:04 +02:00
Brokkonaut
01c4820450
Call EntityDropItemEvent when a container item drops its contents (#11441) 2024-09-27 18:27:14 +02:00
Stefano
627cc64eea
Adjust HAProxy's existance to log for console masters (#11433) 2024-09-27 18:19:29 +02:00
Jake Potrebic
20ec62255d
use correct types for preloading CraftRegistry
also add a check in CraftRegistryEntry constructor to
make sure preload class isn't in net.minecraft package
2024-09-26 14:20:09 -07:00
Jake Potrebic
1bc02e6b23
Fix tag lifecycle event handlers not disabling /reload 2024-09-24 19:33:30 -07:00
Jake Potrebic
9b1ee0d87d
Add missing key files and cleanup registry definition order 2024-09-23 17:36:32 -07:00
Jake Potrebic
acdd6d35ad
make MenuType implement FeatureDependant 2024-09-23 15:03:52 -07:00
Jake Potrebic
4514c71a7f
Only call EntityPortalExitEvent if entity is actually in a portal 2024-09-22 14:36:17 -07:00
Jake Potrebic
e8297c4cca
Expand out datapack API (#10828)
* Expand out datapack API

* add getTitle

* better enable check
2024-09-22 14:28:45 -07:00
TreemanKing
540deb7ef7
Fix Color Particle API (#10895)
* fix: check datatype of particles rather than particle-type

* feature: add ARGB channels

It keeps the functionality of the original color(int).

* fix: order

* fixes

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-09-22 14:06:40 -07:00
Nassim Jahnke
2f50b87277
Fixup command precprocess cancellation (#11424) 2024-09-22 21:25:37 +02:00
Nassim Jahnke
81d94483a2
Add ItemStack array serialization methods (#10387) 2024-09-22 21:02:06 +02:00
Oliver Janka
1cb2bf466f
Add velocity forwarding secret env override (#10127)
Previously, the velocity forwarding secret could only be configured via
the configuration option in the global paper configuration.
This makes configuring/passing such a value rather difficult for
containerized/orchestrated servers as these configuration files are
usually part of the server data volume itself and hence cannot be
sourced from a secret.

This commit enables administrators to define the PAPER_VELOCITY_SECRET
environment variable, which will override any potentially configured
velocity secret.
2024-09-22 20:25:27 +02:00
Bjarne Koll
78feecb12f
Deprecate BlockType#isInteractable (#11427)
While BlockType is still marked as internal, it mirrors the already
paper-deprecated method #isInteractable.

The commit marks said method as deprecated if/when BlockType becomes
experimental/non-internal.
2024-09-22 20:09:41 +02:00
Lulu13022002
1ed64f8270
Update launchProjectile API (#11300) 2024-09-21 21:19:02 +02:00
Jake Potrebic
593faf4fc3
Create TileStateInventoryHolder (#11420)
Adds a missing interface to centralize getSnapshotInventory methods.
2024-09-21 20:09:29 +02:00
Bjarne Koll
5bcb2ff9e4
Correctly launch WindCharges (#11418)
The launch API on LivingEntity only respected the WindCharge type, not
its near-clone BreezeWindCharge.

This commit correctly accounts for BreezeWindCharge in
CraftLivingEntity.
2024-09-21 20:08:31 +02:00
Newwind
d61175421d
Disable pretty printing for advancement saving (#11419) 2024-09-21 20:01:22 +02:00
Bjarne Koll
9c450388e1
Return null in getRegistry(Class) for unknown type (#11422)
The Bukkit#getRegistry(Class) method contract specifies that it returns
null for unknown registry types. The current implementation however
requires the passed class to be mappable to a known registry key.

For types like Material, which have a SimpleRegistry in bukkit's
Registry interface, no server side registry exists and such the type
cannot be mapped to a registry key.

The commit correctly returns null for types that are not mappable to a
registry key instead of throwing a NullPointerException.
2024-09-21 19:57:08 +02:00
Bjarne Koll
c5a10665b8
Remove wall-time / unused skip tick protection (#11412)
Spigot still maintains some partial implementation of "tick skipping", a
practice in which the MinecraftServer.currentTick field is updated not
by an increment of one per actual tick, but instead set to
System.currentTimeMillis() / 50. This behaviour means that the tracked
tick may "skip" a tick value in case a previous tick took more than the
expected 50ms.

To compensate for this in important paths, spigot/craftbukkit
implements "wall-time". Instead of incrementing/decrementing ticks on
block entities/entities by one for each call to their tick() method,
they instead increment/decrement important values, like
an ItemEntity's age or pickupDelay, by the difference of
`currentTick - lastTick`, where `lastTick` is the value of
`currentTick` during the last tick() call.

These "fixes" however do not play nicely with minecraft's simulation
distance as entities/block entities implementing the above behaviour
would "catch up" their values when moving from a non-ticking chunk to a
ticking one as their `lastTick` value remains stuck on the last tick in
a ticking chunk and hence lead to a large "catch up" once ticked again.

Paper completely removes the "tick skipping" behaviour (See patch
"Further-improve-server-tick-loop"), making the above precautions
completely unnecessary, which also rids paper of the previous described
incompatibility with non-ticking chunks.
2024-09-19 16:36:07 +02:00
Shane Freeder
5c82955733
Only mark decorations dirty if a removal actually occurs (#11413)
* Only mark decorations dirty if a removal actually occurs

Vanilla calls this method blindly inside of a loop which erroniously marks
map data files as being dirty even if nothing has actually changed.

* Merge into existing patch

---------

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-09-19 16:27:33 +02:00
4real
2aaf4369b6
Validate slot in PlayerInventory#setSlot (#11399) 2024-09-17 16:57:32 +02:00
Bjarne Koll
1348e44173
Prevent NPE when serializing unresolved profile (#11407)
In the recent upstream update, the paper player profile was updated to
correctly return null for both name and id if constructed as such. This
change however broke the serialisation logic, as it depended on the name
never being null.

The commit moves the checks over to the newly introduced emptyName/UUID
fields that track if the profile was constructed with a null name or
uuid to differentiate it against an empty string or the NIL_UUID.
2024-09-16 20:53:00 +02:00
Tamion
13a23951d7
Fix enable-player-collisions playing sounds when set to false (#11390) 2024-09-15 22:26:23 +02:00
Tamion
951e7ddc44
Fix TrialSpawner forgetting assigned mob when placed by player (#11381) 2024-09-15 22:20:38 +02:00
Jake Potrebic
0a53f1d10d
Set default drop behavior for player deaths (#11380) 2024-09-15 21:51:35 +02:00
Bjarne Koll
d1a72eac31
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11405)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
1fc1020a PR-1049: Add MenuType API
8ae2e3be PR-1055: Expand riptiding API
cac68bfb SPIGOT-7890: AttributeModifier#getUniqueId() doesn't match the UUID passed to its constructor
7004fcf2 SPIGOT-7886: Fix mistake in AttributeModifier UUID shim
1ac7f950 PR-1054: Add FireworkMeta#hasPower
4cfb565f SPIGOT-7873: Add powered state for skulls

CraftBukkit Changes:
bbb30e7a8 SPIGOT-7894: NPE when sending tile entity update
ba21e9472 SPIGOT-7895: PlayerItemBreakEvent not firing
0fb24bbe0 SPIGOT-7875: Fix PlayerItemConsumeEvent cancellation causing client-side desync
815066449 SPIGOT-7891: Can't remove second ingredient of MerchantRecipe
45c206f2c PR-1458: Add MenuType API
19c8ef9ae SPIGOT-7867: Merchant instanceof AbstractVillager always returns false
4e006d28f PR-1468: Expand riptiding API
bd8aded7d Ignore checks in CraftPlayerProfile for ResolvableProfile used in profile components
8679620b5 SPIGOT-7889: Fix tool component deserialisation without speed and/or correct-for-drops
8d5222691 SPIGOT-7882, PR-1467: Fix conversion of name in Profile Component to empty if it is missing
63f91669a SPIGOT-7887: Remove duplicate ProjectileHitEvent for fireballs
7070de8c8 SPIGOT-7878: Server#getLootTable does not return null on invalid loot table
060ee6cae SPIGOT-7876: Can't kick player or disconnect player in PlayerLoginEvent when checking for cookies
7ccb86cc0 PR-1465: Add FireworkMeta#hasPower
804ad6491 SPIGOT-7873: Add powered state for skulls
f9610cdcb Improve minecart movement

Spigot Changes:
a759b629 Rebuild patches

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-09-15 21:39:53 +02:00
Nassim Jahnke
4ff58c4c48
Update spark 2024-09-12 19:54:34 +02:00
Jason Penilla
e945cfe1c5
Fix PaperServerListPingEvent#getPlayerSample not being populated or used (#11387) 2024-09-10 19:52:30 +02:00
Jake Potrebic
61fe23cd08
deprecate isEnabledByFeature in Item/BlockType 2024-09-09 19:19:46 -07:00
Fabrizio La Rosa
971a7a5511
Add Decorated Pot Cracked API (#11365) 2024-09-08 22:12:36 +02:00
masmc05
b09eaf2e8d
Add Item serialization as json api (#11235)
* Item serialization as json

* Add ItemStackAdapter for Gson

* A javadoc note at #serialize() and #deserialize()

* Rebase

* Move serialize closer to deserialize

* Add explaining comment about SERIALIZE_CUSTOM_AS_SNBT usage

* Apply lynxplay requests

* Forgot `@NotNull`

* Very important diff was removed

* Rebase

* Javadocs

---------

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-09-08 12:58:30 -07:00
Jake Potrebic
7632de5134
Tag Lifecycle Events (#10993)
* wip tags

* use generics in tag registrars

* comment out varargs methods for now

* split up patch

* cache loaded service provider

* finish renames

* use builderWithExpectedSize

* finalize
2024-09-08 11:56:09 -07:00
Nassim Jahnke
1ba1be7d26
Update Velocity natives again
If you segfault, update your jre/jdk™️
2024-09-08 20:39:00 +02:00
Jake Potrebic
426f9924a5
Enchantment is data-driven, so not FeatureDependant (#11377) 2024-09-08 10:42:44 -07:00
Jake Potrebic
925c3b9d2b
Add FeatureFlag API (#8952)
* Add FeatureFlag API

* switch to index & move method

* fix test
2024-09-07 13:35:11 -07:00
Jake Potrebic
a8e6a93aec
Deprecate for removal all OldEnum-related methods (#11371) 2024-09-07 13:02:45 -07:00
Jake Potrebic
5d91bef46f
Fix shulkerbox loot table replenish (#11366)
* Fix shulkerbox loot table replenish

* re-add loot table if cleared

* add config
2024-09-07 12:49:28 -07:00
Pedro
0e825274e5
Fix NPE while trying to respawn an already disconnected player (#11353) 2024-09-07 21:34:03 +02:00
Bjarne Koll
21f125f3c2
Revert velocity natives to 3.1.2 (#11368)
The updated velocity native compilation pipeline seems to emit binaries
that are not compatible with alpine.
The commit temporarily reverts the natives included until a proper
solution is found.
2024-09-07 11:00:57 +02:00
Newwind
3db475838f
Check dead flag in isAlive() (#11330)
* Create 1055-Check-dead-flag-in-isAlive().patch

* Rebase
2024-09-06 15:06:32 -07:00
Lulu13022002
e0021b15b6
Fix allowSpiderWorldBorderClimbing world config (#11321) 2024-09-06 23:15:29 +02:00
Jake Potrebic
805a97444a
Improve console completion with brig suggestions (#9251)
* Improve console completion with brig suggestions

* silence warning

* small fixes

* squashed
2024-09-06 13:37:09 -07:00
VelVeV
10f5879992
Change condition check order of entity tracking Y (#11348) 2024-09-06 22:14:20 +02:00
nathannm23
953e6e9918
Fire BlockExpEvent on grindstone use (#11346) 2024-09-06 22:14:10 +02:00
VelVeV
012c527671
Update Velocity natives (#11347) 2024-09-06 21:44:24 +02:00
lucko
691d452643
Fix bundled spark permission check (#11355) 2024-09-06 21:41:54 +02:00
Nassim Jahnke
ff251e42b6
Use reference hash set in reference Holder (#11363) 2024-09-06 21:03:17 +02:00
Space Walker
b483da4e02
Update Alternate Current to v1.9 (#11333) 2024-09-01 10:59:20 -07:00
Tamion
227c94ae21
Fix inventory desync when placing blocks with spawn protection (#11090)
* fix

* mention mojira issue

* move to vanilla bug fixes patch

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-31 12:01:29 -07:00
Tamion
2f0891ed81
Fix InventoryOpenEvent cancellation (#11304)
* fix

* other blocks

* add missing diff in ContainerEntity

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-31 11:50:24 -07:00
Newwind
509ea2fd17
Fix horse armor desync (#11341) 2024-08-31 20:29:50 +02:00
Jason Penilla
e01ddf4627
Fixup porting issue in vanillaBiomeProvider impl (#11185) 2024-08-31 19:59:17 +02:00
Nassim Jahnke
25621248d3
[ci skip] Create SECURITY.md (#11331) 2024-08-27 18:12:32 +02:00
Gegy
e08e6679fc
Fix: synchronise sending chat to client with updating message signature cache (#11332)
In the case where multiple messages from different players are being processed in parallel, there was a potential race condition where the messages would be sent to the client in a different order than the message signature cache was updated. However, the cache relies on the fact that the client and server get the exact same updates in the same order. This race condition would cause the caches to become corrupted, and any future message received by the client would fail to validate.

This also applies to the last seen state of the server, which becomes inconsistent in the same way as the message signature cache and would cause any messages sent to be rejected by the server too.
2024-08-26 19:53:28 +02:00
Lulu13022002
789a267e93
Re-implement maxLeashDistance world conf and call missing event (#11301)
* Re-implement maxLeashDistance world config and call missing event

* migrate config setting to double or default

* fixes

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-25 14:32:32 -07:00
okx-code
a7b8d9574e
Add enchantment seed update API (#11282) 2024-08-25 22:39:06 +02:00
Isaac - The456
dd8c70a851
Ensure TabCompleteEvent always has a mutable backing list. (#11302) 2024-08-25 22:28:32 +02:00
DerEchtePilz
374d9c85ba
Add a method to reset Lodestone compasses back to normal ones (#11308) 2024-08-25 22:25:13 +02:00
DerEchtePilz
ad4c524c2f
Properly destroy placed blocks on the end platform (#11292) 2024-08-25 21:19:40 +02:00
Jake Potrebic
e2da65c689
Deprecate API relating to menu title changes (#11309) 2024-08-25 20:56:17 +02:00
Jake Potrebic
5167856bb8
Fix despawn ranges by defaulting to an ellipsoid shape (#11312) 2024-08-25 20:26:33 +02:00
Newwind
5b2c43edaf
Remove set damage lootable item function from compasses (#11317) 2024-08-25 19:52:12 +02:00
Newwind
94444cebc3
Fix incorrect timestamp in region file header recalculation (#11318) 2024-08-25 19:42:15 +02:00
Lulu13022002
5625051564
Prevent duplicate pickup event for piglins (#11322) 2024-08-25 19:27:31 +02:00
Janet Blackquill
956b3d1c4e
Ensure MaterialChoice materials are items (#11325) 2024-08-25 19:20:10 +02:00
Nassim Jahnke
fcedb49fea
Update spark-paper 2024-08-24 10:52:38 +02:00
roro1506HD
2fdb2e9dcd
Fix structure check API (#11307)
* Fix structure check API

* Use CraftStructure#bukkitToMinecraft

* Fixed spelling mistake on CraftStructure class name
2024-08-20 18:27:33 -07:00
Jake Potrebic
32711191cd
Fix SculkBloomEvent firing for block entity loading (#11306) 2024-08-19 14:28:03 -07:00
Nassim Jahnke
e4b38b4f8c
Fixup config parsing 2024-08-19 12:47:50 +02:00
DerEchtePilz
a8cb8e6745
[ci skip] Fix JavaDocs for HeightMap#MOTION_BLOCKING_NO_LEAVES (#11291) 2024-08-19 11:48:20 +02:00
Anthony J. Halliday
ba1b0162fa
Allow server administrators to disable book size checks (#10457) 2024-08-19 11:46:39 +02:00
kokiriglade
dae906ba45
Add getWorld method that uses adventure Key (#11199) 2024-08-19 11:41:55 +02:00
Nassim Jahnke
8fd3a67138
[ci skip] Clean up book limits patch (#11297) 2024-08-19 11:33:17 +02:00
Spottedleaf
be1078f5f2 Use player file, not directory, when checking for offline player data
When trying to fall back to offline player data in onlide mode,
we need to use the player file. This fixes a mistake during
update where 'file' was used, but the new code uses 'file1'
for the player file.
2024-08-18 15:32:25 -07:00
Spottedleaf
b4bc512cac Fix entity limit patch deleting unnecessary entities
We need to continue the save loop, not break from it
when a limit is reached.
2024-08-18 11:14:39 -07:00
SoSeDiK
64c9ee6584
Allow getting/setting the sign's editor uuid (#10637)
* Allow getting/setting the sign's editor uuid

* rebased

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-17 14:36:27 -07:00
Tamion
44017487a8
Fix CraftBukkit drag system (#10703) 2024-08-17 23:31:38 +02:00
Isaac - The456
8c3018a4b1
Fix Selector Arguments not working with permission (#11286) 2024-08-17 23:20:21 +02:00
Lulu13022002
57dd822393
Leashable API (#10961) 2024-08-17 23:17:18 +02:00
Jake Potrebic
2e82fd2d2c
Add even more Enchantment API (#11115) 2024-08-17 22:58:36 +02:00
Lulu13022002
66a97cc929
Update item data sanitization (#11227) 2024-08-17 22:30:21 +02:00
Jake Potrebic
0e7361704a
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11284)
Updated Upstream (Bukkit/CraftBukkit/Spigot)

Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
4068c6aa PR-1053: Change docs for max power in FireworkMeta
6b3c241b SPIGOT-7783, SPIGOT-7784, PR-1051: Add Trial Vault & Spawner event API
5fe300ec PR-1052: Fix broken links and minor improvement for checkstyle.xml

CraftBukkit Changes:
7548afcf2 SPIGOT-7872: Fix crash with event-modified teleports
93480d5d6 SPIGOT-7868, PR-1463: Fix default and max power in FireworkMeta
5060d1a84 SPIGOT-7783, SPIGOT-7784, PR-1460: Add Trial Vault & Spawner event API
11dfcae71 PR-1462: Fix broken links and minor improvement for checkstyle.xml

Spigot Changes:
ca581228 Rebuild patches
2024-08-17 12:39:11 -07:00
Tamion
75655ec1d3
Add Configuration for vertical Despawn Ranges (#11279) 2024-08-17 21:13:10 +02:00
Shane Freeder
52ae4ad466
Migrate ArmorStand meta to using entity tag (#11107) 2024-08-17 00:30:11 +02:00
Lulu13022002
d5ffc573dc
Implement more methods for horse inventories (#11147) 2024-08-17 00:27:47 +02:00
Lulu13022002
4829fbf6bd
Handle custom registry elements properly (#11230)
* Handle custom registry elements properly

* update error message

Datapack made painting variant support is added in https://github.com/PaperMC/Paper/pull/11244

* change msg for art conversion

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-16 14:21:35 -07:00
Lulu13022002
78216fef26
Re-implement portalCreateRadius world config (#11267) 2024-08-16 13:59:46 -07:00
Mart
e619744fbd
Allow skipping of world symlink validation (#11250) 2024-08-16 22:36:30 +02:00
Bjarne Koll
534ab86010
[ci-skip] Revert "Add Configuration for vertical Despawn Ranges (#10440)" (#11278)
This reverts commit 1b8ab116ed.
2024-08-16 22:33:52 +02:00
Tamion
1b8ab116ed
Add Configuration for vertical Despawn Ranges (#10440) 2024-08-16 22:29:53 +02:00
Abel
ec55c11fc0
Fix indestructable light blocks (#11275)
Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-08-16 22:13:00 +02:00
Lulu13022002
95719832bf
Fix scanForLegacyEnderDragon world config (#11262) 2024-08-16 21:45:07 +02:00
hyperdefined
81bfda8710
[ci skip] Specify rebase location in CONTRIBUTING (#11255)
* [ci skip] Specify rebase location in CONTRIBUTING

* Improve

* remove Paper-MojangAPI mention

---------

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
2024-08-16 12:41:58 -07:00
Spottedleaf
fb530743e5 Apply optimise collision checking in move packet handling patch 2024-08-16 06:56:13 -07:00
Lulu13022002
bf5852a615
Fix NPE for PlayerPostRespawnEvent#getRespawnedLocation (#11268) 2024-08-16 09:20:57 +02:00
Lulu13022002
11b4ac7c65
Fix disableEndCredits world config (#11261) 2024-08-14 21:26:38 +02:00
hyperdefined
9ab644ed29
Fix TooltipContext.create being wrong(#11254)
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-14 14:39:45 +02:00
Nassim Jahnke
7c9240f4a6
Improve standard messenger logging 2024-08-12 18:42:08 +02:00
Jake Potrebic
1798e949e5
Fix BasicCommand suggestion arg count (#11241) 2024-08-12 09:40:39 +02:00
hyperdefined
4a97ba3ea8
Fix setSendViewDistance's return (#11247) 2024-08-12 09:27:27 +02:00
Jake Potrebic
f97aff74b6
[ci skip] Fix Effect javadocs (#11182) 2024-08-12 00:35:45 +02:00
Lulu13022002
098bd39092
Remove arbitrary book page limit (#11228) 2024-08-12 00:30:23 +02:00
Newwind
ab0d24aa6f
Configuration for horizontal-only item merging (#11219) 2024-08-12 00:16:20 +02:00
Jake Potrebic
dd941cc40a
Re-add patches for can-place/can-destroy API (#11238)
* Re-add patches for can-place/can-destroy API

This API is all deprecated for removal and has to be replaced
as the structure of it has too radically changed

* update patches

* add link to MaterialRerouting

* Deprecation

---------

Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
2024-08-11 13:51:37 -07:00
Jake Potrebic
1187544fb0
Fix teleport event getTo returning null (#11239) 2024-08-11 22:42:39 +02:00
Jake Potrebic
1c3c47ab0b
Correctly check enchants for ItemStack#damage (#11240) 2024-08-11 13:27:24 -07:00
Lulu13022002
7d7f123e98
Fix wrong spawn reason for trial spawners (#11229) 2024-08-10 15:19:54 -07:00
Lulu13022002
1cecc24cad
Fix tag key generator output inconsistencies (#11218)
* Fix tag key generator output inconsistencies

* use NonNull instead of NotNull for generated api

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-08-10 15:11:57 -07:00
Lulu13022002
70dfa467e7
Fix CraftMetaShield equality (#11232) 2024-08-10 15:08:00 +02:00
Nassim Jahnke
306d0dfdf0
Update generated code 2024-08-10 12:43:24 +02:00
Nassim Jahnke
83b6b26d39
Update to 1.21.1 2024-08-10 12:24:38 +02:00
Nassim Jahnke
b1b5d4c1e4
Check shooter in configurable projectile relative velocity patch 2024-08-10 11:55:08 +02:00
Joo200
4d7cef3418
Fix source of knockback for spigot events (#11176) 2024-08-09 22:57:55 +02:00
Bjarne Koll
77a5779e24
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11197)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
2ec53f49 PR-1050: Fix empty result check for Complex Recipes
10671012 PR-1044: Add CrafterCraftEvent
4d87ffe0 Use correct method in JavaDoc
ae5e5817 SPIGOT-7850: Add API for Bogged shear state
46b6d445 SPIGOT-7837: Support data pack banner patterns
d5d0cefc Fix JavaDoc error
b3c2b83d PR-1036: Add API for InventoryView derivatives
1fe2c75a SPIGOT-7809: Add ShieldMeta

CraftBukkit Changes:
8ee6fd1b8 SPIGOT-7857: Improve ItemMeta block data deserialization
8f26c30c6 SPIGOT-7857: Fix spurious internal NBT tag when deserializing BlockStateMeta
759061b93 SPIGOT-7855: Fire does not spread or burn blocks
00fc9fb64 SPIGOT-7853: AnvilInventory#getRepairCost() always returns 0
7501e2e04 PR-1450: Add CrafterCraftEvent
8c51673e7 SPIGOT-5731: PortalCreateEvent#getEntity returns null for nether portals ignited by flint and steel
d53d0d0b1 PR-1456: Fix inverted logic in CraftCrafterView#setSlotDisabled
682a678c8 SPIGOT-7850: Add API for Bogged shear state
fccf5243a SPIGOT-7837: Support data pack banner patterns
9c3bd4390 PR-1431: Add API for InventoryView derivatives
0cc6acbc4 SPIGOT-7849: Fix FoodComponent serialize with "using-converts-to" using null
2c5474952 Don't rely on tags for CraftItemMetas
20d107e46 SPIGOT-7846: Fix ItemMeta for hanging signs
76f59e315 Remove redundant clone in Dropper InventoryMoveItemEvent
e61a53d25 SPIGOT-7817: Call InventoryMoveItemEvent for Crafters
894682e2d SPIGOT-7839: Remove redundant Java version checks
2c12b2187 SPIGOT-7809: Add ShieldMeta and fix setting shield base colours

Spigot Changes:
fb8fb722 Rebuild patches
34bd42b7 SPIGOT-7835: Fix issue with custom hopper settings
2024-08-09 22:05:50 +02:00
Nassim Jahnke
4e6a2a13a3
Check for block type in SculkSensorBlock#canActivate 2024-08-07 14:34:12 +02:00
granny
042f15ffbd
[ci skip] chore: fix incorrect commit hash in PR builds (#11198)
* fix incorrect hash in PR builds

* only apply ref on pull_request triggers
2024-08-06 10:37:26 -07:00
metabrix
7e44684a1f
Fix wrong assumption about locale being null in the login phase (#11204)
Fixes #11203
2024-08-05 21:02:19 +02:00
Nassim Jahnke
5a5c3a4a24
Remove chunk unload trace debug
The issue the patch was initially added for has already been fixed and filling stacktraces can be expensive
2024-08-05 19:57:34 +02:00
Spottedleaf
df3b6544f7 ConcurrentUtil: Fix concurrent long map resize chain pull function
The function assumed that the current resize chain pointed to
the previous table, when in fact it pointed to the current table.

The function is supposed to restore the resize chain to the previous
table, previous increment, and previous index + new increment.
2024-08-01 16:55:33 -07:00
Spottedleaf
0a1be9ae87 Make loadChunksForMoveAsync use new chunk system load calls
This is to allow the call to work properly when on Folia,
as Folia does not have a main thread.
2024-07-30 19:50:14 -07:00
Jason Penilla
58c7ea3193
Preserve command node when re-registering modern commands through old API (#11184)
* Preserve command node when re-registering modern commands through old API

* make fix more targeted

mainly because it didn't work for vanilla commands :)
2024-07-30 11:42:55 -07:00
Jason Penilla
67d414a927
Allow plugin aliases to override vanilla commands (#11186)
fixes #11035
2024-07-30 11:28:05 -07:00
Spottedleaf
227544cfc7 Move TickThread changes from Moonrise patch to MCUtils
The common changes from Moonrise should be entirely in MCUtils
2024-07-30 05:32:20 -07:00
Shane Freeder
100d75a11c
Don't entirely die just because a plugin jar was bad 2024-07-29 16:54:46 +01:00
Shane Freeder
438863c4c5
Shutdown L4J cordially if the server stops before it's even started (#11172)
primarily, this allows us to ensure that appenders are flushed, console, log files
before the JVM exits to avoid issues such as error messages disappearing
2024-07-29 16:10:53 +01:00
Spottedleaf
0246a9da86 Add mob bucket items to item id to entity map in DataConverter
Mojang missed these in their mapping. Since the entity data
is used when spawning the bucketed mob, we need to have these
inside the id map to ensure that the entity data is converted
correctly if the entity id is missing.
2024-07-28 17:40:59 -07:00
Spottedleaf
3234b20ee4 Do not allow chunk unloading outside of the regular tick loop
Allowing chunk loading to occur at any point via purgeUnload()
introduces possible undesirable behavior to occur recursively
inside the chunk system.
2024-07-28 16:18:25 -07:00
Spottedleaf
50bdfc3e2c Null check tracker in Entity#resendPossiblyDesyncedEntityData
Accidentally dropped this check last commit. It is possible
that this is called while the entity is not tracked.
2024-07-28 15:49:38 -07:00
Spottedleaf
f774787a39 Copy missed changes to chunk system from Folia 2024-07-28 15:34:07 -07:00
Spottedleaf
694b120d0b Remove Entity tracker field
Now the only tracker field is from the entity tracker
optimisations.
2024-07-28 15:28:52 -07:00
Jake Potrebic
f82bea6940
Add argument for FinePosition to brig API (#11094) 2024-07-28 11:23:18 -07:00
powercas_gamer
dcbd99de4a
Fix Owen's typos (#11179) 2024-07-28 10:58:57 -07:00
Tamion
66165f712a
Fix PickupStatus getting reset (#11154) 2024-07-27 16:37:51 +02:00
Newwind
645a677122
Make max interaction range configurable (#11164)
The server validates incoming interaction packets by ensuring the player
sending them is inside their interaction range. For this, the server adds
a magic value, by default 1.0, to the original interaction range to
account for latency issues.

This value however may be too low in high latency environments.
The patch exposes a new configuration option to configure said value.
2024-07-27 14:18:16 +02:00
Shane Freeder
e1462a9253
Bump MCUtils#asyncExecutor core size
Long ago we discovered that the default thread pools would not increase
the number of threads running the pool until queue addition failed.
Bumping the core size mitigates an issue with spark-paper, and in general,
keeping async threads around generally beats having to spin new ones
everytime we want to execute a periodic async task.
2024-07-26 13:43:48 +01:00
Lulu13022002
5a5035be96
Fix a couple of ItemMeta related NPEs (#11149) 2024-07-23 10:11:00 +02:00
powercas_gamer
5512af798f
[ci skip] remove timings from issue templates (#11127) 2024-07-22 23:30:57 +02:00
Lulu13022002
73a863b337
Fix horse inventories indices (#11139) 2024-07-22 15:17:25 +02:00
Tamion
aa36ae6576
Fix EntityUnleashEvent cancellation on distance cause (#11131) 2024-07-21 12:33:37 +02:00
1303 changed files with 25339 additions and 8767 deletions

View file

@ -44,10 +44,10 @@ body:
```
> version
[20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT)
[20:34:42 INFO]: Checking version, please wait...
[20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5)
[20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT)
[20:34:42 INFO]: You are running the latest version
[20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21)
```
</details>

View file

@ -5,7 +5,7 @@ contact_links:
about: Suggest an idea for Paper
- name: PaperMC Discord
url: https://discord.gg/papermc
about: If you are having issues with timings or have other minor issues, come ask us on our Discord server!
about: If you are having issues with spark or have other minor issues, come ask us on our Discord server!
- name: Exploit Report
url: https://discord.gg/papermc
about: |

View file

@ -10,9 +10,9 @@ body:
- type: input
attributes:
label: Timings or Profile link
description: We ask that all timings/profiles are a link, not a screenshot. Screenshots inhibit our ability to figure out the real cause of the issue.
placeholder: "Example: https://timings.aikar.co/?id=6b48586fbbdd48e585ca0ebb07c59dd0"
label: Profile link
description: We ask that all profiles are a link, not a screenshot. Screenshots inhibit our ability to figure out the real cause of the issue.
placeholder: "Example: https://spark.lucko.me/XsN0hxGfsi"
validations:
required: true
@ -56,10 +56,10 @@ body:
```
> version
[20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT)
[20:34:42 INFO]: Checking version, please wait...
[20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5)
[20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT)
[20:34:42 INFO]: You are running the latest version
[20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21)
```
</details>

View file

@ -44,10 +44,10 @@ body:
```
> version
[20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT)
[20:34:42 INFO]: Checking version, please wait...
[20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5)
[20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT)
[20:34:42 INFO]: You are running the latest version
[20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21)
```
</details>

View file

@ -24,7 +24,12 @@ jobs:
java: [21]
fail-fast: true
steps:
- uses: actions/checkout@v4
- if: ${{ github.event_name == 'push' }}
uses: actions/checkout@v4
- if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: JDK ${{ matrix.java }}
uses: actions/setup-java@v4
with:

View file

@ -56,7 +56,6 @@ split into different directories which target certain parts of the code. These
directories are:
- `Paper-API` - Modifications to `Spigot-API`/`Bukkit`;
- `Paper-MojangAPI` - An API for [Mojang's Brigadier](https://github.com/Mojang/brigadier);
- `Paper-Server` - Modifications to `Spigot`/`CraftBukkit`.
Because the entire structure is based on patches and git, a basic understanding
@ -97,7 +96,9 @@ Your commit will be converted into a patch that you can then PR into Paper.
## Modifying Patches
Modifying previous patches is a bit more complex:
Modifying previous patches is a bit more complex.
Similar to adding patches, the methods to modify a patch are applied inside
the `Paper-Server` and/or `Paper-API` folders.
### Method 1
@ -248,6 +249,17 @@ instead of adding a new import to the top of the file. If you are using a type a
can add an import with a comment. However, if its only used a couple of times, the FQN is preferred to prevent future
patch conflicts in the import section of the file.
### Nullability annotations
We are in the process of switching nullability annotation libraries, so you might need to use one or the other:
**For classes we add**: Fields, method parameters and return types that are nullable should be marked via the
`@Nullable` annotation from `org.jspecify.annotations`. Whenever you create a new class, add `@NullMarked`, meaning types
are assumed to be non-null by default. For less obvious placing such as on generics or arrays, see the [JSpecify docs](https://jspecify.dev/docs/user-guide/).
**For classes added by upstream**: Keep using both `@Nullable` and `@NotNull` from `org.jetbrains.annotations`. These
will be replaced later.
```java
import org.bukkit.event.Event;
// don't add import here, use FQN like below

View file

@ -64,4 +64,5 @@ Oliwier Miodun <naczs@blueflow.pl>
aerulion <aerulion@gmail.com>
Lukas Planz <lukas.planz@web.de>
granny <contact@granny.dev>
mja00 <me@mja00.dev>
```

View file

@ -40,7 +40,7 @@ How To (Plugin Developers)
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<version>1.21.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
```
@ -53,7 +53,7 @@ repositories {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
}
java {

14
SECURITY.md Normal file
View file

@ -0,0 +1,14 @@
# Security Policy
## Supported Versions
We generally only fully support the latest version, the same applies to exploits such as server crashes and item
duplication bugs. In the transition period during larger Minecraft updates, we may still backport important fixes to the
last minor or major release.
## Reporting a Vulnerability
For any issues that are NOT duplication bugs, server/client crashes, or otherwise serious exploits, please open an issue
through the [Issues tab](https://github.com/PaperMC/Paper/issues).
For exploits, please [join our Discord](https://discord.gg/papermc) and see the [#paper-exploit-report channel](https://discord.com/channels/289587909051416579/1208749386348101682) for
further instructions.

View file

@ -11,7 +11,7 @@ import kotlin.io.path.*
plugins {
java
`maven-publish`
id("io.papermc.paperweight.core") version "1.7.1"
id("io.papermc.paperweight.core") version "1.7.3"
}
allprojects {
@ -67,7 +67,7 @@ repositories {
}
dependencies {
paramMappings("net.fabricmc:yarn:1.21+build.1:mergedv2")
paramMappings("net.fabricmc:yarn:1.21.1+build.3:mergedv2")
remapper("net.fabricmc:tiny-remapper:0.10.3:fat")
decompiler("org.vineflower:vineflower:1.10.1")
spigotDecompiler("io.papermc:patched-spigot-fernflower:0.1+build.13")

View file

@ -1,6 +1,6 @@
group=io.papermc.paper
version=1.21-R0.1-SNAPSHOT
mcVersion=1.21
version=1.21.1-R0.1-SNAPSHOT
mcVersion=1.21.1
# Set to true while updating Minecraft version
updatingMinecraft=false

View file

@ -51,7 +51,7 @@ import org.bukkit.entity.WanderingTrader;
import org.bukkit.entity.Wither;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.Zombie;
import org.jetbrains.annotations.NotNull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Vanilla keys for Mob Goals.
@ -66,7 +66,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<AbstractHorse> RANDOM_STAND = create("random_stand", AbstractHorse.class);
@ -436,8 +436,8 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Zombie> ZOMBIE_ATTACK_TURTLE_EGG = create("zombie_attack_turtle_egg", Zombie.class);
private static <T extends Mob> @NotNull GoalKey<T> create(final @NotNull String key,
final @NotNull Class<T> type) {
private static <T extends Mob> @NonNull GoalKey<T> create(final @NonNull String key,
final @NonNull Class<T> type) {
return GoalKey.of(type, NamespacedKey.minecraft(key));
}
}

View file

@ -0,0 +1,343 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.block.banner.PatternType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#BANNER_PATTERN}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class BannerPatternKeys {
/**
* {@code minecraft:base}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> BASE = create(key("base"));
/**
* {@code minecraft:border}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> BORDER = create(key("border"));
/**
* {@code minecraft:bricks}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> BRICKS = create(key("bricks"));
/**
* {@code minecraft:circle}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> CIRCLE = create(key("circle"));
/**
* {@code minecraft:creeper}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> CREEPER = create(key("creeper"));
/**
* {@code minecraft:cross}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> CROSS = create(key("cross"));
/**
* {@code minecraft:curly_border}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> CURLY_BORDER = create(key("curly_border"));
/**
* {@code minecraft:diagonal_left}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> DIAGONAL_LEFT = create(key("diagonal_left"));
/**
* {@code minecraft:diagonal_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> DIAGONAL_RIGHT = create(key("diagonal_right"));
/**
* {@code minecraft:diagonal_up_left}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> DIAGONAL_UP_LEFT = create(key("diagonal_up_left"));
/**
* {@code minecraft:diagonal_up_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> DIAGONAL_UP_RIGHT = create(key("diagonal_up_right"));
/**
* {@code minecraft:flow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> FLOW = create(key("flow"));
/**
* {@code minecraft:flower}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> FLOWER = create(key("flower"));
/**
* {@code minecraft:globe}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> GLOBE = create(key("globe"));
/**
* {@code minecraft:gradient}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> GRADIENT = create(key("gradient"));
/**
* {@code minecraft:gradient_up}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> GRADIENT_UP = create(key("gradient_up"));
/**
* {@code minecraft:guster}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> GUSTER = create(key("guster"));
/**
* {@code minecraft:half_horizontal}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> HALF_HORIZONTAL = create(key("half_horizontal"));
/**
* {@code minecraft:half_horizontal_bottom}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> HALF_HORIZONTAL_BOTTOM = create(key("half_horizontal_bottom"));
/**
* {@code minecraft:half_vertical}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> HALF_VERTICAL = create(key("half_vertical"));
/**
* {@code minecraft:half_vertical_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> HALF_VERTICAL_RIGHT = create(key("half_vertical_right"));
/**
* {@code minecraft:mojang}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> MOJANG = create(key("mojang"));
/**
* {@code minecraft:piglin}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> PIGLIN = create(key("piglin"));
/**
* {@code minecraft:rhombus}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> RHOMBUS = create(key("rhombus"));
/**
* {@code minecraft:skull}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SKULL = create(key("skull"));
/**
* {@code minecraft:small_stripes}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SMALL_STRIPES = create(key("small_stripes"));
/**
* {@code minecraft:square_bottom_left}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SQUARE_BOTTOM_LEFT = create(key("square_bottom_left"));
/**
* {@code minecraft:square_bottom_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SQUARE_BOTTOM_RIGHT = create(key("square_bottom_right"));
/**
* {@code minecraft:square_top_left}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SQUARE_TOP_LEFT = create(key("square_top_left"));
/**
* {@code minecraft:square_top_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> SQUARE_TOP_RIGHT = create(key("square_top_right"));
/**
* {@code minecraft:straight_cross}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRAIGHT_CROSS = create(key("straight_cross"));
/**
* {@code minecraft:stripe_bottom}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_BOTTOM = create(key("stripe_bottom"));
/**
* {@code minecraft:stripe_center}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_CENTER = create(key("stripe_center"));
/**
* {@code minecraft:stripe_downleft}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_DOWNLEFT = create(key("stripe_downleft"));
/**
* {@code minecraft:stripe_downright}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_DOWNRIGHT = create(key("stripe_downright"));
/**
* {@code minecraft:stripe_left}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_LEFT = create(key("stripe_left"));
/**
* {@code minecraft:stripe_middle}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_MIDDLE = create(key("stripe_middle"));
/**
* {@code minecraft:stripe_right}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_RIGHT = create(key("stripe_right"));
/**
* {@code minecraft:stripe_top}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> STRIPE_TOP = create(key("stripe_top"));
/**
* {@code minecraft:triangle_bottom}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> TRIANGLE_BOTTOM = create(key("triangle_bottom"));
/**
* {@code minecraft:triangle_top}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> TRIANGLE_TOP = create(key("triangle_top"));
/**
* {@code minecraft:triangles_bottom}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> TRIANGLES_BOTTOM = create(key("triangles_bottom"));
/**
* {@code minecraft:triangles_top}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PatternType> TRIANGLES_TOP = create(key("triangles_top"));
private BannerPatternKeys() {
}
/**
* Creates a key for {@link PatternType} in the registry {@code minecraft:banner_pattern}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NonNull TypedKey<PatternType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.BANNER_PATTERN, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.block.Biome;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#BIOME}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class BiomeKeys {
/**
@ -478,13 +478,13 @@ public final class BiomeKeys {
}
/**
* Creates a key for {@link Biome} in a registry.
* Creates a key for {@link Biome} in the registry {@code minecraft:worldgen/biome}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<Biome> create(final @NotNull Key key) {
public static @NonNull TypedKey<Biome> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.BIOME, key);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.Cat;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#CAT_VARIANT}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class CatVariantKeys {
/**
* {@code minecraft:all_black}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> ALL_BLACK = create(key("all_black"));
/**
* {@code minecraft:black}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> BLACK = create(key("black"));
/**
* {@code minecraft:british_shorthair}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> BRITISH_SHORTHAIR = create(key("british_shorthair"));
/**
* {@code minecraft:calico}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> CALICO = create(key("calico"));
/**
* {@code minecraft:jellie}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> JELLIE = create(key("jellie"));
/**
* {@code minecraft:persian}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> PERSIAN = create(key("persian"));
/**
* {@code minecraft:ragdoll}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> RAGDOLL = create(key("ragdoll"));
/**
* {@code minecraft:red}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> RED = create(key("red"));
/**
* {@code minecraft:siamese}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> SIAMESE = create(key("siamese"));
/**
* {@code minecraft:tabby}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> TABBY = create(key("tabby"));
/**
* {@code minecraft:white}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Cat.Type> WHITE = create(key("white"));
private CatVariantKeys() {
}
private static @NonNull TypedKey<Cat.Type> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.CAT_VARIANT, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.damage.DamageType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#DAMAGE_TYPE}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class DamageTypeKeys {
/**
@ -359,13 +359,13 @@ public final class DamageTypeKeys {
}
/**
* Creates a key for {@link DamageType} in a registry.
* Creates a key for {@link DamageType} in the registry {@code minecraft:damage_type}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<DamageType> create(final @NotNull Key key) {
public static @NonNull TypedKey<DamageType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.DAMAGE_TYPE, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.enchantments.Enchantment;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#ENCHANTMENT}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class EnchantmentKeys {
/**
@ -323,7 +323,7 @@ public final class EnchantmentKeys {
private EnchantmentKeys() {
}
private static @NotNull TypedKey<Enchantment> create(final @NotNull Key key) {
private static @NonNull TypedKey<Enchantment> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.ENCHANTMENT, key);
}
}

View file

@ -0,0 +1,56 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.Frog;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#FROG_VARIANT}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class FrogVariantKeys {
/**
* {@code minecraft:cold}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Frog.Variant> COLD = create(key("cold"));
/**
* {@code minecraft:temperate}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Frog.Variant> TEMPERATE = create(key("temperate"));
/**
* {@code minecraft:warm}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Frog.Variant> WARM = create(key("warm"));
private FrogVariantKeys() {
}
private static @NonNull TypedKey<Frog.Variant> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.FROG_VARIANT, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.GameEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#GAME_EVENT}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class GameEventKeys {
/**
@ -449,7 +449,7 @@ public final class GameEventKeys {
private GameEventKeys() {
}
private static @NotNull TypedKey<GameEvent> create(final @NotNull Key key) {
private static @NonNull TypedKey<GameEvent> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.GAME_EVENT, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.MusicInstrument;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#INSTRUMENT}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class InstrumentKeys {
/**
@ -85,7 +85,7 @@ public final class InstrumentKeys {
private InstrumentKeys() {
}
private static @NotNull TypedKey<MusicInstrument> create(final @NotNull Key key) {
private static @NonNull TypedKey<MusicInstrument> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.INSTRUMENT, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.inventory.ItemType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#ITEM}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class ItemTypeKeys {
/**
@ -9360,7 +9360,7 @@ public final class ItemTypeKeys {
private ItemTypeKeys() {
}
private static @NotNull TypedKey<ItemType> create(final @NotNull Key key) {
private static @NonNull TypedKey<ItemType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.ITEM, key);
}
}

View file

@ -0,0 +1,175 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.JukeboxSong;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#JUKEBOX_SONG}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class JukeboxSongKeys {
/**
* {@code minecraft:11}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> ELEVEN = create(key("11"));
/**
* {@code minecraft:13}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> THIRTEEN = create(key("13"));
/**
* {@code minecraft:5}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> FIVE = create(key("5"));
/**
* {@code minecraft:blocks}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> BLOCKS = create(key("blocks"));
/**
* {@code minecraft:cat}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> CAT = create(key("cat"));
/**
* {@code minecraft:chirp}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> CHIRP = create(key("chirp"));
/**
* {@code minecraft:creator}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> CREATOR = create(key("creator"));
/**
* {@code minecraft:creator_music_box}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> CREATOR_MUSIC_BOX = create(key("creator_music_box"));
/**
* {@code minecraft:far}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> FAR = create(key("far"));
/**
* {@code minecraft:mall}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> MALL = create(key("mall"));
/**
* {@code minecraft:mellohi}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> MELLOHI = create(key("mellohi"));
/**
* {@code minecraft:otherside}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> OTHERSIDE = create(key("otherside"));
/**
* {@code minecraft:pigstep}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> PIGSTEP = create(key("pigstep"));
/**
* {@code minecraft:precipice}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> PRECIPICE = create(key("precipice"));
/**
* {@code minecraft:relic}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> RELIC = create(key("relic"));
/**
* {@code minecraft:stal}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> STAL = create(key("stal"));
/**
* {@code minecraft:strad}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> STRAD = create(key("strad"));
/**
* {@code minecraft:wait}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> WAIT = create(key("wait"));
/**
* {@code minecraft:ward}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<JukeboxSong> WARD = create(key("ward"));
private JukeboxSongKeys() {
}
/**
* Creates a key for {@link JukeboxSong} in the registry {@code minecraft:jukebox_song}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NonNull TypedKey<JukeboxSong> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.JUKEBOX_SONG, key);
}
}

View file

@ -0,0 +1,280 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.map.MapCursor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#MAP_DECORATION_TYPE}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class MapDecorationTypeKeys {
/**
* {@code minecraft:banner_black}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_BLACK = create(key("banner_black"));
/**
* {@code minecraft:banner_blue}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_BLUE = create(key("banner_blue"));
/**
* {@code minecraft:banner_brown}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_BROWN = create(key("banner_brown"));
/**
* {@code minecraft:banner_cyan}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_CYAN = create(key("banner_cyan"));
/**
* {@code minecraft:banner_gray}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_GRAY = create(key("banner_gray"));
/**
* {@code minecraft:banner_green}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_GREEN = create(key("banner_green"));
/**
* {@code minecraft:banner_light_blue}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_LIGHT_BLUE = create(key("banner_light_blue"));
/**
* {@code minecraft:banner_light_gray}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_LIGHT_GRAY = create(key("banner_light_gray"));
/**
* {@code minecraft:banner_lime}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_LIME = create(key("banner_lime"));
/**
* {@code minecraft:banner_magenta}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_MAGENTA = create(key("banner_magenta"));
/**
* {@code minecraft:banner_orange}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_ORANGE = create(key("banner_orange"));
/**
* {@code minecraft:banner_pink}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_PINK = create(key("banner_pink"));
/**
* {@code minecraft:banner_purple}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_PURPLE = create(key("banner_purple"));
/**
* {@code minecraft:banner_red}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_RED = create(key("banner_red"));
/**
* {@code minecraft:banner_white}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_WHITE = create(key("banner_white"));
/**
* {@code minecraft:banner_yellow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BANNER_YELLOW = create(key("banner_yellow"));
/**
* {@code minecraft:blue_marker}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> BLUE_MARKER = create(key("blue_marker"));
/**
* {@code minecraft:frame}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> FRAME = create(key("frame"));
/**
* {@code minecraft:jungle_temple}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> JUNGLE_TEMPLE = create(key("jungle_temple"));
/**
* {@code minecraft:mansion}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> MANSION = create(key("mansion"));
/**
* {@code minecraft:monument}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> MONUMENT = create(key("monument"));
/**
* {@code minecraft:player}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> PLAYER = create(key("player"));
/**
* {@code minecraft:player_off_limits}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> PLAYER_OFF_LIMITS = create(key("player_off_limits"));
/**
* {@code minecraft:player_off_map}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> PLAYER_OFF_MAP = create(key("player_off_map"));
/**
* {@code minecraft:red_marker}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> RED_MARKER = create(key("red_marker"));
/**
* {@code minecraft:red_x}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> RED_X = create(key("red_x"));
/**
* {@code minecraft:swamp_hut}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> SWAMP_HUT = create(key("swamp_hut"));
/**
* {@code minecraft:target_point}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> TARGET_POINT = create(key("target_point"));
/**
* {@code minecraft:target_x}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> TARGET_X = create(key("target_x"));
/**
* {@code minecraft:trial_chambers}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> TRIAL_CHAMBERS = create(key("trial_chambers"));
/**
* {@code minecraft:village_desert}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> VILLAGE_DESERT = create(key("village_desert"));
/**
* {@code minecraft:village_plains}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> VILLAGE_PLAINS = create(key("village_plains"));
/**
* {@code minecraft:village_savanna}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> VILLAGE_SAVANNA = create(key("village_savanna"));
/**
* {@code minecraft:village_snowy}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> VILLAGE_SNOWY = create(key("village_snowy"));
/**
* {@code minecraft:village_taiga}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MapCursor.Type> VILLAGE_TAIGA = create(key("village_taiga"));
private MapDecorationTypeKeys() {
}
private static @NonNull TypedKey<MapCursor.Type> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.MAP_DECORATION_TYPE, key);
}
}

View file

@ -0,0 +1,210 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.inventory.MenuType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#MENU}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class MenuTypeKeys {
/**
* {@code minecraft:anvil}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> ANVIL = create(key("anvil"));
/**
* {@code minecraft:beacon}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> BEACON = create(key("beacon"));
/**
* {@code minecraft:blast_furnace}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> BLAST_FURNACE = create(key("blast_furnace"));
/**
* {@code minecraft:brewing_stand}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> BREWING_STAND = create(key("brewing_stand"));
/**
* {@code minecraft:cartography_table}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> CARTOGRAPHY_TABLE = create(key("cartography_table"));
/**
* {@code minecraft:crafter_3x3}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> CRAFTER_3X3 = create(key("crafter_3x3"));
/**
* {@code minecraft:crafting}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> CRAFTING = create(key("crafting"));
/**
* {@code minecraft:enchantment}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> ENCHANTMENT = create(key("enchantment"));
/**
* {@code minecraft:furnace}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> FURNACE = create(key("furnace"));
/**
* {@code minecraft:generic_3x3}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_3X3 = create(key("generic_3x3"));
/**
* {@code minecraft:generic_9x1}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X1 = create(key("generic_9x1"));
/**
* {@code minecraft:generic_9x2}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X2 = create(key("generic_9x2"));
/**
* {@code minecraft:generic_9x3}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X3 = create(key("generic_9x3"));
/**
* {@code minecraft:generic_9x4}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X4 = create(key("generic_9x4"));
/**
* {@code minecraft:generic_9x5}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X5 = create(key("generic_9x5"));
/**
* {@code minecraft:generic_9x6}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GENERIC_9X6 = create(key("generic_9x6"));
/**
* {@code minecraft:grindstone}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> GRINDSTONE = create(key("grindstone"));
/**
* {@code minecraft:hopper}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> HOPPER = create(key("hopper"));
/**
* {@code minecraft:lectern}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> LECTERN = create(key("lectern"));
/**
* {@code minecraft:loom}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> LOOM = create(key("loom"));
/**
* {@code minecraft:merchant}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> MERCHANT = create(key("merchant"));
/**
* {@code minecraft:shulker_box}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> SHULKER_BOX = create(key("shulker_box"));
/**
* {@code minecraft:smithing}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> SMITHING = create(key("smithing"));
/**
* {@code minecraft:smoker}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> SMOKER = create(key("smoker"));
/**
* {@code minecraft:stonecutter}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MenuType> STONECUTTER = create(key("stonecutter"));
private MenuTypeKeys() {
}
private static @NonNull TypedKey<MenuType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.MENU, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.potion.PotionEffectType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#MOB_EFFECT}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class MobEffectKeys {
/**
@ -302,7 +302,7 @@ public final class MobEffectKeys {
private MobEffectKeys() {
}
private static @NotNull TypedKey<PotionEffectType> create(final @NotNull Key key) {
private static @NonNull TypedKey<PotionEffectType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.MOB_EFFECT, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.generator.structure.Structure;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#STRUCTURE}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class StructureKeys {
/**
@ -268,13 +268,13 @@ public final class StructureKeys {
}
/**
* Creates a key for {@link Structure} in a registry.
* Creates a key for {@link Structure} in the registry {@code minecraft:worldgen/structure}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<Structure> create(final @NotNull Key key) {
public static @NonNull TypedKey<Structure> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.STRUCTURE, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.generator.structure.StructureType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#STRUCTURE_TYPE}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class StructureTypeKeys {
/**
@ -141,7 +141,7 @@ public final class StructureTypeKeys {
private StructureTypeKeys() {
}
private static @NotNull TypedKey<StructureType> create(final @NotNull Key key) {
private static @NonNull TypedKey<StructureType> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.STRUCTURE_TYPE, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#TRIM_MATERIAL}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class TrimMaterialKeys {
/**
@ -100,13 +100,13 @@ public final class TrimMaterialKeys {
}
/**
* Creates a key for {@link TrimMaterial} in a registry.
* Creates a key for {@link TrimMaterial} in the registry {@code minecraft:trim_material}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<TrimMaterial> create(final @NotNull Key key) {
public static @NonNull TypedKey<TrimMaterial> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.TRIM_MATERIAL, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#TRIM_PATTERN}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class TrimPatternKeys {
/**
@ -156,13 +156,13 @@ public final class TrimPatternKeys {
}
/**
* Creates a key for {@link TrimPattern} in a registry.
* Creates a key for {@link TrimPattern} in the registry {@code minecraft:trim_pattern}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<TrimPattern> create(final @NotNull Key key) {
public static @NonNull TypedKey<TrimPattern> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.TRIM_PATTERN, key);
}
}

View file

@ -0,0 +1,140 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.Villager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#VILLAGER_PROFESSION}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class VillagerProfessionKeys {
/**
* {@code minecraft:armorer}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> ARMORER = create(key("armorer"));
/**
* {@code minecraft:butcher}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> BUTCHER = create(key("butcher"));
/**
* {@code minecraft:cartographer}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> CARTOGRAPHER = create(key("cartographer"));
/**
* {@code minecraft:cleric}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> CLERIC = create(key("cleric"));
/**
* {@code minecraft:farmer}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> FARMER = create(key("farmer"));
/**
* {@code minecraft:fisherman}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> FISHERMAN = create(key("fisherman"));
/**
* {@code minecraft:fletcher}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> FLETCHER = create(key("fletcher"));
/**
* {@code minecraft:leatherworker}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> LEATHERWORKER = create(key("leatherworker"));
/**
* {@code minecraft:librarian}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> LIBRARIAN = create(key("librarian"));
/**
* {@code minecraft:mason}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> MASON = create(key("mason"));
/**
* {@code minecraft:nitwit}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> NITWIT = create(key("nitwit"));
/**
* {@code minecraft:none}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> NONE = create(key("none"));
/**
* {@code minecraft:shepherd}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> SHEPHERD = create(key("shepherd"));
/**
* {@code minecraft:toolsmith}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> TOOLSMITH = create(key("toolsmith"));
/**
* {@code minecraft:weaponsmith}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Profession> WEAPONSMITH = create(key("weaponsmith"));
private VillagerProfessionKeys() {
}
private static @NonNull TypedKey<Villager.Profession> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.VILLAGER_PROFESSION, key);
}
}

View file

@ -0,0 +1,84 @@
package io.papermc.paper.registry.keys;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.Villager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
/**
* Vanilla keys for {@link RegistryKey#VILLAGER_TYPE}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class VillagerTypeKeys {
/**
* {@code minecraft:desert}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> DESERT = create(key("desert"));
/**
* {@code minecraft:jungle}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> JUNGLE = create(key("jungle"));
/**
* {@code minecraft:plains}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> PLAINS = create(key("plains"));
/**
* {@code minecraft:savanna}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> SAVANNA = create(key("savanna"));
/**
* {@code minecraft:snow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> SNOW = create(key("snow"));
/**
* {@code minecraft:swamp}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> SWAMP = create(key("swamp"));
/**
* {@code minecraft:taiga}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Villager.Type> TAIGA = create(key("taiga"));
private VillagerTypeKeys() {
}
private static @NonNull TypedKey<Villager.Type> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.VILLAGER_TYPE, key);
}
}

View file

@ -7,8 +7,8 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.Wolf;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#WOLF_VARIANT}.
@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class WolfVariantKeys {
/**
@ -93,13 +93,13 @@ public final class WolfVariantKeys {
}
/**
* Creates a key for {@link Wolf.Variant} in a registry.
* Creates a key for {@link Wolf.Variant} in the registry {@code minecraft:wolf_variant}.
*
* @param key the value's key in the registry
* @return a new typed key
*/
@ApiStatus.Experimental
public static @NotNull TypedKey<Wolf.Variant> create(final @NotNull Key key) {
public static @NonNull TypedKey<Wolf.Variant> create(final @NonNull Key key) {
return TypedKey.create(RegistryKey.WOLF_VARIANT, key);
}
}

View file

@ -8,8 +8,8 @@ import io.papermc.paper.registry.tag.TagKey;
import net.kyori.adventure.key.Key;
import org.bukkit.MinecraftExperimental;
import org.bukkit.enchantments.Enchantment;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Vanilla keys for {@link RegistryKey#ENCHANTMENT}.
@ -24,66 +24,9 @@ import org.jetbrains.annotations.NotNull;
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21")
@GeneratedFrom("1.21.1")
@ApiStatus.Experimental
public final class EnchantmentTagKeys {
/**
* {@code #minecraft:trades/swamp_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SWAMP_SPECIAL = create(key("trades/swamp_special"));
/**
* {@code #minecraft:trades/plains_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_PLAINS_SPECIAL = create(key("trades/plains_special"));
/**
* {@code #minecraft:on_traded_equipment}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> ON_TRADED_EQUIPMENT = create(key("on_traded_equipment"));
/**
* {@code #minecraft:trades/desert_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_DESERT_SPECIAL = create(key("trades/desert_special"));
/**
* {@code #minecraft:prevents_ice_melting}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_ICE_MELTING = create(key("prevents_ice_melting"));
/**
* {@code #minecraft:trades/taiga_common}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_TAIGA_COMMON = create(key("trades/taiga_common"));
/**
* {@code #minecraft:tradeable}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TRADEABLE = create(key("tradeable"));
/**
* {@code #minecraft:curse}
*
@ -91,36 +34,6 @@ public final class EnchantmentTagKeys {
*/
public static final TagKey<Enchantment> CURSE = create(key("curse"));
/**
* {@code #minecraft:treasure}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TREASURE = create(key("treasure"));
/**
* {@code #minecraft:prevents_infested_spawns}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_INFESTED_SPAWNS = create(key("prevents_infested_spawns"));
/**
* {@code #minecraft:trades/savanna_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SAVANNA_SPECIAL = create(key("trades/savanna_special"));
/**
* {@code #minecraft:exclusive_set/riptide}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_RIPTIDE = create(key("exclusive_set/riptide"));
/**
* {@code #minecraft:double_trade_price}
*
@ -129,20 +42,11 @@ public final class EnchantmentTagKeys {
public static final TagKey<Enchantment> DOUBLE_TRADE_PRICE = create(key("double_trade_price"));
/**
* {@code #minecraft:trades/taiga_special}
* {@code #minecraft:exclusive_set/armor}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_TAIGA_SPECIAL = create(key("trades/taiga_special"));
/**
* {@code #minecraft:smelts_loot}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> SMELTS_LOOT = create(key("smelts_loot"));
public static final TagKey<Enchantment> EXCLUSIVE_SET_ARMOR = create(key("exclusive_set/armor"));
/**
* {@code #minecraft:exclusive_set/boots}
@ -152,13 +56,53 @@ public final class EnchantmentTagKeys {
public static final TagKey<Enchantment> EXCLUSIVE_SET_BOOTS = create(key("exclusive_set/boots"));
/**
* {@code #minecraft:trades/plains_common}
* {@code #minecraft:exclusive_set/bow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_PLAINS_COMMON = create(key("trades/plains_common"));
public static final TagKey<Enchantment> EXCLUSIVE_SET_BOW = create(key("exclusive_set/bow"));
/**
* {@code #minecraft:exclusive_set/crossbow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_CROSSBOW = create(key("exclusive_set/crossbow"));
/**
* {@code #minecraft:exclusive_set/damage}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_DAMAGE = create(key("exclusive_set/damage"));
/**
* {@code #minecraft:exclusive_set/mining}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_MINING = create(key("exclusive_set/mining"));
/**
* {@code #minecraft:exclusive_set/riptide}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_RIPTIDE = create(key("exclusive_set/riptide"));
/**
* {@code #minecraft:in_enchanting_table}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> IN_ENCHANTING_TABLE = create(key("in_enchanting_table"));
/**
* {@code #minecraft:non_treasure}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> NON_TREASURE = create(key("non_treasure"));
/**
* {@code #minecraft:on_mob_spawn_equipment}
@ -167,6 +111,69 @@ public final class EnchantmentTagKeys {
*/
public static final TagKey<Enchantment> ON_MOB_SPAWN_EQUIPMENT = create(key("on_mob_spawn_equipment"));
/**
* {@code #minecraft:on_random_loot}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> ON_RANDOM_LOOT = create(key("on_random_loot"));
/**
* {@code #minecraft:on_traded_equipment}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> ON_TRADED_EQUIPMENT = create(key("on_traded_equipment"));
/**
* {@code #minecraft:prevents_bee_spawns_when_mining}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_BEE_SPAWNS_WHEN_MINING = create(key("prevents_bee_spawns_when_mining"));
/**
* {@code #minecraft:prevents_decorated_pot_shattering}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_DECORATED_POT_SHATTERING = create(key("prevents_decorated_pot_shattering"));
/**
* {@code #minecraft:prevents_ice_melting}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_ICE_MELTING = create(key("prevents_ice_melting"));
/**
* {@code #minecraft:prevents_infested_spawns}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_INFESTED_SPAWNS = create(key("prevents_infested_spawns"));
/**
* {@code #minecraft:smelts_loot}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> SMELTS_LOOT = create(key("smelts_loot"));
/**
* {@code #minecraft:tooltip_order}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TOOLTIP_ORDER = create(key("tooltip_order"));
/**
* {@code #minecraft:tradeable}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TRADEABLE = create(key("tradeable"));
/**
* {@code #minecraft:trades/desert_common}
*
@ -177,46 +184,13 @@ public final class EnchantmentTagKeys {
public static final TagKey<Enchantment> TRADES_DESERT_COMMON = create(key("trades/desert_common"));
/**
* {@code #minecraft:exclusive_set/mining}
* {@code #minecraft:trades/desert_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_MINING = create(key("exclusive_set/mining"));
/**
* {@code #minecraft:tooltip_order}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TOOLTIP_ORDER = create(key("tooltip_order"));
/**
* {@code #minecraft:prevents_decorated_pot_shattering}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_DECORATED_POT_SHATTERING = create(key("prevents_decorated_pot_shattering"));
/**
* {@code #minecraft:exclusive_set/bow}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_BOW = create(key("exclusive_set/bow"));
/**
* {@code #minecraft:on_random_loot}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> ON_RANDOM_LOOT = create(key("on_random_loot"));
/**
* {@code #minecraft:exclusive_set/armor}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_ARMOR = create(key("exclusive_set/armor"));
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_DESERT_SPECIAL = create(key("trades/desert_special"));
/**
* {@code #minecraft:trades/jungle_common}
@ -227,38 +201,6 @@ public final class EnchantmentTagKeys {
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_JUNGLE_COMMON = create(key("trades/jungle_common"));
/**
* {@code #minecraft:in_enchanting_table}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> IN_ENCHANTING_TABLE = create(key("in_enchanting_table"));
/**
* {@code #minecraft:trades/swamp_common}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SWAMP_COMMON = create(key("trades/swamp_common"));
/**
* {@code #minecraft:trades/snow_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SNOW_SPECIAL = create(key("trades/snow_special"));
/**
* {@code #minecraft:non_treasure}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> NON_TREASURE = create(key("non_treasure"));
/**
* {@code #minecraft:trades/jungle_special}
*
@ -269,18 +211,22 @@ public final class EnchantmentTagKeys {
public static final TagKey<Enchantment> TRADES_JUNGLE_SPECIAL = create(key("trades/jungle_special"));
/**
* {@code #minecraft:prevents_bee_spawns_when_mining}
* {@code #minecraft:trades/plains_common}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> PREVENTS_BEE_SPAWNS_WHEN_MINING = create(key("prevents_bee_spawns_when_mining"));
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_PLAINS_COMMON = create(key("trades/plains_common"));
/**
* {@code #minecraft:exclusive_set/damage}
* {@code #minecraft:trades/plains_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_DAMAGE = create(key("exclusive_set/damage"));
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_PLAINS_SPECIAL = create(key("trades/plains_special"));
/**
* {@code #minecraft:trades/savanna_common}
@ -291,6 +237,15 @@ public final class EnchantmentTagKeys {
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SAVANNA_COMMON = create(key("trades/savanna_common"));
/**
* {@code #minecraft:trades/savanna_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SAVANNA_SPECIAL = create(key("trades/savanna_special"));
/**
* {@code #minecraft:trades/snow_common}
*
@ -301,23 +256,68 @@ public final class EnchantmentTagKeys {
public static final TagKey<Enchantment> TRADES_SNOW_COMMON = create(key("trades/snow_common"));
/**
* {@code #minecraft:exclusive_set/crossbow}
* {@code #minecraft:trades/snow_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> EXCLUSIVE_SET_CROSSBOW = create(key("exclusive_set/crossbow"));
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SNOW_SPECIAL = create(key("trades/snow_special"));
/**
* {@code #minecraft:trades/swamp_common}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SWAMP_COMMON = create(key("trades/swamp_common"));
/**
* {@code #minecraft:trades/swamp_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_SWAMP_SPECIAL = create(key("trades/swamp_special"));
/**
* {@code #minecraft:trades/taiga_common}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_TAIGA_COMMON = create(key("trades/taiga_common"));
/**
* {@code #minecraft:trades/taiga_special}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
@ApiStatus.Experimental
@MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE)
public static final TagKey<Enchantment> TRADES_TAIGA_SPECIAL = create(key("trades/taiga_special"));
/**
* {@code #minecraft:treasure}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<Enchantment> TREASURE = create(key("treasure"));
private EnchantmentTagKeys() {
}
/**
* Creates a tag key for {@link Enchantment} in the registry {@code minecraft:root}.
* Creates a tag key for {@link Enchantment} in the registry {@code minecraft:enchantment}.
*
* @param key the tag key's key
* @return a new tag key
*/
@ApiStatus.Experimental
public static @NotNull TagKey<Enchantment> create(final @NotNull Key key) {
public static @NonNull TagKey<Enchantment> create(final @NonNull Key key) {
return TagKey.create(RegistryKey.ENCHANTMENT, key);
}
}

View file

@ -9,34 +9,55 @@ import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import org.bukkit.GameEvent;
import org.bukkit.JukeboxSong;
import org.bukkit.MusicInstrument;
import org.bukkit.block.Biome;
import org.bukkit.block.BlockType;
import org.bukkit.block.banner.PatternType;
import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemType;
import org.bukkit.inventory.MenuType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.map.MapCursor;
import org.bukkit.potion.PotionEffectType;
public interface Generators {
SourceGenerator[] API = {
// built-ins
simpleKey("GameEventKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT, false),
simpleKey("BiomeKeys", Biome.class, Registries.BIOME, RegistryKey.BIOME, true),
simpleKey("TrimMaterialKeys", TrimMaterial.class, Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, true),
simpleKey("TrimPatternKeys", TrimPattern.class, Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, true),
simpleKey("StructureKeys", Structure.class, Registries.STRUCTURE, RegistryKey.STRUCTURE, true),
simpleKey("StructureTypeKeys", StructureType.class, Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, false),
simpleKey("InstrumentKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT, false),
simpleKey("EnchantmentKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, false),
simpleKey("MobEffectKeys", PotionEffectType.class, Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, false),
simpleKey("BlockTypeKeys", BlockType.class, Registries.BLOCK, RegistryKey.BLOCK, false),
simpleKey("ItemTypeKeys", ItemType.class, Registries.ITEM, RegistryKey.ITEM, false),
simpleKey("CatVariantKeys", Cat.Type.class, Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, false),
simpleKey("FrogVariantKeys", Frog.Variant.class, Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, false),
simpleKey("VillagerProfessionKeys", Villager.Profession.class, Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, false),
simpleKey("VillagerTypeKeys", Villager.Type.class, Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, false),
simpleKey("MapDecorationTypeKeys", MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, false),
simpleKey("MenuTypeKeys", MenuType.class, Registries.MENU, RegistryKey.MENU, false),
// data-driven
simpleKey("BiomeKeys", Biome.class, Registries.BIOME, RegistryKey.BIOME, true),
simpleKey("StructureKeys", Structure.class, Registries.STRUCTURE, RegistryKey.STRUCTURE, true),
simpleKey("TrimMaterialKeys", TrimMaterial.class, Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, true),
simpleKey("TrimPatternKeys", TrimPattern.class, Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, true),
simpleKey("DamageTypeKeys", DamageType.class, Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, true),
simpleKey("WolfVariantKeys", Wolf.Variant.class, Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, true),
simpleKey("ItemTypeKeys", ItemType.class, Registries.ITEM, RegistryKey.ITEM, false),
simpleKey("EnchantmentKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, false),
simpleKey("JukeboxSongKeys", JukeboxSong.class, Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG, true),
simpleKey("BannerPatternKeys", PatternType.class, Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, true),
// tags
simpleTagKey("EnchantmentTagKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT),
simpleTagKey("ItemTypeTagKeys", ItemType.class, Registries.ITEM, RegistryKey.ITEM),
new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai")

View file

@ -31,8 +31,6 @@ import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.flag.FeatureElement;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.MinecraftExperimental;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
@ -72,7 +70,7 @@ public class GeneratedKeyType<T, A> extends SimpleGenerator {
}
private static final String CREATE_JAVADOC = """
Creates a key for {@link $T} in a registry.
Creates a key for {@link $T} in the registry {@code $L}.
@param key the value's key in the registry
@return a new typed key
@ -102,7 +100,7 @@ public class GeneratedKeyType<T, A> extends SimpleGenerator {
.returns(returnType.annotated(NOT_NULL));
if (this.publicCreateKeyMethod) {
create.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO remove once not experimental
create.addJavadoc(CREATE_JAVADOC, this.apiType);
create.addJavadoc(CREATE_JAVADOC, this.apiType, this.registryKey.location().toString());
}
return create;
}
@ -190,8 +188,6 @@ public class GeneratedKeyType<T, A> extends SimpleGenerator {
@Override
protected JavaFile.Builder file(final JavaFile.Builder builder) {
return builder
.skipJavaLangImports(true)
.addStaticImport(Key.class, "key")
.indent(" ");
.addStaticImport(Key.class, "key");
}
}

View file

@ -15,15 +15,11 @@ import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.tag.TagKey;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import net.kyori.adventure.key.Key;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.resources.ResourceKey;
import org.bukkit.MinecraftExperimental;
@ -39,11 +35,6 @@ import static javax.lang.model.element.Modifier.STATIC;
public class GeneratedTagKeyType<T, A> extends SimpleGenerator {
private static final Map<ResourceKey<? extends Registry<?>>, RegistrySetBuilder.RegistryBootstrap<?>> VANILLA_REGISTRY_ENTRIES = VanillaRegistries.BUILDER.entries.stream()
.collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap));
private static final Map<ResourceKey<? extends Registry<?>>, RegistrySetBuilder.RegistryBootstrap<?>> EXPERIMENTAL_REGISTRY_ENTRIES = Collections.emptyMap(); // Update for Experimental API
private static final Map<RegistryKey<?>, String> REGISTRY_KEY_FIELD_NAMES;
static {
final Map<RegistryKey<?>, String> map = new HashMap<>();
@ -91,7 +82,7 @@ public class GeneratedTagKeyType<T, A> extends SimpleGenerator {
.returns(returnType.annotated(NOT_NULL));
if (this.publicCreateKeyMethod) {
create.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO remove once not experimental
create.addJavadoc(CREATE_JAVADOC, this.apiType, this.registryKey.registry().toString());
create.addJavadoc(CREATE_JAVADOC, this.apiType, this.registryKey.location().toString());
}
return create;
}
@ -102,8 +93,8 @@ public class GeneratedTagKeyType<T, A> extends SimpleGenerator {
.addJavadoc(Javadocs.getVersionDependentClassHeader("{@link $T#$L}"), RegistryKey.class, REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey))
.addAnnotations(Annotations.CLASS_HEADER)
.addMethod(MethodSpec.constructorBuilder()
.addModifiers(PRIVATE)
.build()
.addModifiers(PRIVATE)
.build()
);
}
@ -117,8 +108,7 @@ public class GeneratedTagKeyType<T, A> extends SimpleGenerator {
final Registry<T> registry = Main.REGISTRY_ACCESS.registryOrThrow(this.registryKey);
final AtomicBoolean allExperimental = new AtomicBoolean(true);
registry.getTags().forEach(pair -> {
final net.minecraft.tags.TagKey<T> nmsTagKey = pair.getFirst();
registry.getTagNames().sorted(Formatting.alphabeticKeyOrder(nmsTagKey -> nmsTagKey.location().getPath())).forEach(nmsTagKey -> {
final String fieldName = Formatting.formatKeyAsField(nmsTagKey.location().getPath());
final FieldSpec.Builder fieldBuilder = FieldSpec.builder(tagKey, fieldName, PUBLIC, STATIC, FINAL)
.initializer("$N(key($S))", createMethod.build(), nmsTagKey.location().getPath())
@ -142,8 +132,6 @@ public class GeneratedTagKeyType<T, A> extends SimpleGenerator {
@Override
protected JavaFile.Builder file(final JavaFile.Builder builder) {
return builder
.skipJavaLangImports(true)
.addStaticImport(Key.class, "key")
.indent(" ");
.addStaticImport(Key.class, "key");
}
}

View file

@ -132,8 +132,7 @@ public class MobGoalGenerator extends SimpleGenerator {
@Override
protected JavaFile.Builder file(JavaFile.Builder builder) {
return builder
.skipJavaLangImports(true);
return builder;
}
record DeprecatedEntry(Class<?> entity, String entryName, @Nullable String removalVersion,

View file

@ -7,8 +7,8 @@ import java.util.List;
import io.papermc.paper.generated.GeneratedFrom;
import net.minecraft.SharedConstants;
import org.bukkit.MinecraftExperimental;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class Annotations {
@ -26,10 +26,10 @@ public final class Annotations {
return annotationSpecs;
}
public static AnnotationSpec deprecatedVersioned(final @Nullable String version, boolean forRemoval) {
AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(Deprecated.class);
public static AnnotationSpec deprecatedVersioned(final @Nullable String version, final boolean forRemoval) {
final AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(Deprecated.class);
if (forRemoval) {
annotationSpec.addMember("forRemoval", "$L", forRemoval);
annotationSpec.addMember("forRemoval", "$L", true);
}
if (version != null) {
annotationSpec.addMember("since", "$S", version);
@ -46,7 +46,7 @@ public final class Annotations {
@ApiStatus.Experimental
public static final AnnotationSpec EXPERIMENTAL_API_ANNOTATION = AnnotationSpec.builder(ApiStatus.Experimental.class).build();
public static final AnnotationSpec NOT_NULL = AnnotationSpec.builder(NotNull.class).build();
public static final AnnotationSpec NOT_NULL = AnnotationSpec.builder(NonNull.class).build();
private static final AnnotationSpec SUPPRESS_WARNINGS = AnnotationSpec.builder(SuppressWarnings.class)
.addMember("value", "$S", "unused")
.addMember("value", "$S", "SpellCheckingInspection")

View file

@ -2,7 +2,6 @@ package io.papermc.generator.utils;
import com.mojang.serialization.Lifecycle;
import io.papermc.generator.Main;
import java.util.List;
import java.util.Set;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderGetter;

View file

@ -1,5 +1,6 @@
package io.papermc.generator.utils;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.Comparator;
@ -12,8 +13,13 @@ public final class Formatting {
private static final Pattern ILLEGAL_FIELD_CHARACTERS = Pattern.compile("[.-/]");
private static final Map<String, String> MANUAL_OVERRIDES = Map.of(
"5", "five",
"11", "eleven",
"13", "thirteen"
);
public static String formatKeyAsField(String path) {
return ILLEGAL_FIELD_CHARACTERS.matcher(path.toUpperCase(Locale.ROOT)).replaceAll("_");
return ILLEGAL_FIELD_CHARACTERS.matcher(MANUAL_OVERRIDES.getOrDefault(path, path).toUpperCase(Locale.ROOT)).replaceAll("_");
}
public static Optional<String> formatTagKey(String tagDir, String resourcePath) {

View file

@ -4,7 +4,6 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.mojang.logging.LogUtils;
import io.papermc.generator.Main;
import io.papermc.generator.utils.Formatting;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
@ -19,7 +18,6 @@ import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.repository.BuiltInPackSource;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagManager;
import org.slf4j.Logger;
// collect all the tags by grabbing the json from the data-packs
@ -50,9 +48,9 @@ public final class TagCollector {
}
result.put(entry.value().getTagNames()
.filter(tagKey -> tagKey.location().getPath().equals(path))
.findFirst()
.orElseThrow(), packId);
.filter(tagKey -> tagKey.location().getPath().equals(path))
.findFirst()
.orElseThrow(), packId);
});
});
return Collections.unmodifiableMap(result);

View file

@ -124,7 +124,7 @@ index 0000000000000000000000000000000000000000..6271e2bad0ed937c2c46a8c8fdf186c4
+}
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 86628114c1d111f6d256186ca739ba8a44b3412a..0000000000000000000000000000000000000000
index 2c5ac393cffbe61330c5aa95115e7e906c0775d3..0000000000000000000000000000000000000000
--- a/pom.xml
+++ /dev/null
@@ -1,267 +0,0 @@
@ -135,7 +135,7 @@ index 86628114c1d111f6d256186ca739ba8a44b3412a..00000000000000000000000000000000
-
- <groupId>org.spigotmc</groupId>
- <artifactId>spigot-api</artifactId>
- <version>1.21-R0.1-SNAPSHOT</version>
- <version>1.21.1-R0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
-
- <name>Spigot-API</name>

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Build system changes
diff --git a/build.gradle.kts b/build.gradle.kts
index 6271e2bad0ed937c2c46a8c8fdf186c46b0b620e..a918fd14c95e714e935758d60bccd72755e00b11 100644
index 6271e2bad0ed937c2c46a8c8fdf186c46b0b620e..78aadebda145fe83327ceb430c4b38f9a8e45a2b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -18,15 +18,26 @@ dependencies {
@@ -18,15 +18,27 @@ dependencies {
api("net.md-5:bungeecord-chat:$bungeeCordChatVersion")
api("org.yaml:snakeyaml:2.2")
api("org.joml:joml:1.10.5")
@ -32,11 +32,12 @@ index 6271e2bad0ed937c2c46a8c8fdf186c46b0b620e..a918fd14c95e714e935758d60bccd727
+ compileOnlyApi(checkerQual)
+ testCompileOnly(checkerQual)
+ // Paper end
+ api("org.jspecify:jspecify:1.0.0") // Paper - add jspecify
+
testImplementation("org.apache.commons:commons-lang3:3.12.0")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testImplementation("org.hamcrest:hamcrest:2.2")
@@ -69,8 +80,12 @@ tasks.withType<Javadoc> {
@@ -69,8 +81,13 @@ tasks.withType<Javadoc> {
options.links(
"https://guava.dev/releases/32.1.2-jre/api/docs/",
"https://javadoc.io/doc/org.yaml/snakeyaml/2.2/",
@ -46,11 +47,12 @@ index 6271e2bad0ed937c2c46a8c8fdf186c46b0b620e..a918fd14c95e714e935758d60bccd727
+ // 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",
+ "https://jspecify.dev/docs/api/",
+ // Paper end
)
options.tags("apiNote:a:API Note:")
@@ -89,3 +104,14 @@ tasks.withType<Javadoc> {
@@ -89,3 +106,14 @@ tasks.withType<Javadoc> {
tasks.test {
useJUnitPlatform()
}

View file

@ -12,10 +12,10 @@ Co-authored-by: Riley Park <rileysebastianpark@gmail.com>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/build.gradle.kts b/build.gradle.kts
index a918fd14c95e714e935758d60bccd72755e00b11..768024b2b4584fd7dd86f068c0e79c89ffc5faa1 100644
index 78aadebda145fe83327ceb430c4b38f9a8e45a2b..8c7a5be5193ae397ec324d78566edce90608ed57 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -105,6 +105,12 @@ tasks.test {
@@ -107,6 +107,12 @@ tasks.test {
useJUnitPlatform()
}
@ -66,7 +66,7 @@ index 0000000000000000000000000000000000000000..77154095cfb8b259bdb318e8ff40cb6f
+ }
+}
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9d6888609 100644
index 64e7aef6220097edefdff3b98a771b988365930d..7ff939ea41417bad3a436a87c89d5efa7ecefe86 100644
--- a/src/test/java/org/bukkit/AnnotationTest.java
+++ b/src/test/java/org/bukkit/AnnotationTest.java
@@ -29,7 +29,13 @@ public class AnnotationTest {
@ -103,7 +103,19 @@ index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9
};
@Test
@@ -67,14 +83,48 @@ public class AnnotationTest {
@@ -61,20 +77,60 @@ public class AnnotationTest {
continue;
}
+ // Paper start - skip class if it's @NullMarked
+ if (isClassNullMarked(clazz)) {
+ return;
+ }
+ // Paper end - skip class if it's @NullMarked
+
for (MethodNode method : clazz.methods) {
if (!isMethodIncluded(clazz, method, foundClasses)) {
continue;
}
if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) {
@ -152,7 +164,7 @@ index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9
ParameterNode paramNode = parameters == null ? null : parameters.get(i);
String paramName = paramNode == null ? null : paramNode.name;
@@ -91,13 +141,18 @@ public class AnnotationTest {
@@ -91,13 +147,18 @@ public class AnnotationTest {
Collections.sort(errors);
@ -175,7 +187,20 @@ index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9
}
private static void collectClasses(@NotNull File from, @NotNull Map<String, ClassNode> to) throws IOException {
@@ -140,6 +195,11 @@ public class AnnotationTest {
@@ -125,6 +186,12 @@ public class AnnotationTest {
}
}
+ // Paper start - skip class if it's @NullMarked
+ private static boolean isClassNullMarked(@NotNull ClassNode clazz) {
+ return clazz.visibleAnnotations != null && clazz.visibleAnnotations.stream().anyMatch(node -> "Lorg/jspecify/annotations/NullMarked;".equals(node.desc));
+ }
+ // Paper end - skip class if it's @NullMarked
+
private static boolean isClassIncluded(@NotNull ClassNode clazz, @NotNull Map<String, ClassNode> allClasses) {
// Exclude private, synthetic or deprecated classes and annotations, since their members can't be null
if ((clazz.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ANNOTATION)) != 0) {
@@ -140,6 +207,11 @@ public class AnnotationTest {
// Exceptions are excluded
return false;
}
@ -187,7 +212,7 @@ index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9
for (String excludedClass : EXCLUDED_CLASSES) {
if (excludedClass.equals(clazz.name)) {
@@ -152,7 +212,7 @@ public class AnnotationTest {
@@ -152,7 +224,7 @@ public class AnnotationTest {
private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map<String, ClassNode> allClasses) {
// Exclude private, synthetic and deprecated methods
@ -196,7 +221,7 @@ index 64e7aef6220097edefdff3b98a771b988365930d..d9091ba1e5a55e03adca98305233cce9
return false;
}
@@ -170,11 +230,30 @@ public class AnnotationTest {
@@ -170,11 +242,30 @@ public class AnnotationTest {
if ("<init>".equals(method.name) && isAnonymous(clazz)) {
return false;
}

View file

@ -7,7 +7,7 @@ Currently includes generated key holder classes for types
used in the Registry Modification API
diff --git a/build.gradle.kts b/build.gradle.kts
index 768024b2b4584fd7dd86f068c0e79c89ffc5faa1..f11a22ab01e97e51619c96f2d8a78a99297efc59 100644
index 8c7a5be5193ae397ec324d78566edce90608ed57..877ea06c0ea8c8c0c73d23fbb996f6692c100d98 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,6 +1,7 @@
@ -18,7 +18,7 @@ index 768024b2b4584fd7dd86f068c0e79c89ffc5faa1..f11a22ab01e97e51619c96f2d8a78a99
}
java {
@@ -45,6 +46,22 @@ dependencies {
@@ -46,6 +47,22 @@ dependencies {
testImplementation("org.ow2.asm:asm-tree:9.7")
}
@ -41,7 +41,7 @@ index 768024b2b4584fd7dd86f068c0e79c89ffc5faa1..f11a22ab01e97e51619c96f2d8a78a99
configure<PublishingExtension> {
publications.create<MavenPublication>("maven") {
from(components["java"])
@@ -121,3 +138,14 @@ tasks.check {
@@ -123,3 +140,14 @@ tasks.check {
dependsOn(scanJar)
}
// Paper end
@ -85,10 +85,10 @@ index 0000000000000000000000000000000000000000..2512dba27edfdccbc4430815b6cba048
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd20c561286
index 0000000000000000000000000000000000000000..8410d7213370f01cbedbf7fac29bac96f150c49a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
@@ -0,0 +1,147 @@
@@ -0,0 +1,179 @@
+package io.papermc.paper.registry;
+
+import net.kyori.adventure.key.Keyed;
@ -114,12 +114,14 @@ index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd2
+import org.bukkit.generator.structure.Structure;
+import org.bukkit.generator.structure.StructureType;
+import org.bukkit.inventory.ItemType;
+import org.bukkit.inventory.MenuType;
+import org.bukkit.inventory.meta.trim.TrimMaterial;
+import org.bukkit.inventory.meta.trim.TrimPattern;
+import org.bukkit.map.MapCursor;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+import static io.papermc.paper.registry.RegistryKeyImpl.create;
+
@ -136,6 +138,7 @@ index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd2
+ * @param <T> the value type
+ */
+@SuppressWarnings("unused")
+@NullMarked
+public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
+
+ /* ******************* *
@ -171,6 +174,36 @@ index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd2
+ */
+ @ApiStatus.Internal
+ RegistryKey<ItemType> ITEM = create("item");
+ /**
+ * Built-in registry for cat variants.
+ * @see io.papermc.paper.registry.keys.CatVariantKeys
+ */
+ RegistryKey<Cat.Type> CAT_VARIANT = create("cat_variant");
+ /**
+ * Built-in registry for frog variants.
+ * @see io.papermc.paper.registry.keys.FrogVariantKeys
+ */
+ RegistryKey<Frog.Variant> FROG_VARIANT = create("frog_variant");
+ /**
+ * Built-in registry for villager professions.
+ * @see io.papermc.paper.registry.keys.VillagerProfessionKeys
+ */
+ RegistryKey<Villager.Profession> VILLAGER_PROFESSION = create("villager_profession");
+ /**
+ * Built-in registry for villager types.
+ * @see io.papermc.paper.registry.keys.VillagerTypeKeys
+ */
+ RegistryKey<Villager.Type> VILLAGER_TYPE = create("villager_type");
+ /**
+ * Built-in registry for map decoration types.
+ * @see io.papermc.paper.registry.keys.MapDecorationTypeKeys
+ */
+ RegistryKey<MapCursor.Type> MAP_DECORATION_TYPE = create("map_decoration_type");
+ /**
+ * Built-in registry for menu types.
+ * @see io.papermc.paper.registry.keys.MenuTypeKeys
+ */
+ RegistryKey<MenuType> MENU = create("menu");
+
+
+ /* ********************** *
@ -213,9 +246,14 @@ index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd2
+ RegistryKey<Enchantment> ENCHANTMENT = create("enchantment");
+ /**
+ * Data-driven registry for jukebox songs.
+ * @see io.papermc.paper.registry.keys.JukeboxSongKeys
+ */
+ @ApiStatus.Experimental
+ RegistryKey<JukeboxSong> JUKEBOX_SONG = create("jukebox_song");
+ /**
+ * Data-driven registry for banner patterns.
+ * @see io.papermc.paper.registry.keys.BannerPatternKeys
+ */
+ RegistryKey<PatternType> BANNER_PATTERN = create("banner_pattern");
+
+
+ /* ******************* *
@ -223,34 +261,30 @@ index 0000000000000000000000000000000000000000..76daccf4ea502e1747a6f9176dc16fd2
+ * ******************* */
+ RegistryKey<Art> PAINTING_VARIANT = create("painting_variant");
+ RegistryKey<Attribute> ATTRIBUTE = create("attribute");
+ RegistryKey<PatternType> BANNER_PATTERN = create("banner_pattern");
+ RegistryKey<Cat.Type> CAT_VARIANT = create("cat_variant");
+ RegistryKey<EntityType> ENTITY_TYPE = create("entity_type");
+ RegistryKey<Particle> PARTICLE_TYPE = create("particle_type");
+ RegistryKey<PotionType> POTION = create("potion");
+ RegistryKey<Sound> SOUND_EVENT = create("sound_event");
+ RegistryKey<Villager.Profession> VILLAGER_PROFESSION = create("villager_profession");
+ RegistryKey<Villager.Type> VILLAGER_TYPE = create("villager_type");
+ RegistryKey<MemoryKey<?>> MEMORY_MODULE_TYPE = create("memory_module_type");
+ RegistryKey<Fluid> FLUID = create("fluid");
+ RegistryKey<Frog.Variant> FROG_VARIANT = create("frog_variant");
+ RegistryKey<MapCursor.Type> MAP_DECORATION_TYPE = create("map_decoration_type");
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..791813220b2504214b1adecc69093cd600fb0f8c
index 0000000000000000000000000000000000000000..80e3e64f47ac55a4978c9e5b430e2f2d1c871d1b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java
@@ -0,0 +1,24 @@
@@ -0,0 +1,26 @@
+package io.papermc.paper.registry;
+
+import com.google.common.collect.Sets;
+import java.util.Set;
+import net.kyori.adventure.key.Key;
+import org.intellij.lang.annotations.Subst;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+record RegistryKeyImpl<T>(@NotNull Key key) implements RegistryKey<T> {
+@NullMarked
+record RegistryKeyImpl<T>(Key key) implements RegistryKey<T> {
+
+ static final Set<RegistryKey<?>> REGISTRY_KEYS = Sets.newIdentityHashSet();
+
@ -268,16 +302,16 @@ index 0000000000000000000000000000000000000000..791813220b2504214b1adecc69093cd6
+}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a233bf3855e
index 0000000000000000000000000000000000000000..cb2e1a4a6d583787573eeefab24e3188c43d148f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/TypedKey.java
@@ -0,0 +1,44 @@
@@ -0,0 +1,45 @@
+package io.papermc.paper.registry;
+
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.key.Keyed;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents a key for a value in a specific registry.
@ -285,6 +319,7 @@ index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a23
+ * @param <T> the value type for the registry
+ */
+@ApiStatus.Experimental
+@NullMarked
+public sealed interface TypedKey<T> extends Keyed permits TypedKeyImpl {
+
+ /**
@ -293,7 +328,7 @@ index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a23
+ * @return the value's key
+ */
+ @Override
+ @NotNull Key key();
+ Key key();
+
+ /**
+ * Gets the registry key for the value this key
@ -301,7 +336,7 @@ index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a23
+ *
+ * @return the registry key
+ */
+ @NotNull RegistryKey<T> registryKey();
+ RegistryKey<T> registryKey();
+
+ /**
+ * Create a typed key from a key and a registry key.
@ -312,23 +347,23 @@ index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a23
+ * @return a new key for the value key and registry key
+ */
+ @ApiStatus.Experimental
+ static <T> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
+ static <T> TypedKey<T> create(final RegistryKey<T> registryKey, final Key key) {
+ return new TypedKeyImpl<>(key, registryKey);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a97b3359c4ece5c29131da7c3f208aaa8fab66e
index 0000000000000000000000000000000000000000..99375deaa6b90b33cd6a77e0df651236d304874e
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
@@ -0,0 +1,8 @@
+package io.papermc.paper.registry;
+
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.key.Keyed;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+record TypedKeyImpl<T>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
+@NullMarked
+record TypedKeyImpl<T>(Key key, RegistryKey<T> registryKey) implements TypedKey<T> {
+}
diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java
index a86b87e4c3332202e40e484c3f9c6562b419c70f..305532968f9f7dd497c77259ed147ea2f081bc74 100644

View file

@ -8,7 +8,7 @@ Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Yannick Lamprecht <yannicklamprecht@live.de>
diff --git a/build.gradle.kts b/build.gradle.kts
index 2f266350a787a4cfdfda1b0e760bfb7604cac43c..af3514113abdf3f42c41f1e7ff0f930cc1a417f5 100644
index 3383fb91249ea53740326b538abd905f84ff0e3c..74f0e2b812c1e2e922b136fefe505fc8cbe33e83 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -11,12 +11,28 @@ java {
@ -55,7 +55,7 @@ index 2f266350a787a4cfdfda1b0e760bfb7604cac43c..af3514113abdf3f42c41f1e7ff0f930c
// Paper end
compileOnly("org.apache.maven:maven-resolver-provider:3.9.6")
@@ -99,14 +122,31 @@ tasks.withType<Javadoc> {
@@ -100,15 +123,32 @@ tasks.withType<Javadoc> {
"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
@ -64,6 +64,7 @@ index 2f266350a787a4cfdfda1b0e760bfb7604cac43c..af3514113abdf3f42c41f1e7ff0f930c
// 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",
"https://jspecify.dev/docs/api/",
// Paper end
+ // Paper start
+ "https://jd.advntr.dev/api/$adventureVersion/",
@ -90,23 +91,25 @@ index 2f266350a787a4cfdfda1b0e760bfb7604cac43c..af3514113abdf3f42c41f1e7ff0f930c
doLast {
diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af85e287a6
index 0000000000000000000000000000000000000000..1288cdeafe587e9e78e7c5087742ea054ba8423d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/chat/ChatRenderer.java
@@ -0,0 +1,71 @@
@@ -0,0 +1,70 @@
+package io.papermc.paper.chat;
+
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A chat renderer is responsible for rendering chat messages sent by {@link Player}s to the server.
+ */
+@NullMarked
+@FunctionalInterface
+public interface ChatRenderer {
+
+ /**
+ * Renders a chat message. This will be called once for each receiving {@link Audience}.
+ *
@ -117,15 +120,13 @@ index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af
+ * @return a rendered chat message
+ */
+ @ApiStatus.OverrideOnly
+ @NotNull
+ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer);
+ Component render(Player source, Component sourceDisplayName, Component message, Audience viewer);
+
+ /**
+ * Create a new instance of the default {@link ChatRenderer}.
+ *
+ * @return a new {@link ChatRenderer}
+ */
+ @NotNull
+ static ChatRenderer defaultRenderer() {
+ return new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message));
+ }
@ -141,8 +142,7 @@ index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af
+ * @param renderer the viewer unaware renderer
+ * @return a new {@link ChatRenderer}
+ */
+ @NotNull
+ static ChatRenderer viewerUnaware(final @NotNull ViewerUnaware renderer) {
+ static ChatRenderer viewerUnaware(final ViewerUnaware renderer) {
+ return new ViewerUnawareImpl(renderer);
+ }
+
@ -152,6 +152,7 @@ index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af
+ * @see ChatRenderer#viewerUnaware(ViewerUnaware)
+ */
+ interface ViewerUnaware {
+
+ /**
+ * Renders a chat message.
+ *
@ -161,24 +162,26 @@ index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af
+ * @return a rendered chat message
+ */
+ @ApiStatus.OverrideOnly
+ @NotNull
+ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message);
+ Component render(Player source, Component sourceDisplayName, Component message);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ad76b1751ba707f7ae0d283aa1cbaf6c9619da9
index 0000000000000000000000000000000000000000..e1ef23b4bdf60a299d6d37099cef777b3de13ac7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java
@@ -0,0 +1,35 @@
@@ -0,0 +1,38 @@
+package io.papermc.paper.chat;
+
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@ApiStatus.Internal
+@NullMarked
+sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default {
+ private final ViewerUnaware unaware;
+ private @Nullable Component message;
@ -188,12 +191,12 @@ index 0000000000000000000000000000000000000000..2ad76b1751ba707f7ae0d283aa1cbaf6
+ }
+
+ @Override
+ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message, final @NotNull Audience viewer) {
+ public Component render(final Player source, final Component sourceDisplayName, final Component message, final Audience viewer) {
+ return this.render(source, sourceDisplayName, message);
+ }
+
+ @Override
+ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message) {
+ public Component render(final Player source, final Component sourceDisplayName, final Component message) {
+ if (this.message == null) {
+ this.message = this.unaware.render(source, sourceDisplayName, message);
+ }
@ -208,13 +211,14 @@ index 0000000000000000000000000000000000000000..2ad76b1751ba707f7ae0d283aa1cbaf6
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803a7017a28
index 0000000000000000000000000000000000000000..9a95d203151d2c91b0eec494e3674f0facfaa305
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java
@@ -0,0 +1,127 @@
@@ -0,0 +1,122 @@
+package io.papermc.paper.event.player;
+
+import io.papermc.paper.chat.ChatRenderer;
+import java.util.Set;
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.chat.SignedMessage;
+import net.kyori.adventure.text.Component;
@ -222,9 +226,7 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+import org.jspecify.annotations.NullMarked;
+
+import static java.util.Objects.requireNonNull;
+
@ -232,6 +234,7 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ * An abstract implementation of a chat event, handling shared logic.
+ */
+@ApiStatus.NonExtendable
+@NullMarked
+public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable {
+
+ private final Set<Audience> viewers;
@ -242,7 +245,7 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+
+ private boolean cancelled;
+
+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set<Audience> viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage, final @NotNull SignedMessage signedMessage) {
+ AbstractChatEvent(final boolean async, final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
+ super(player, async);
+ this.viewers = viewers;
+ this.renderer = renderer;
@ -259,7 +262,6 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ *
+ * @return a mutable set of {@link Audience audiences} who will receive the chat message
+ */
+ @NotNull
+ public final Set<Audience> viewers() {
+ return this.viewers;
+ }
@ -270,7 +272,7 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ * @param renderer the chat renderer
+ * @throws NullPointerException if {@code renderer} is {@code null}
+ */
+ public final void renderer(final @NotNull ChatRenderer renderer) {
+ public final void renderer(final ChatRenderer renderer) {
+ this.renderer = requireNonNull(renderer, "renderer");
+ }
+
@ -279,7 +281,6 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ *
+ * @return the chat renderer
+ */
+ @NotNull
+ public final ChatRenderer renderer() {
+ return this.renderer;
+ }
@ -290,7 +291,6 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ *
+ * @return the user-supplied message
+ */
+ @NotNull
+ public final Component message() {
+ return this.message;
+ }
@ -301,7 +301,7 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ * @param message the user-supplied message
+ * @throws NullPointerException if {@code message} is {@code null}
+ */
+ public final void message(final @NotNull Component message) {
+ public final void message(final Component message) {
+ this.message = requireNonNull(message, "message");
+ }
+
@ -312,7 +312,6 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ *
+ * @return the original user-supplied message
+ */
+ @NotNull
+ public final Component originalMessage() {
+ return this.originalMessage;
+ }
@ -324,7 +323,6 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+ *
+ * @return the signed message
+ */
+ @NotNull
+ public final SignedMessage signedMessage() {
+ return this.signedMessage;
+ }
@ -341,41 +339,42 @@ index 0000000000000000000000000000000000000000..a0fd845bc9b2540c398fe1dbbf821803
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..01cf89d3558132912c4d0eb48c98cd8c06e46a67
index 0000000000000000000000000000000000000000..ddd4c90f83b5cb8f069ff53760abb3c4adfd1168
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java
@@ -0,0 +1,28 @@
@@ -0,0 +1,29 @@
+package io.papermc.paper.event.player;
+
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@ApiStatus.Experimental
+@NullMarked
+public class AsyncChatCommandDecorateEvent extends AsyncChatDecorateEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @ApiStatus.Internal
+ public AsyncChatCommandDecorateEvent(@Nullable Player player, @NotNull Component originalMessage) {
+ public AsyncChatCommandDecorateEvent(final @Nullable Player player, final Component originalMessage) {
+ super(player, originalMessage);
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static @NotNull HandlerList getHandlerList() {
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb562be2f06
index 0000000000000000000000000000000000000000..9e5ea0cd006bd9744b84923620841f07fa40c2cb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java
@@ -0,0 +1,105 @@
@ -387,9 +386,8 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.server.ServerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * This event is fired when the server decorates a component for chat purposes. This is called
@ -401,18 +399,19 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+ * See {@link AsyncChatCommandDecorateEvent} for the decoration of messages sent via commands
+ */
+@ApiStatus.Experimental
+@NullMarked
+public class AsyncChatDecorateEvent extends ServerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final Player player;
+ private final @Nullable Player player;
+ private final Component originalMessage;
+ private Component result;
+
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public AsyncChatDecorateEvent(final @Nullable Player player, final @NotNull Component originalMessage) {
+ public AsyncChatDecorateEvent(final @Nullable Player player, final Component originalMessage) {
+ super(true);
+ this.player = player;
+ this.originalMessage = originalMessage;
@ -436,7 +435,7 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+ *
+ * @return the input
+ */
+ public @NotNull Component originalMessage() {
+ public Component originalMessage() {
+ return this.originalMessage;
+ }
+
@ -447,7 +446,7 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+ *
+ * @return the result
+ */
+ public @NotNull Component result() {
+ public Component result() {
+ return this.result;
+ }
+
@ -456,7 +455,7 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+ *
+ * @param result the result
+ */
+ public void result(@NotNull Component result) {
+ public void result(final Component result) {
+ this.result = result;
+ }
+
@ -471,36 +470,36 @@ index 0000000000000000000000000000000000000000..2e492f4cd179135bd40ad951ab23acb5
+ * component.
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static @NotNull HandlerList getHandlerList() {
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..4adae8b8a8640ffbd6a86b0908ca21fded737b88
index 0000000000000000000000000000000000000000..50c3e117dec63811823b4e6395bf4f090692ee8c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java
@@ -0,0 +1,45 @@
@@ -0,0 +1,44 @@
+package io.papermc.paper.event.player;
+
+import java.util.Set;
+import io.papermc.paper.chat.ChatRenderer;
+import java.util.Set;
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.chat.SignedMessage;
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * An event fired when a {@link Player} sends a chat message to the server.
@ -515,36 +514,35 @@ index 0000000000000000000000000000000000000000..4adae8b8a8640ffbd6a86b0908ca21fd
+ * Care should be taken to check {@link #isAsynchronous()} and treat the event
+ * appropriately.
+ */
+@NullMarked
+public final class AsyncChatEvent extends AbstractChatEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @ApiStatus.Internal
+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set<Audience> viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage, final @NotNull SignedMessage signedMessage) {
+ public AsyncChatEvent(final boolean async, final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
+ super(async, player, viewers, renderer, message, originalMessage, signedMessage);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7411f58f9f36beaadcc47c2264a4af313956ee03
index 0000000000000000000000000000000000000000..42a82ce2316a4aad2883d24c7e2ff95d95f5881a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java
@@ -0,0 +1,41 @@
@@ -0,0 +1,40 @@
+package io.papermc.paper.event.player;
+
+import java.util.Set;
+import io.papermc.paper.chat.ChatRenderer;
+import java.util.Set;
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.chat.SignedMessage;
+import net.kyori.adventure.text.Component;
@ -552,7 +550,7 @@ index 0000000000000000000000000000000000000000..7411f58f9f36beaadcc47c2264a4af31
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * An event fired when a {@link Player} sends a chat message to the server.
@ -562,34 +560,34 @@ index 0000000000000000000000000000000000000000..7411f58f9f36beaadcc47c2264a4af31
+ */
+@Deprecated
+@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.")
+@NullMarked
+public final class ChatEvent extends AbstractChatEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @ApiStatus.Internal
+ public ChatEvent(final @NotNull Player player, final @NotNull Set<Audience> viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage, final @NotNull SignedMessage signedMessage) {
+ public ChatEvent(final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
+ super(false, player, viewers, renderer, message, originalMessage, signedMessage);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/text/PaperComponents.java b/src/main/java/io/papermc/paper/text/PaperComponents.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b9042d0bb
index 0000000000000000000000000000000000000000..934d1d3ca490a8e25c438bc8c57eb6bde50e0147
--- /dev/null
+++ b/src/main/java/io/papermc/paper/text/PaperComponents.java
@@ -0,0 +1,177 @@
@@ -0,0 +1,180 @@
+package io.papermc.paper.text;
+
+import java.io.IOException;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.flattener.ComponentFlattener;
+import net.kyori.adventure.text.format.NamedTextColor;
@ -600,15 +598,15 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Paper API-specific methods for working with {@link Component}s and related.
+ */
+@NullMarked
+public final class PaperComponents {
+
+ private PaperComponents() {
+ throw new RuntimeException("PaperComponents is not to be instantiated!");
+ }
@ -638,7 +636,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @return the resolved component
+ * @throws IOException if a syntax error tripped during resolving
+ */
+ public static @NotNull Component resolveWithContext(@NotNull Component input, @Nullable CommandSender context, @Nullable Entity scoreboardSubject) throws IOException {
+ public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject) throws IOException {
+ return resolveWithContext(input, context, scoreboardSubject, true);
+ }
+
@ -669,7 +667,8 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @return the resolved component
+ * @throws IOException if a syntax error tripped during resolving
+ */
+ public static @NotNull Component resolveWithContext(@NotNull Component input, @Nullable CommandSender context, @Nullable Entity scoreboardSubject, boolean bypassPermissions) throws IOException {
+ @SuppressWarnings("deprecation") // using unsafe as a bridge
+ public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject, final boolean bypassPermissions) throws IOException {
+ return Bukkit.getUnsafe().resolveWithContext(input, context, scoreboardSubject, bypassPermissions);
+ }
+
@ -678,7 +677,8 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ *
+ * @return a component flattener
+ */
+ public static @NotNull ComponentFlattener flattener() {
+ @SuppressWarnings("deprecation") // using unsafe as a bridge
+ public static ComponentFlattener flattener() {
+ return Bukkit.getUnsafe().componentFlattener();
+ }
+
@ -693,7 +693,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @deprecated will be removed in adventure 5.0.0, use {@link PlainTextComponentSerializer#plainText()}
+ */
+ @Deprecated(forRemoval = true, since = "1.18.1")
+ public static @NotNull PlainComponentSerializer plainSerializer() {
+ public static PlainComponentSerializer plainSerializer() {
+ return Bukkit.getUnsafe().plainComponentSerializer();
+ }
+
@ -708,7 +708,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @deprecated use {@link PlainTextComponentSerializer#plainText()}
+ */
+ @Deprecated(forRemoval = true, since = "1.18.2")
+ public static @NotNull PlainTextComponentSerializer plainTextSerializer() {
+ public static PlainTextComponentSerializer plainTextSerializer() {
+ return Bukkit.getUnsafe().plainTextSerializer();
+ }
+
@ -724,7 +724,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @deprecated use {@link GsonComponentSerializer#gson()}
+ */
+ @Deprecated(forRemoval = true, since = "1.18.2")
+ public static @NotNull GsonComponentSerializer gsonSerializer() {
+ public static GsonComponentSerializer gsonSerializer() {
+ return Bukkit.getUnsafe().gsonComponentSerializer();
+ }
+
@ -741,7 +741,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @deprecated use {@link GsonComponentSerializer#colorDownsamplingGson()}
+ */
+ @Deprecated(forRemoval = true, since = "1.18.2")
+ public static @NotNull GsonComponentSerializer colorDownsamplingGsonSerializer() {
+ public static GsonComponentSerializer colorDownsamplingGsonSerializer() {
+ return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer();
+ }
+
@ -761,7 +761,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b
+ * @deprecated use {@link LegacyComponentSerializer#legacySection()}
+ */
+ @Deprecated(forRemoval = true, since = "1.18.2")
+ public static @NotNull LegacyComponentSerializer legacySectionSerializer() {
+ public static LegacyComponentSerializer legacySectionSerializer() {
+ return Bukkit.getUnsafe().legacyComponentSerializer();
+ }
+}
@ -3343,16 +3343,16 @@ index 133760be6c73436512ba684a3ac77a514b2d8765..9473303bd8ab1f6b63b6999a5f5ff3ec
* Gets how much EXP the Player should have at respawn.
* <p>
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java
index c5734d66686e68080f55034754d43ae55030c3eb..32cd8ee2e849df602a7e10aa5d0a218007faa0ac 100644
index 094963b16eccc303fb1a10b1e052feebe4a4d68b..3e6ac5beb137efd8ecd80e2e9b17015cb38e8a0a 100644
--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java
+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java
@@ -161,6 +161,18 @@ public enum InventoryType {
@@ -163,7 +163,18 @@ public enum InventoryType {
private final String title;
private final MenuType menuType;
private final boolean isCreatable;
+ // Paper start
+ private final net.kyori.adventure.text.Component defaultTitleComponent;
+
+ /**
+ * Gets the inventory's default title.
+ *
@ -3362,18 +3362,18 @@ index c5734d66686e68080f55034754d43ae55030c3eb..32cd8ee2e849df602a7e10aa5d0a2180
+ return defaultTitleComponent;
+ }
+ // Paper end
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) {
this(defaultSize, defaultTitle, true);
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, @Nullable MenuType type) {
this(defaultSize, defaultTitle, type, true);
}
@@ -169,6 +181,7 @@ public enum InventoryType {
size = defaultSize;
@@ -173,6 +184,7 @@ public enum InventoryType {
title = defaultTitle;
this.menuType = type;
this.isCreatable = isCreatable;
+ this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure
}
public int getDefaultSize() {
@@ -176,6 +189,7 @@ public enum InventoryType {
@@ -180,6 +192,7 @@ public enum InventoryType {
}
@NotNull
@ -4327,10 +4327,10 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..72ebc29db42d08d1d0361dba462fc8a5
/**
diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java
index 5b479ff2abe8cdd5e889803c73a713bc9855bc0b..5954dff2134654bb0ccc3b4c3b51a8e1ca77f6c9 100644
index 278259e211b926283ee6dfef6f96e11ddbcbf275..ebc14022c9ef9b0b3331ee53e96a32667e4762e0 100644
--- a/src/main/java/org/bukkit/inventory/InventoryView.java
+++ b/src/main/java/org/bukkit/inventory/InventoryView.java
@@ -267,12 +267,26 @@ public interface InventoryView {
@@ -269,12 +269,26 @@ public interface InventoryView {
*/
public boolean setProperty(@NotNull Property prop, int value);
@ -4421,6 +4421,56 @@ index eade62328895133c026e7e678e648e1fc846f5ee..730c42eddd38acec1cdbb19dfc8c6757
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/inventory/MenuType.java b/src/main/java/org/bukkit/inventory/MenuType.java
index ee39bf9019fa0377beb895a22db0b2a0934a4d84..29dfad691cbdd09d043f6171defc8a7fabbc2b75 100644
--- a/src/main/java/org/bukkit/inventory/MenuType.java
+++ b/src/main/java/org/bukkit/inventory/MenuType.java
@@ -146,11 +146,45 @@ public interface MenuType extends Keyed {
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
+ * @deprecated Use {@link #create(HumanEntity, net.kyori.adventure.text.Component)} instead.
*/
@NotNull
+ @Deprecated(since = "1.21") // Paper - adventure
V create(@NotNull HumanEntity player, @NotNull String title);
+
+ // Paper start - adventure
+ /**
+ * Creates a view of the specified menu type.
+ * <p>
+ * The player provided to create this view must be the player the view
+ * is opened for. See {@link HumanEntity#openInventory(InventoryView)}
+ * for more information.
+ *
+ * @param player the player the view belongs to
+ * @param title the title of the view
+ * @return the created {@link InventoryView}
+ */
+ @NotNull
+ V create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
+ // Paper end - adventure
}
+ // Paper start - adventure
+ /**
+ * Creates a view of the specified menu type.
+ * <p>
+ * The player provided to create this view must be the player the view
+ * is opened for. See {@link HumanEntity#openInventory(InventoryView)}
+ * for more information.
+ *
+ * @param player the player the view belongs to
+ * @param title the title of the view
+ * @return the created {@link InventoryView}
+ */
+ @NotNull
+ InventoryView create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
+ // Paper end - adventure
+
/**
* Yields this MenuType as a typed version of itself with a plain
* {@link InventoryView} representing it.
diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java
index 9bab73c3c2ca759b8e1c7d07d98cc593c961666a..f0c6943da3f783101ca647b75b3230fae3a310da 100644
--- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java

View file

@ -6,22 +6,25 @@ Subject: [PATCH] Paper Utils
diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java
new file mode 100644
index 0000000000000000000000000000000000000000..9db0056ab94145819628b3ad8d8d26130d117fcf
index 0000000000000000000000000000000000000000..fbcd82b513b4cb9839f9d2b38d9c6c73148e30a6
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java
@@ -0,0 +1,16 @@
@@ -0,0 +1,19 @@
+package com.destroystokyo.paper.util;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+public class SneakyThrow {
+@ApiStatus.Internal
+@NullMarked
+public final class SneakyThrow {
+
+ public static void sneaky(@NotNull Throwable exception) {
+ SneakyThrow.<RuntimeException>throwSneaky(exception);
+ public static void sneaky(final Throwable exception) {
+ SneakyThrow.throwSneaky(exception);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void throwSneaky(@NotNull Throwable exception) throws T {
+ private static <T extends Throwable> void throwSneaky(final Throwable exception) throws T {
+ throw (T) exception;
+ }
+

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Use ASM for event executors.
Uses method handles for private or static methods.
diff --git a/build.gradle.kts b/build.gradle.kts
index af3514113abdf3f42c41f1e7ff0f930cc1a417f5..ed0b67ac322aa22b191cd35502ae5b4f20af19f8 100644
index 74f0e2b812c1e2e922b136fefe505fc8cbe33e83..1f627e81622e77b81b1228a467fbb9e6fd979e7a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -47,6 +47,9 @@ dependencies {
@ -21,127 +21,138 @@ index af3514113abdf3f42c41f1e7ff0f930cc1a417f5..ed0b67ac322aa22b191cd35502ae5b4f
compileOnly("org.apache.maven:maven-resolver-provider:3.9.6")
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994
index 0000000000000000000000000000000000000000..5a702481d28d90cb503faad0d9b9c3231bbff940
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
@@ -0,0 +1,42 @@
@@ -0,0 +1,46 @@
+package com.destroystokyo.paper.event.executor;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+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;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@ApiStatus.Internal
+@NullMarked
+public class MethodHandleEventExecutor implements EventExecutor {
+
+ private final Class<? extends Event> eventClass;
+ private final MethodHandle handle;
+
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
+ public MethodHandleEventExecutor(final Class<? extends Event> eventClass, final MethodHandle handle) {
+ this.eventClass = eventClass;
+ this.handle = handle;
+ }
+
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
+ public MethodHandleEventExecutor(final Class<? extends Event> eventClass, final Method m) {
+ this.eventClass = eventClass;
+ try {
+ m.setAccessible(true);
+ this.handle = MethodHandles.lookup().unreflect(m);
+ } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
+ throw new AssertionError("Unable to set accessible", e);
+ }
+ }
+
+ @Override
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
+ if (!eventClass.isInstance(event)) return;
+ public void execute(final Listener listener, final Event event) throws EventException {
+ if (!this.eventClass.isInstance(event)) return;
+ try {
+ handle.invoke(listener, event);
+ } catch (Throwable t) {
+ this.handle.invoke(listener, event);
+ } catch (final Throwable t) {
+ SneakyThrow.sneaky(t);
+ }
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..827f2b27f70a7ec0bc11d039305c3e58c02a4ef4
index 0000000000000000000000000000000000000000..bbdb5b472df116b71c459bdc6cc4b74267ea0f5e
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
@@ -0,0 +1,42 @@
@@ -0,0 +1,44 @@
+package com.destroystokyo.paper.event.executor;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+import com.google.common.base.Preconditions;
+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.event.Event;
+import org.bukkit.event.EventException;
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.EventExecutor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+@ApiStatus.Internal
+@NullMarked
+public class StaticMethodHandleEventExecutor implements EventExecutor {
+
+ private final Class<? extends Event> eventClass;
+ private final MethodHandle handle;
+
+ public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
+ public StaticMethodHandleEventExecutor(final Class<? extends Event> eventClass, final 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) {
+ } catch (final IllegalAccessException e) {
+ throw new AssertionError("Unable to set accessible", e);
+ }
+ }
+
+ @Override
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
+ if (!eventClass.isInstance(event)) return;
+ public void execute(final Listener listener, final Event event) throws EventException {
+ if (!this.eventClass.isInstance(event)) return;
+ try {
+ handle.invoke(event);
+ } catch (Throwable throwable) {
+ this.handle.invoke(event);
+ } catch (final Throwable throwable) {
+ SneakyThrow.sneaky(throwable);
+ }
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..084c31af1a7ba32bb4c3dc8f16f67fd09ce0b6a4
index 0000000000000000000000000000000000000000..abfcb6e8383ff311940d82afe4ff990649a082dc
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
@@ -0,0 +1,54 @@
@@ -0,0 +1,59 @@
+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.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+
+import static org.objectweb.asm.Opcodes.*;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.V1_8;
+
+public class ASMEventExecutorGenerator {
+@ApiStatus.Internal
+@NullMarked
+public final 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)});
+ public static byte[] generateEventExecutor(final Method m, final String name) {
+ final 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();
@ -169,22 +180,25 @@ index 0000000000000000000000000000000000000000..084c31af1a7ba32bb4c3dc8f16f67fd0
+ }
+
+ public static AtomicInteger NEXT_ID = new AtomicInteger(1);
+ @NotNull
+
+ public static String generateName() {
+ int id = NEXT_ID.getAndIncrement();
+ final int id = NEXT_ID.getAndIncrement();
+ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
new file mode 100644
index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4
index 0000000000000000000000000000000000000000..581561fbd32c81ab1774ba8f0b7f3cec9392d99a
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
@@ -0,0 +1,34 @@
@@ -0,0 +1,35 @@
+package com.destroystokyo.paper.event.executor.asm;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+@ApiStatus.Internal
+@NullMarked
+public interface ClassDefiner {
+
+ /**
@ -192,7 +206,7 @@ index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7
+ *
+ * @return if classes bypass access checks
+ */
+ public default boolean isBypassAccessChecks() {
+ default boolean isBypassAccessChecks() {
+ return false;
+ }
+
@ -206,79 +220,79 @@ index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7
+ * @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);
+ Class<?> defineClass(ClassLoader parentLoader, String name, byte[] data);
+
+ @NotNull
+ public static ClassDefiner getInstance() {
+ static ClassDefiner getInstance() {
+ return SafeClassDefiner.INSTANCE;
+ }
+
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
new file mode 100644
index 0000000000000000000000000000000000000000..abcc966d8ee01d73c1d1480237ab46fa0ab55fdc
index 0000000000000000000000000000000000000000..48bcc72293c2a31b6e2dd2dcd6a79d618c72a137
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
@@ -0,0 +1,64 @@
@@ -0,0 +1,66 @@
+package com.destroystokyo.paper.event.executor.asm;
+
+import java.util.concurrent.ConcurrentMap;
+
+import com.google.common.base.Preconditions;
+
+import com.google.common.collect.MapMaker;
+import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.ConcurrentMap;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+@ApiStatus.Internal
+@NullMarked
+public class SafeClassDefiner implements ClassDefiner {
+
+ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
+
+ private 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);
+ public Class<?> defineClass(final ClassLoader parentLoader, final String name, final byte[] data) {
+ final GeneratedClassLoader loader = this.loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
+ synchronized (loader.getClassLoadingLock(name)) {
+ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
+ Class<?> c = loader.define(name, data);
+ final 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) {
+ protected GeneratedClassLoader(final 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);
+ private Class<?> define(final String name, final byte[] data) {
+ synchronized (this.getClassLoadingLock(name)) {
+ assert !this.hasClass(name);
+ final Class<?> c = this.defineClass(name, data, 0, data.length);
+ this.resolveClass(c);
+ return c;
+ }
+ }
+
+ @Override
+ @NotNull
+ public Object getClassLoadingLock(@NotNull String name) {
+ public Object getClassLoadingLock(final String name) {
+ return super.getClassLoadingLock(name);
+ }
+
+ public boolean hasClass(@NotNull String name) {
+ synchronized (getClassLoadingLock(name)) {
+ public boolean hasClass(final String name) {
+ synchronized (this.getClassLoadingLock(name)) {
+ try {
+ Class.forName(name);
+ return true;
+ } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
+ return false;
+ }
+ }

View file

@ -5,7 +5,7 @@ Subject: [PATCH] Paper Plugins
diff --git a/build.gradle.kts b/build.gradle.kts
index ed0b67ac322aa22b191cd35502ae5b4f20af19f8..258d7010d24c529c9bbc76cc26adf226c641ee58 100644
index 1f627e81622e77b81b1228a467fbb9e6fd979e7a..3c50362de25617d878ef58f14f67c240005ff624 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -52,7 +52,7 @@ dependencies {
@ -17,7 +17,7 @@ index ed0b67ac322aa22b191cd35502ae5b4f20af19f8..258d7010d24c529c9bbc76cc26adf226
compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18")
@@ -139,6 +139,7 @@ tasks.withType<Javadoc> {
@@ -141,6 +141,7 @@ tasks.withType<Javadoc> {
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
// Paper end
@ -27,26 +27,26 @@ index ed0b67ac322aa22b191cd35502ae5b4f20af19f8..258d7010d24c529c9bbc76cc26adf226
diff --git a/src/main/java/io/papermc/paper/plugin/PermissionManager.java b/src/main/java/io/papermc/paper/plugin/PermissionManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c27846933
index 0000000000000000000000000000000000000000..c78ada48e27c5552529fe8d5bc23db1dac94e481
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/PermissionManager.java
@@ -0,0 +1,171 @@
@@ -0,0 +1,166 @@
+package io.papermc.paper.plugin;
+
+import org.bukkit.permissions.Permissible;
+import org.bukkit.permissions.Permission;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Set;
+import org.bukkit.permissions.Permissible;
+import org.bukkit.permissions.Permission;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * A permission manager implementation to keep backwards compatibility partially alive with existing plugins that used
+ * the bukkit one before.
+ */
+@ApiStatus.Experimental
+@NullMarked
+public interface PermissionManager {
+
+ /**
@ -55,8 +55,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param name Name of the permission
+ * @return Permission, or null if none
+ */
+ @Nullable
+ Permission getPermission(@NotNull String name);
+ @Nullable Permission getPermission(String name);
+
+ /**
+ * Adds a {@link Permission} to this plugin manager.
@ -68,7 +67,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @throws IllegalArgumentException Thrown when a permission with the same
+ * name already exists
+ */
+ void addPermission(@NotNull Permission perm);
+ void addPermission(Permission perm);
+
+ /**
+ * Removes a {@link Permission} registration from this plugin manager.
@ -81,7 +80,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ *
+ * @param perm Permission to remove
+ */
+ void removePermission(@NotNull Permission perm);
+ void removePermission(Permission perm);
+
+ /**
+ * Removes a {@link Permission} registration from this plugin manager.
@ -94,7 +93,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ *
+ * @param name Permission to remove
+ */
+ void removePermission(@NotNull String name);
+ void removePermission(String name);
+
+ /**
+ * Gets the default permissions for the given op status
@ -102,7 +101,6 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param op Which set of default permissions to get
+ * @return The default permissions
+ */
+ @NotNull
+ Set<Permission> getDefaultPermissions(boolean op);
+
+ /**
@ -113,7 +111,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ *
+ * @param perm Permission to recalculate
+ */
+ void recalculatePermissionDefaults(@NotNull Permission perm);
+ void recalculatePermissionDefaults(Permission perm);
+
+ /**
+ * Subscribes the given Permissible for information about the requested
@ -125,7 +123,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param permission Permission to subscribe to
+ * @param permissible Permissible subscribing
+ */
+ void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible);
+ void subscribeToPermission(String permission, Permissible permissible);
+
+ /**
+ * Unsubscribes the given Permissible for information about the requested
@ -134,7 +132,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param permission Permission to unsubscribe from
+ * @param permissible Permissible subscribing
+ */
+ void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible);
+ void unsubscribeFromPermission(String permission, Permissible permissible);
+
+ /**
+ * Gets a set containing all subscribed {@link Permissible}s to the given
@ -143,8 +141,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param permission Permission to query for
+ * @return Set containing all subscribed permissions
+ */
+ @NotNull
+ Set<Permissible> getPermissionSubscriptions(@NotNull String permission);
+ Set<Permissible> getPermissionSubscriptions(String permission);
+
+ /**
+ * Subscribes to the given Default permissions by operator status
@ -155,7 +152,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param op Default list to subscribe to
+ * @param permissible Permissible subscribing
+ */
+ void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible);
+ void subscribeToDefaultPerms(boolean op, Permissible permissible);
+
+ /**
+ * Unsubscribes from the given Default permissions by operator status
@ -163,7 +160,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param op Default list to unsubscribe from
+ * @param permissible Permissible subscribing
+ */
+ void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible);
+ void unsubscribeFromDefaultPerms(boolean op, Permissible permissible);
+
+ /**
+ * Gets a set containing all subscribed {@link Permissible}s to the given
@ -172,7 +169,6 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ * @param op Default list to query for
+ * @return Set containing all subscribed permissions
+ */
+ @NotNull
+ Set<Permissible> getDefaultPermSubscriptions(boolean op);
+
+ /**
@ -182,7 +178,6 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ *
+ * @return Set containing all current registered permissions
+ */
+ @NotNull
+ Set<Permission> getPermissions();
+
+ /**
@ -192,7 +187,7 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+ *
+ * @param perm permission
+ */
+ void addPermissions(@NotNull List<Permission> perm);
+ void addPermissions(List<Permission> perm);
+
+ /**
+ * Clears the current registered permissinos.
@ -204,27 +199,29 @@ index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c
+}
diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..08f2050356acaf74e3210416760e3873c2dafd2c
index 0000000000000000000000000000000000000000..4c47414fc08e1183b1e59369bacc4d7f7042f262
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java
@@ -0,0 +1,14 @@
@@ -0,0 +1,16 @@
+package io.papermc.paper.plugin.bootstrap;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin
+ * instantiation logic.
+ * A boostrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances
+ * A bootstrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances
+ * like the plugin's configuration or logger during the plugins bootstrap.
+ */
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface BootstrapContext extends PluginProviderContext {
+}
diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java
new file mode 100644
index 0000000000000000000000000000000000000000..288c078da3d3ca78d02caa4e3565ac7cf89f9f9f
index 0000000000000000000000000000000000000000..e6696dcd8049e869bd1733f7c67ff802c54d7c37
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java
@@ -0,0 +1,41 @@
@ -233,10 +230,10 @@ index 0000000000000000000000000000000000000000..288c078da3d3ca78d02caa4e3565ac7c
+import io.papermc.paper.plugin.provider.util.ProviderUtil;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A plugin boostrap is meant for loading certain parts of the plugin before the server is loaded.
+ * A plugin bootstrap is meant for loading certain parts of the plugin before the server is loaded.
+ * <p>
+ * Plugin bootstrapping allows values to be initialized in certain parts of the server that might not be allowed
+ * when the server is running.
@ -245,8 +242,9 @@ index 0000000000000000000000000000000000000000..288c078da3d3ca78d02caa4e3565ac7c
+ * <p>
+ * <b>All calls to Bukkit may throw a NullPointerExceptions or return null unexpectedly. You should only call api methods that are explicitly documented to work in the bootstrapper</b>
+ */
+@ApiStatus.OverrideOnly
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.OverrideOnly
+public interface PluginBootstrap {
+
+ /**
@ -254,7 +252,7 @@ index 0000000000000000000000000000000000000000..288c078da3d3ca78d02caa4e3565ac7c
+ *
+ * @param context the server provided context
+ */
+ void bootstrap(@NotNull BootstrapContext context);
+ void bootstrap(BootstrapContext context);
+
+ /**
+ * Called by the server to instantiate your main class.
@ -264,34 +262,33 @@ index 0000000000000000000000000000000000000000..288c078da3d3ca78d02caa4e3565ac7c
+ * @param context the server created bootstrap object
+ * @return the server requested instance of the plugins main class.
+ */
+ @NotNull
+ default JavaPlugin createPlugin(@NotNull PluginProviderContext context) {
+ default JavaPlugin createPlugin(final PluginProviderContext context) {
+ return ProviderUtil.loadClass(context.getConfiguration().getMainClass(), JavaPlugin.class, this.getClass().getClassLoader());
+ }
+}
diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c14693155de3654d5ca011c63e13e4a1abf2080
index 0000000000000000000000000000000000000000..19bb302ab264b72306d9bd15e9c40ade6dde7ee7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java
@@ -0,0 +1,52 @@
@@ -0,0 +1,48 @@
+package io.papermc.paper.plugin.bootstrap;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import java.nio.file.Path;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.nio.file.Path;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin
+ * instantiation logic.
+ * A boostrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances
+ * A bootstrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances
+ * like the plugin's configuration or logger during the plugins bootstrap.
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface PluginProviderContext {
+
+ /**
@ -299,7 +296,6 @@ index 0000000000000000000000000000000000000000..2c14693155de3654d5ca011c63e13e4a
+ *
+ * @return the plugin's configuration
+ */
+ @NotNull
+ PluginMeta getConfiguration();
+
+ /**
@ -307,7 +303,6 @@ index 0000000000000000000000000000000000000000..2c14693155de3654d5ca011c63e13e4a
+ *
+ * @return the previously described path
+ */
+ @NotNull
+ Path getDataDirectory();
+
+ /**
@ -315,7 +310,6 @@ index 0000000000000000000000000000000000000000..2c14693155de3654d5ca011c63e13e4a
+ *
+ * @return the logger instance
+ */
+ @NotNull
+ ComponentLogger getLogger();
+
+ /**
@ -323,33 +317,32 @@ index 0000000000000000000000000000000000000000..2c14693155de3654d5ca011c63e13e4a
+ *
+ * @return the previously described path
+ */
+ @NotNull
+ Path getPluginSource();
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9ada2e585f
index 0000000000000000000000000000000000000000..3c768d5ccf490e962d9638e92d4ea7c85670bad8
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java
@@ -0,0 +1,203 @@
@@ -0,0 +1,186 @@
+package io.papermc.paper.plugin.configuration;
+
+import java.util.List;
+import org.bukkit.permissions.Permission;
+import org.bukkit.permissions.PermissionDefault;
+import org.bukkit.plugin.PluginLoadOrder;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * This class acts as an abstraction for a plugin configuration.
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental // Subject to change!
+@NullMarked
+@ApiStatus.NonExtendable
+public interface PluginMeta {
+
+ /**
@ -369,7 +362,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return the name of the plugin
+ */
+ @NotNull
+ String getName();
+
+ /**
@ -377,7 +369,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return a descriptive name of the plugin and respective version
+ */
+ @NotNull
+ default String getDisplayName() {
+ return this.getName() + " v" + this.getVersion();
+ }
@ -388,7 +379,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return the fully qualified class name of the plugin's main class.
+ */
+ @NotNull
+ String getMainClass();
+
+ /**
@ -397,7 +387,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ * @return the plugin load order
+ * @see PluginLoadOrder for further details regards the available load orders.
+ */
+ @NotNull
+ PluginLoadOrder getLoadOrder();
+
+ /**
@ -407,7 +396,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return the string representation of the plugin's version
+ */
+ @NotNull
+ String getVersion();
+
+ /**
@ -418,8 +406,7 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ * @return the specific overwrite of the logger prefix as defined by the plugin. If the plugin did not define a
+ * custom logger prefix, this method will return null
+ */
+ @Nullable
+ String getLoggerPrefix();
+ @Nullable String getLoggerPrefix();
+
+ /**
+ * Provides a list of dependencies that are required for this plugin to load.
@ -430,7 +417,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return an immutable list of required dependency names
+ */
+ @NotNull
+ List<String> getPluginDependencies();
+
+ /**
@ -443,7 +429,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return immutable list of soft dependencies
+ */
+ @NotNull
+ List<String> getPluginSoftDependencies();
+
+ /**
@ -456,7 +441,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return immutable list of plugins to load before this plugin
+ */
+ @NotNull
+ List<String> getLoadBeforePlugins();
+
+ /**
@ -466,7 +450,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return immutable list of provided plugins/dependencies
+ */
+ @NotNull
+ List<String> getProvidedPlugins();
+
+ /**
@ -475,7 +458,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return an immutable list of the plugin's authors
+ */
+ @NotNull
+ List<String> getAuthors();
+
+ /**
@ -484,7 +466,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return an immutable list of the plugin's contributors
+ */
+ @NotNull
+ List<String> getContributors();
+
+ /**
@ -493,8 +474,7 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return description or null if the plugin did not define a human readable description.
+ */
+ @Nullable
+ String getDescription();
+ @Nullable String getDescription();
+
+ /**
+ * Provides the website for the plugin or the plugin's author.
@ -502,8 +482,7 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ *
+ * @return a string representation of the website that serves as the main hub for this plugin/its author.
+ */
+ @Nullable
+ String getWebsite();
+ @Nullable String getWebsite();
+
+ /**
+ * Provides the list of permissions that are defined via the plugin meta instance.
@ -511,7 +490,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ * @return an immutable list of permissions
+ */
+ // TODO: Do we even want this? Why not just use the bootstrapper
+ @NotNull
+ List<Permission> getPermissions();
+
+ /**
@ -521,7 +499,6 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ * @see #getPermissions()
+ */
+ // TODO: Do we even want this? Why not just use the bootstrapper
+ @NotNull
+ PermissionDefault getPermissionDefault();
+
+ /**
@ -532,8 +509,7 @@ index 0000000000000000000000000000000000000000..bcf91d048d84144f6acf9bfd2095df9a
+ * @return the version string made up of the major and minor version (e.g. 1.18 or 1.19). Minor versions like 1.18.2
+ * are unified to their major release version (in this example 1.18)
+ */
+ @Nullable
+ String getAPIVersion();
+ @Nullable String getAPIVersion();
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/configuration/package-info.java b/src/main/java/io/papermc/paper/plugin/configuration/package-info.java
@ -552,10 +528,10 @@ index 0000000000000000000000000000000000000000..ddb3076124365d0d1a5caa32d4dcb1f4
+package io.papermc.paper.plugin.configuration;
diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..28cbc09b7c1ded1f4515969cef4a669adac85703
index 0000000000000000000000000000000000000000..ddb768057cdfd9202e4386494fd5f643692c73a1
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java
@@ -0,0 +1,38 @@
@@ -0,0 +1,37 @@
+package io.papermc.paper.plugin.loader;
+
+import io.papermc.paper.plugin.bootstrap.PluginProviderContext;
@ -563,14 +539,15 @@ index 0000000000000000000000000000000000000000..28cbc09b7c1ded1f4515969cef4a669a
+import io.papermc.paper.plugin.loader.library.LibraryStore;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A mutable builder that may be used to collect and register all {@link ClassPathLibrary} instances a
+ * {@link PluginLoader} aims to provide to its plugin at runtime.
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface PluginClasspathBuilder {
+
+ /**
@ -587,23 +564,21 @@ index 0000000000000000000000000000000000000000..28cbc09b7c1ded1f4515969cef4a669a
+ * @see io.papermc.paper.plugin.loader.library.impl.JarLibrary
+ * @see io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver
+ */
+ @NotNull
+ @Contract("_ -> this")
+ PluginClasspathBuilder addLibrary(@NotNull ClassPathLibrary classPathLibrary);
+ PluginClasspathBuilder addLibrary(ClassPathLibrary classPathLibrary);
+
+ @NotNull
+ PluginProviderContext getContext();
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9e31f78ff6ff969436c6d99755845786c4d383f
index 0000000000000000000000000000000000000000..c2d029e4474cc00c84e5b3f7fceec4c3f30b486b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java
@@ -0,0 +1,30 @@
@@ -0,0 +1,31 @@
+package io.papermc.paper.plugin.loader;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A plugin loader is responsible for creating certain aspects of a plugin before it is created.
@ -615,8 +590,9 @@ index 0000000000000000000000000000000000000000..c9e31f78ff6ff969436c6d9975584578
+ * It should be noted that this class will be called from a different classloader, this will cause any static values
+ * set in this class/any other classes loaded not to persist when the plugin loads.
+ */
+@ApiStatus.OverrideOnly
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.OverrideOnly
+public interface PluginLoader {
+
+ /**
@ -627,23 +603,24 @@ index 0000000000000000000000000000000000000000..c9e31f78ff6ff969436c6d9975584578
+ * @param classpathBuilder a mutable classpath builder that may be used to register custom runtime dependencies
+ * for the plugin the loader was registered for.
+ */
+ void classloader(@NotNull PluginClasspathBuilder classpathBuilder);
+ void classloader(PluginClasspathBuilder classpathBuilder);
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java
new file mode 100644
index 0000000000000000000000000000000000000000..1347b535d90c2c281c184d0459e7ac59c0350c9f
index 0000000000000000000000000000000000000000..8a07333a592056bab1d26d811316bb5ea5f30e18
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java
@@ -0,0 +1,20 @@
@@ -0,0 +1,21 @@
+package io.papermc.paper.plugin.loader.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * The classpath library interface represents libraries that are capable of registering themselves via
+ * {@link #register(LibraryStore)} on any given {@link LibraryStore}.
+ */
+@NullMarked
+public interface ClassPathLibrary {
+
+ /**
@ -654,7 +631,7 @@ index 0000000000000000000000000000000000000000..1347b535d90c2c281c184d0459e7ac59
+ * @param store the library store instance to register this library into
+ * @throws LibraryLoadingException if library loading failed for this classpath library
+ */
+ void register(@NotNull LibraryStore store) throws LibraryLoadingException;
+ void register(LibraryStore store) throws LibraryLoadingException;
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java
new file mode 100644
@ -679,16 +656,15 @@ index 0000000000000000000000000000000000000000..79ba423a364b50588f3ee87fdc69155c
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..0546fa1e9dcd7155086a8650806a8c086b6fc458
index 0000000000000000000000000000000000000000..93ef8e369a158c25bc4fdd553faf13c1826ad872
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java
@@ -0,0 +1,26 @@
+package io.papermc.paper.plugin.loader.library;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.nio.file.Path;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents a storage that stores library jars.
@ -699,6 +675,7 @@ index 0000000000000000000000000000000000000000..0546fa1e9dcd7155086a8650806a8c08
+ * @see io.papermc.paper.plugin.loader.PluginLoader
+ */
+@ApiStatus.Internal
+@NullMarked
+public interface LibraryStore {
+
+ /**
@ -706,12 +683,12 @@ index 0000000000000000000000000000000000000000..0546fa1e9dcd7155086a8650806a8c08
+ *
+ * @param library path to the libraries jar file on the disk
+ */
+ void addLibrary(@NotNull Path library);
+ void addLibrary(Path library);
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3da0d67cab01e1233dccde1a12ff25961ee79fb
index 0000000000000000000000000000000000000000..9efcd9a62d6439eb27fc4e08498b4b7fbbdecb3c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java
@@ -0,0 +1,45 @@
@ -720,10 +697,9 @@ index 0000000000000000000000000000000000000000..e3da0d67cab01e1233dccde1a12ff259
+import io.papermc.paper.plugin.loader.library.ClassPathLibrary;
+import io.papermc.paper.plugin.loader.library.LibraryLoadingException;
+import io.papermc.paper.plugin.loader.library.LibraryStore;
+import org.jetbrains.annotations.NotNull;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A simple jar library implementation of the {@link ClassPathLibrary} that allows {@link io.papermc.paper.plugin.loader.PluginLoader}s to
@ -738,6 +714,7 @@ index 0000000000000000000000000000000000000000..e3da0d67cab01e1233dccde1a12ff259
+ * <p>
+ * The jar library implementation will error if the file does not exist at the specified path.
+ */
+@NullMarked
+public class JarLibrary implements ClassPathLibrary {
+
+ private final Path path;
@ -747,12 +724,12 @@ index 0000000000000000000000000000000000000000..e3da0d67cab01e1233dccde1a12ff259
+ *
+ * @param path the path, relative to the JVMs start directory.
+ */
+ public JarLibrary(@NotNull Path path) {
+ public JarLibrary(final Path path) {
+ this.path = path;
+ }
+
+ @Override
+ public void register(@NotNull LibraryStore store) throws LibraryLoadingException {
+ public void register(final LibraryStore store) throws LibraryLoadingException {
+ if (Files.notExists(this.path)) {
+ throw new LibraryLoadingException("Could not find library at " + this.path);
+ }
@ -762,7 +739,7 @@ index 0000000000000000000000000000000000000000..e3da0d67cab01e1233dccde1a12ff259
+}
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19a94791ab
index 0000000000000000000000000000000000000000..107705db2d82b7c191e5e625ec888e0bc3b03831
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
@@ -0,0 +1,133 @@
@ -771,6 +748,9 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+import io.papermc.paper.plugin.loader.library.ClassPathLibrary;
+import io.papermc.paper.plugin.loader.library.LibraryLoadingException;
+import io.papermc.paper.plugin.loader.library.LibraryStore;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
@ -791,14 +771,10 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+import org.eclipse.aether.transfer.TransferCancelledException;
+import org.eclipse.aether.transfer.TransferEvent;
+import org.eclipse.aether.transport.http.HttpTransporterFactory;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The maven library resolver acts as a resolver for yet to be resolved jar libraries that may be pulled from a
+ * remote maven repository.
@ -813,12 +789,13 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ * "central", "default", "https://repo1.maven.org/maven2/"
+ * ).build());
+ * }</pre>
+ *
+ * <p>
+ * Plugins may create and register a {@link MavenLibraryResolver} after configuring it.
+ */
+@NullMarked
+public class MavenLibraryResolver implements ClassPathLibrary {
+
+ private static final Logger logger = LoggerFactory.getLogger("MavenLibraryResolver");
+ private static final Logger LOGGER = LoggerFactory.getLogger("MavenLibraryResolver");
+
+ private final RepositorySystem repository;
+ private final DefaultRepositorySystemSession session;
@ -834,7 +811,7 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ * submitting the {@link MavenLibraryResolver} to the {@link io.papermc.paper.plugin.loader.PluginClasspathBuilder}.
+ */
+ public MavenLibraryResolver() {
+ DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
+ final DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
+ locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
+ locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
+
@ -846,8 +823,8 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ this.session.setLocalRepositoryManager(this.repository.newLocalRepositoryManager(this.session, new LocalRepository("libraries")));
+ this.session.setTransferListener(new AbstractTransferListener() {
+ @Override
+ public void transferInitiated(@NotNull TransferEvent event) throws TransferCancelledException {
+ logger.info("Downloading {}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName());
+ public void transferInitiated(final TransferEvent event) throws TransferCancelledException {
+ LOGGER.info("Downloading {}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName());
+ }
+ });
+ this.session.setReadOnly();
@ -860,7 +837,7 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ * @param dependency the definition of the dependency the maven library resolver should resolve when running
+ * @see MavenLibraryResolver#addRepository(RemoteRepository)
+ */
+ public void addDependency(@NotNull Dependency dependency) {
+ public void addDependency(final Dependency dependency) {
+ this.dependencies.add(dependency);
+ }
+
@ -870,9 +847,9 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ * repository.
+ *
+ * @param remoteRepository the configuration that defines the maven repository this library resolver should fetch
+ * dependencies from
+ * dependencies from
+ */
+ public void addRepository(@NotNull RemoteRepository remoteRepository) {
+ public void addRepository(final RemoteRepository remoteRepository) {
+ this.repositories.add(remoteRepository);
+ }
+
@ -883,32 +860,32 @@ index 0000000000000000000000000000000000000000..70f352630de71f575d1aea5a3126da19
+ * @throws LibraryLoadingException if resolving a dependency failed
+ */
+ @Override
+ public void register(@NotNull LibraryStore store) throws LibraryLoadingException {
+ List<RemoteRepository> repos = this.repository.newResolutionRepositories(this.session, this.repositories);
+ public void register(final LibraryStore store) throws LibraryLoadingException {
+ final List<RemoteRepository> repos = this.repository.newResolutionRepositories(this.session, this.repositories);
+
+ DependencyResult result;
+ final DependencyResult result;
+ try {
+ result = this.repository.resolveDependencies(this.session, new DependencyRequest(new CollectRequest((Dependency) null, this.dependencies, repos), null));
+ } catch (DependencyResolutionException ex) {
+ } catch (final DependencyResolutionException ex) {
+ throw new LibraryLoadingException("Error resolving libraries", ex);
+ }
+
+ for (ArtifactResult artifact : result.getArtifactResults()) {
+ File file = artifact.getArtifact().getFile();
+ for (final ArtifactResult artifact : result.getArtifactResults()) {
+ final File file = artifact.getArtifact().getFile();
+ store.addLibrary(file.toPath());
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..64e46fdfa4d404cb08c67a456e5990b729296b98
index 0000000000000000000000000000000000000000..75fe408ec742319c3cba2461b33b2a6e8b22d231
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java
@@ -0,0 +1,34 @@
@@ -0,0 +1,35 @@
+package io.papermc.paper.plugin.provider.classloader;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * The class loader access interface is an <b>internal</b> representation of a class accesses' ability to see types
@ -919,6 +896,7 @@ index 0000000000000000000000000000000000000000..64e46fdfa4d404cb08c67a456e5990b7
+ * is owned by a direct or transitive dependency of the plugin, preventing the plugin for accidentally discovering and
+ * using class types that are supplied by plugins/libraries the plugin did not actively define as a dependency.
+ */
+@NullMarked
+@ApiStatus.Internal
+public interface ClassLoaderAccess {
+
@ -941,19 +919,18 @@ index 0000000000000000000000000000000000000000..64e46fdfa4d404cb08c67a456e5990b7
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..a21bdc57564aef7caf43dde3b2bcb2fc7f30461c
index 0000000000000000000000000000000000000000..7c23e0a1a38f8b89484aee160647f751088903cd
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java
@@ -0,0 +1,71 @@
@@ -0,0 +1,70 @@
+package io.papermc.paper.plugin.provider.classloader;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import java.io.Closeable;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Closeable;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * The configured plugin class loader represents an <b>internal</b> abstraction over the classloaders used by the server
@ -962,6 +939,7 @@ index 0000000000000000000000000000000000000000..a21bdc57564aef7caf43dde3b2bcb2fc
+ * It implements {@link Closeable} to define the ability to shutdown and close the classloader that implements this
+ * interface.
+ */
+@NullMarked
+@ApiStatus.Internal
+public interface ConfiguredPluginClassLoader extends Closeable {
+
@ -987,7 +965,7 @@ index 0000000000000000000000000000000000000000..a21bdc57564aef7caf43dde3b2bcb2fc
+ * @see ClassLoader#loadClass(String)
+ * @see Class#forName(String, boolean, ClassLoader)
+ */
+ Class<?> loadClass(@NotNull String name,
+ Class<?> loadClass(String name,
+ boolean resolve,
+ boolean checkGlobal,
+ boolean checkLibraries) throws ClassNotFoundException;
@ -1013,8 +991,7 @@ index 0000000000000000000000000000000000000000..a21bdc57564aef7caf43dde3b2bcb2fc
+ * that is used by the underlying classloader
+ * @return classloader
+ */
+ @Nullable
+ PluginClassLoaderGroup getGroup();
+ @Nullable PluginClassLoaderGroup getGroup();
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java
new file mode 100644
@ -1139,15 +1116,16 @@ index 0000000000000000000000000000000000000000..2c0e5ba6f8eba7a632180491843071b8
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..885151cb932d9b8c09a7887edc879e154225f416
index 0000000000000000000000000000000000000000..dd3bfbf8a30c9ac6a82dcbdf879bbf120d920e20
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java
@@ -0,0 +1,65 @@
@@ -0,0 +1,66 @@
+package io.papermc.paper.plugin.provider.classloader;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * A plugin classloader group represents a group of classloaders that a plugins classloader may access.
@ -1155,6 +1133,7 @@ index 0000000000000000000000000000000000000000..885151cb932d9b8c09a7887edc879e15
+ * An example of this would be a classloader group that holds all direct and transitive dependencies a plugin declared,
+ * allowing a plugins classloader to access classes included in these dependencies via this group.
+ */
+@NullMarked
+@ApiStatus.Internal
+public interface PluginClassLoaderGroup {
+
@ -1172,8 +1151,7 @@ index 0000000000000000000000000000000000000000..885151cb932d9b8c09a7887edc879e15
+ * will be returned.
+ * @see ConfiguredPluginClassLoader#loadClass(String, boolean, boolean, boolean)
+ */
+ @Nullable
+ Class<?> getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester);
+ @Nullable Class<?> getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester);
+
+ /**
+ * Removes a configured plugin classloader from this class loader group.
@ -1210,15 +1188,15 @@ index 0000000000000000000000000000000000000000..885151cb932d9b8c09a7887edc879e15
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc986b3761b4
index 0000000000000000000000000000000000000000..338dc25d5161b7378dd17b17d6f603c92eb0a894
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java
@@ -0,0 +1,48 @@
@@ -0,0 +1,49 @@
+package io.papermc.paper.plugin.provider.entrypoint;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A dependency context is a read-only abstraction of a type/concept that can resolve dependencies between plugins.
@ -1226,6 +1204,7 @@ index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc98
+ * This may for example be the server wide plugin manager itself, capable of validating if a dependency exists between
+ * two {@link PluginMeta} instances, however the implementation is not limited to such a concrete use-case.
+ */
+@NullMarked
+@ApiStatus.Internal
+public interface DependencyContext {
+
@ -1245,7 +1224,7 @@ index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc98
+ * @param depend the potential transitive dependency of the {@code plugin} parameter.
+ * @return a simple boolean flag indicating if {@code plugin} considers {@code depend} as a transitive dependency.
+ */
+ boolean isTransitiveDependency(@NotNull PluginMeta plugin, @NotNull PluginMeta depend);
+ boolean isTransitiveDependency(PluginMeta plugin, PluginMeta depend);
+
+ /**
+ * Computes if this dependency context is aware of a dependency that provides/matches the passed identifier.
@ -1259,29 +1238,30 @@ index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc98
+ * @return a plain boolean flag indicating if this dependency context is aware of a potential dependency with the
+ * passed identifier.
+ */
+ boolean hasDependency(@NotNull String pluginIdentifier);
+ boolean hasDependency(String pluginIdentifier);
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bf3d212a6156ad9ab0e82d1ca0a04f83f6e4b83
index 0000000000000000000000000000000000000000..48a67c1b6070292dbf4ea3081f89b530207f9f6d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java
@@ -0,0 +1,78 @@
@@ -0,0 +1,77 @@
+package io.papermc.paper.plugin.provider.util;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * An <b>internal</b> utility type that holds logic for loading a provider-like type from a classloaders.
+ * Provides, at least in the context of this utility, define themselves as implementations of a specific parent
+ * interface/type, e.g. {@link org.bukkit.plugin.java.JavaPlugin} and implement a no-args constructor.
+ */
+@NullMarked
+@ApiStatus.Internal
+public class ProviderUtil {
+public final class ProviderUtil {
+
+ /**
+ * Loads the class found at the provided fully qualified class name from the passed classloader, creates a new
@ -1294,8 +1274,7 @@ index 0000000000000000000000000000000000000000..6bf3d212a6156ad9ab0e82d1ca0a04f8
+ * @param <T> the generic type of the parent class the created object will be cast to
+ * @return the object instantiated from the class found at the provided FQN, cast to the parent type
+ */
+ @NotNull
+ public static <T> T loadClass(@NotNull String clazz, @NotNull Class<T> classType, @NotNull ClassLoader loader) {
+ public static <T> T loadClass(final String clazz, final Class<T> classType, final ClassLoader loader) {
+ return loadClass(clazz, classType, loader, null);
+ }
+
@ -1312,30 +1291,29 @@ index 0000000000000000000000000000000000000000..6bf3d212a6156ad9ab0e82d1ca0a04f8
+ * @return the object instantiated from the class found at the provided fully qualified class name, cast to the
+ * parent type
+ */
+ @NotNull
+ public static <T> T loadClass(@NotNull String clazz, @NotNull Class<T> classType, @NotNull ClassLoader loader, @Nullable Runnable onError) {
+ public static <T> T loadClass(final String clazz, final Class<T> classType, final ClassLoader loader, final @Nullable Runnable onError) {
+ try {
+ T clazzInstance;
+ final T clazzInstance;
+
+ try {
+ Class<?> jarClass = Class.forName(clazz, true, loader);
+ final Class<?> jarClass = Class.forName(clazz, true, loader);
+
+ Class<? extends T> pluginClass;
+ final Class<? extends T> pluginClass;
+ try {
+ pluginClass = jarClass.asSubclass(classType);
+ } catch (ClassCastException ex) {
+ } catch (final ClassCastException ex) {
+ throw new ClassCastException("class '%s' does not extend '%s'".formatted(clazz, classType));
+ }
+
+ clazzInstance = pluginClass.getDeclaredConstructor().newInstance();
+ } catch (IllegalAccessException exception) {
+ } catch (final IllegalAccessException exception) {
+ throw new RuntimeException("No public constructor");
+ } catch (InstantiationException exception) {
+ } catch (final InstantiationException exception) {
+ throw new RuntimeException("Abnormal class instantiation", exception);
+ }
+
+ return clazzInstance;
+ } catch (Throwable e) {
+ } catch (final Throwable e) {
+ if (onError != null) {
+ onError.run();
+ }

View file

@ -6,25 +6,27 @@ Subject: [PATCH] Add Position
diff --git a/src/main/java/io/papermc/paper/math/BlockPosition.java b/src/main/java/io/papermc/paper/math/BlockPosition.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e67020761ded3ac1
index 0000000000000000000000000000000000000000..c358bfdefc9bc7598dbd0d89a6b0b8a9408b5bb3
--- /dev/null
+++ b/src/main/java/io/papermc/paper/math/BlockPosition.java
@@ -0,0 +1,98 @@
@@ -0,0 +1,100 @@
+package io.papermc.paper.math;
+
+import org.bukkit.Axis;
+import org.bukkit.block.BlockFace;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A position represented with integers.
+ * <p>
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
+ *
+ * @see FinePosition
+ */
+@ApiStatus.Experimental
+@NullMarked
+public interface BlockPosition extends Position {
+
+ @Override
@ -53,17 +55,17 @@ index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e6702076
+ }
+
+ @Override
+ default @NotNull BlockPosition toBlock() {
+ default BlockPosition toBlock() {
+ return this;
+ }
+
+ @Override
+ default @NotNull BlockPosition offset(int x, int y, int z) {
+ default BlockPosition offset(final int x, final int y, final int z) {
+ return x == 0 && y == 0 && z == 0 ? this : new BlockPositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z);
+ }
+
+ @Override
+ default @NotNull FinePosition offset(double x, double y, double z) {
+ default FinePosition offset(final double x, final double y, final double z) {
+ return new FinePositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z);
+ }
+
@ -74,7 +76,7 @@ index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e6702076
+ * @return the offset block position
+ */
+ @Contract(value = "_ -> new", pure = true)
+ default @NotNull BlockPosition offset(@NotNull BlockFace blockFace) {
+ default BlockPosition offset(final BlockFace blockFace) {
+ return this.offset(blockFace, 1);
+ }
+
@ -87,7 +89,7 @@ index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e6702076
+ * @return the offset block position
+ */
+ @Contract(pure = true)
+ default @NotNull BlockPosition offset(@NotNull BlockFace blockFace, int amount) {
+ default BlockPosition offset(final BlockFace blockFace, final int amount) {
+ return amount == 0 ? this : new BlockPositionImpl(this.blockX() + (blockFace.getModX() * amount), this.blockY() + (blockFace.getModY() * amount), this.blockZ() + (blockFace.getModZ() * amount));
+ }
+
@ -100,7 +102,7 @@ index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e6702076
+ * @return the offset block position
+ */
+ @Contract(pure = true)
+ default @NotNull BlockPosition offset(@NotNull Axis axis, int amount) {
+ default BlockPosition offset(final Axis axis, final int amount) {
+ return amount == 0 ? this : switch (axis) {
+ case X -> new BlockPositionImpl(this.blockX() + amount, this.blockY(), this.blockZ());
+ case Y -> new BlockPositionImpl(this.blockX(), this.blockY() + amount, this.blockZ());
@ -120,24 +122,25 @@ index 0000000000000000000000000000000000000000..eb5a3f26c7ba56c6715827f52c0013a8
+}
diff --git a/src/main/java/io/papermc/paper/math/FinePosition.java b/src/main/java/io/papermc/paper/math/FinePosition.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8df70d731573cf2446044925f218876d62fd7cf
index 0000000000000000000000000000000000000000..b9c0065d8a9dedc3bd1a2d8bfbedfbc7f952ff93
--- /dev/null
+++ b/src/main/java/io/papermc/paper/math/FinePosition.java
@@ -0,0 +1,56 @@
@@ -0,0 +1,57 @@
+package io.papermc.paper.math;
+
+import org.bukkit.util.NumberConversions;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A position represented with doubles.
+ * <p>
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
+ *
+ * @see BlockPosition
+ */
+@ApiStatus.Experimental
+@NullMarked
+public interface FinePosition extends Position {
+
+ @Override
@ -166,17 +169,17 @@ index 0000000000000000000000000000000000000000..d8df70d731573cf2446044925f218876
+ }
+
+ @Override
+ default @NotNull BlockPosition toBlock() {
+ default BlockPosition toBlock() {
+ return new BlockPositionImpl(this.blockX(), this.blockY(), this.blockZ());
+ }
+
+ @Override
+ default @NotNull FinePosition offset(int x, int y, int z) {
+ default FinePosition offset(final int x, final int y, final int z) {
+ return this.offset((double) x, y, z);
+ }
+
+ @Override
+ default @NotNull FinePosition offset(double x, double y, double z) {
+ default FinePosition offset(final double x, final double y, final double z) {
+ return x == 0.0 && y == 0.0 && z == 0.0 ? this : new FinePositionImpl(this.x() + x, this.y() + y, this.z() + z);
+ }
+}
@ -192,10 +195,10 @@ index 0000000000000000000000000000000000000000..93476aaf8d21efb5a30b6d2cc2eeda81
+}
diff --git a/src/main/java/io/papermc/paper/math/Position.java b/src/main/java/io/papermc/paper/math/Position.java
new file mode 100644
index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d9f242740
index 0000000000000000000000000000000000000000..0e6a6a6738353b118e0ed093994dda06750700c4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/math/Position.java
@@ -0,0 +1,191 @@
@@ -0,0 +1,192 @@
+package io.papermc.paper.math;
+
+import org.bukkit.Location;
@ -203,7 +206,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Common interface for {@link FinePosition} and {@link BlockPosition}.
@ -211,6 +214,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
+ */
+@ApiStatus.Experimental
+@NullMarked
+public interface Position {
+
+ FinePosition FINE_ZERO = new FinePositionImpl(0, 0, 0);
@ -287,7 +291,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @param z z value to offset
+ * @return the offset position
+ */
+ @NotNull Position offset(int x, int y, int z);
+ Position offset(int x, int y, int z);
+
+ /**
+ * Returns a position offset by the specified amounts.
@ -297,7 +301,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @param z z value to offset
+ * @return the offset position
+ */
+ @NotNull FinePosition offset(double x, double y, double z);
+ FinePosition offset(double x, double y, double z);
+
+ /**
+ * Returns a new position at the center of the block position this represents
@ -305,7 +309,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a new center position
+ */
+ @Contract(value = "-> new", pure = true)
+ default @NotNull FinePosition toCenter() {
+ default FinePosition toCenter() {
+ return new FinePositionImpl(this.blockX() + 0.5, this.blockY() + 0.5, this.blockZ() + 0.5);
+ }
+
@ -316,7 +320,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return the block position
+ */
+ @Contract(pure = true)
+ @NotNull BlockPosition toBlock();
+ BlockPosition toBlock();
+
+ /**
+ * Converts this position to a vector
@ -324,7 +328,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a new vector
+ */
+ @Contract(value = "-> new", pure = true)
+ default @NotNull Vector toVector() {
+ default Vector toVector() {
+ return new Vector(this.x(), this.y(), this.z());
+ }
+
@ -335,7 +339,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a new location
+ */
+ @Contract(value = "_ -> new", pure = true)
+ default @NotNull Location toLocation(@NotNull World world) {
+ default Location toLocation(final World world) {
+ return new Location(world, this.x(), this.y(), this.z());
+ }
+
@ -348,7 +352,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a position with those coords
+ */
+ @Contract(value = "_, _, _ -> new", pure = true)
+ static @NotNull BlockPosition block(int x, int y, int z) {
+ static BlockPosition block(final int x, final int y, final int z) {
+ return new BlockPositionImpl(x, y, z);
+ }
+
@ -359,7 +363,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a new position at that location
+ */
+ @Contract(value = "_ -> new", pure = true)
+ static @NotNull BlockPosition block(@NotNull Location location) {
+ static BlockPosition block(final Location location) {
+ return new BlockPositionImpl(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
@ -372,7 +376,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a position with those coords
+ */
+ @Contract(value = "_, _, _ -> new", pure = true)
+ static @NotNull FinePosition fine(double x, double y, double z) {
+ static FinePosition fine(final double x, final double y, final double z) {
+ return new FinePositionImpl(x, y, z);
+ }
+
@ -383,7 +387,7 @@ index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d
+ * @return a new position at that location
+ */
+ @Contract(value = "_ -> new", pure = true)
+ static @NotNull FinePosition fine(@NotNull Location location) {
+ static FinePosition fine(final Location location) {
+ return new FinePositionImpl(location.getX(), location.getY(), location.getZ());
+ }
+}

View file

@ -10,18 +10,21 @@ Co-authored-by: Riley Park <rileysebastianpark@gmail.com>
diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346
index 0000000000000000000000000000000000000000..023cc52a9e28e1238c7452c0f3f577f2850fd861
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
@@ -0,0 +1,45 @@
@@ -0,0 +1,47 @@
+package com.destroystokyo.paper.util;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.bukkit.Bukkit;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public interface VersionFetcher {
+
+ /**
+ * Amount of time to cache results for in milliseconds
+ * <p>
@ -39,9 +42,9 @@ index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c7
+ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()})
+ * @return the message to show when requesting a version
+ */
+ @NotNull
+ Component getVersionMessage(@NotNull String serverVersion);
+ Component getVersionMessage(String serverVersion);
+
+ @ApiStatus.Internal
+ class DummyVersionFetcher implements VersionFetcher {
+
+ @Override
@ -49,9 +52,8 @@ index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c7
+ return -1;
+ }
+
+ @NotNull
+ @Override
+ public Component getVersionMessage(@NotNull String serverVersion) {
+ public Component getVersionMessage(final String serverVersion) {
+ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!");
+ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()");
+ new Throwable().printStackTrace();
@ -61,10 +63,10 @@ index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c7
+}
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816df1ef0964
index 0000000000000000000000000000000000000000..652ff54e7c50412503725d628bfe72ed03059790
--- /dev/null
+++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java
@@ -0,0 +1,121 @@
@@ -0,0 +1,122 @@
+package io.papermc.paper;
+
+import java.time.Instant;
@ -73,11 +75,12 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.util.Services;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Information about the current server build.
+ */
+@NullMarked
+@ApiStatus.NonExtendable
+public interface ServerBuildInfo {
+ /**
@ -90,7 +93,7 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+ *
+ * @return the {@code ServerBuildInfo}
+ */
+ static @NotNull ServerBuildInfo buildInfo() {
+ static ServerBuildInfo buildInfo() {
+ //<editor-fold defaultstate="collapsed" desc="Holder">
+ final class Holder {
+ static final Optional<ServerBuildInfo> INSTANCE = Services.service(ServerBuildInfo.class);
@ -104,7 +107,7 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+ *
+ * @return the brand id of the server (e.g. "papermc:paper")
+ */
+ @NotNull Key brandId();
+ Key brandId();
+
+ /**
+ * Checks if the current server supports the specified brand.
@ -113,56 +116,56 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+ * @return {@code true} if the server supports the specified brand
+ */
+ @ApiStatus.Experimental
+ boolean isBrandCompatible(final @NotNull Key brandId);
+ boolean isBrandCompatible(final Key brandId);
+
+ /**
+ * Gets the brand name of the server.
+ *
+ * @return the brand name of the server (e.g. "Paper")
+ */
+ @NotNull String brandName();
+ String brandName();
+
+ /**
+ * Gets the Minecraft version id.
+ *
+ * @return the Minecraft version id (e.g. "1.20.4", "1.20.2-pre2", "23w31a")
+ */
+ @NotNull String minecraftVersionId();
+ String minecraftVersionId();
+
+ /**
+ * Gets the Minecraft version name.
+ *
+ * @return the Minecraft version name (e.g. "1.20.4", "1.20.2 Pre-release 2", "23w31a")
+ */
+ @NotNull String minecraftVersionName();
+ String minecraftVersionName();
+
+ /**
+ * Gets the build number.
+ *
+ * @return the build number
+ */
+ @NotNull OptionalInt buildNumber();
+ OptionalInt buildNumber();
+
+ /**
+ * Gets the build time.
+ *
+ * @return the build time
+ */
+ @NotNull Instant buildTime();
+ Instant buildTime();
+
+ /**
+ * Gets the git commit branch.
+ *
+ * @return the git commit branch
+ */
+ @NotNull Optional<String> gitBranch();
+ Optional<String> gitBranch();
+
+ /**
+ * Gets the git commit hash.
+ *
+ * @return the git commit hash
+ */
+ @NotNull Optional<String> gitCommit();
+ Optional<String> gitCommit();
+
+ /**
+ * Creates a string representation of the server build information.
@ -170,7 +173,7 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+ * @param representation the type of representation
+ * @return a string
+ */
+ @NotNull String asString(final @NotNull StringRepresentation representation);
+ String asString(final StringRepresentation representation);
+
+ /**
+ * String representation types.
@ -188,10 +191,10 @@ index 0000000000000000000000000000000000000000..9df9d09aa477d4cd3c496ba0933c816d
+}
diff --git a/src/main/java/io/papermc/paper/util/JarManifests.java b/src/main/java/io/papermc/paper/util/JarManifests.java
new file mode 100644
index 0000000000000000000000000000000000000000..909617079db61b675cc7b60b44ef96b306076343
index 0000000000000000000000000000000000000000..7915a70d676b1205dcae39259f670af258a1ab9b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/JarManifests.java
@@ -0,0 +1,37 @@
@@ -0,0 +1,38 @@
+package io.papermc.paper.util;
+
+import java.io.IOException;
@ -202,9 +205,10 @@ index 0000000000000000000000000000000000000000..909617079db61b675cc7b60b44ef96b3
+import java.util.WeakHashMap;
+import java.util.jar.Manifest;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+@ApiStatus.Internal
+public final class JarManifests {
+ private JarManifests() {
@ -212,7 +216,7 @@ index 0000000000000000000000000000000000000000..909617079db61b675cc7b60b44ef96b3
+
+ private static final Map<ClassLoader, Manifest> MANIFESTS = Collections.synchronizedMap(new WeakHashMap<>());
+
+ public static @Nullable Manifest manifest(final @NotNull Class<?> clazz) {
+ public static @Nullable Manifest manifest(final Class<?> clazz) {
+ return MANIFESTS.computeIfAbsent(clazz.getClassLoader(), classLoader -> {
+ final String classLocation = "/" + clazz.getName().replace(".", "/") + ".class";
+ final URL resource = clazz.getResource(classLocation);

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Add BeaconEffectEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1288f8f13
index 0000000000000000000000000000000000000000..741d0e73bc635a545c94c4b1254cee8f41ba8925
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
@@ -0,0 +1,91 @@
@@ -0,0 +1,88 @@
+package com.destroystokyo.paper.event.block;
+
+import org.bukkit.block.Block;
@ -19,11 +19,12 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+import org.bukkit.event.block.BlockEvent;
+import org.bukkit.potion.PotionEffect;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called when a beacon effect is being applied to a player.
+ */
+@NullMarked
+public class BeaconEffectEvent extends BlockEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
@ -35,7 +36,7 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) {
+ public BeaconEffectEvent(final Block block, final PotionEffect effect, final Player player, final boolean primary) {
+ super(block);
+ this.effect = effect;
+ this.player = player;
@ -47,7 +48,6 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+ *
+ * @return Potion effect
+ */
+ @NotNull
+ public PotionEffect getEffect() {
+ return this.effect;
+ }
@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+ *
+ * @param effect Potion effect
+ */
+ public void setEffect(@NotNull PotionEffect effect) {
+ public void setEffect(final PotionEffect effect) {
+ this.effect = effect;
+ }
+
@ -66,7 +66,6 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+ *
+ * @return Affected player
+ */
+ @NotNull
+ public Player getPlayer() {
+ return this.player;
+ }
@ -86,17 +85,15 @@ index 0000000000000000000000000000000000000000..7270c1feece2dc15a4a0503c4bca93a1
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -6,30 +6,31 @@ Subject: [PATCH] Add exception reporting event
diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9377ee1c2368ce058397037952d17bc010f66957
index 0000000000000000000000000000000000000000..95a5a59e6bd88345177fca0b12008ddd689cb448
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
@@ -0,0 +1,45 @@
@@ -0,0 +1,43 @@
+package com.destroystokyo.paper.event.server;
+
+import com.destroystokyo.paper.exception.ServerException;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import com.destroystokyo.paper.exception.ServerException;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called whenever an exception is thrown in a recoverable section of the server.
+ */
+@NullMarked
+public class ServerExceptionEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final ServerException exception;
+ private final ServerException exception;
+
+ @ApiStatus.Internal
+ public ServerExceptionEvent(@NotNull ServerException exception) {
+ public ServerExceptionEvent(final ServerException exception) {
+ super(!Bukkit.isPrimaryThread());
+ this.exception = exception;
+ }
@ -39,18 +40,15 @@ index 0000000000000000000000000000000000000000..9377ee1c2368ce058397037952d17bc0
+ *
+ * @return Exception thrown
+ */
+ @NotNull
+ public ServerException getException() {
+ return this.exception;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,7 +7,7 @@ Upstream added methods for this so the original methods
are now deprecated
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index 67115810d5e837f154c3accd92dbb5e4192d264f..32e89741ffd895e31af0104a0126c2f72742a1bb 100644
index b5a302ba913d2de97f1bcd7c60fd5cd4f245d275..cafa79f80eec5ec6d8d31d40cc2b46acc06831f9 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -243,12 +243,44 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@ -56,7 +56,7 @@ index 67115810d5e837f154c3accd92dbb5e4192d264f..32e89741ffd895e31af0104a0126c2f7
/**
* Returns the living entity's current maximum no damage ticks.
@@ -777,4 +809,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@@ -787,4 +819,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
* @return Whether the entity is invisible
*/
public boolean isInvisible();

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Entity AddTo/RemoveFrom World Events
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d8e3c93a139bba11affca74b742269f24300d2c
index 0000000000000000000000000000000000000000..11f8540a4752cf4d2112eff48bcca3b935c9f8b1
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
@@ -0,0 +1,45 @@
@@ -0,0 +1,44 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.World;
@ -18,21 +18,22 @@ index 0000000000000000000000000000000000000000..1d8e3c93a139bba11affca74b742269f
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired any time an entity is being added to the world for any reason (including a chunk loading).
+ * <p>
+ * Not to be confused with {@link CreatureSpawnEvent}
+ */
+@NullMarked
+public class EntityAddToWorldEvent extends EntityEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final World world;
+ private final World world;
+
+ @ApiStatus.Internal
+ public EntityAddToWorldEvent(@NotNull Entity entity, @NotNull World world) {
+ public EntityAddToWorldEvent(final Entity entity, final World world) {
+ super(entity);
+ this.world = world;
+ }
@ -40,27 +41,25 @@ index 0000000000000000000000000000000000000000..1d8e3c93a139bba11affca74b742269f
+ /**
+ * @return The world that the entity is being added to
+ */
+ @NotNull
+ public World getWorld() {
+ return this.world;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75e6a8334c7408ea8c3f155414fc14dc427f190
index 0000000000000000000000000000000000000000..5ad5632d4d47d8b42e4f2af19c0fe6cf94ac5643
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
@@ -0,0 +1,43 @@
@@ -0,0 +1,42 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.World;
@ -68,20 +67,21 @@ index 0000000000000000000000000000000000000000..d75e6a8334c7408ea8c3f155414fc14d
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired any time an entity is being removed from a world for any reason (including a chunk unloading).
+ * Note: The entity is updated prior to this event being called, as such, the entity's world may not be equal to {@link #getWorld()}.
+ */
+@NullMarked
+public class EntityRemoveFromWorldEvent extends EntityEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final World world;
+ private final World world;
+
+ @ApiStatus.Internal
+ public EntityRemoveFromWorldEvent(@NotNull Entity entity, @NotNull World world) {
+ public EntityRemoveFromWorldEvent(final Entity entity, final World world) {
+ super(entity);
+ this.world = world;
+ }
@ -89,17 +89,15 @@ index 0000000000000000000000000000000000000000..d75e6a8334c7408ea8c3f155414fc14d
+ /**
+ * @return The world that the entity is being removed from
+ */
+ @NotNull
+ public World getWorld() {
+ return this.world;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,10 +7,10 @@ Fires when an Entity decides to start moving to a location.
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee4b29e109
index 0000000000000000000000000000000000000000..8624e0a528985c9b118f5e8a0f33d3286af2fc36
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
@@ -0,0 +1,87 @@
@@ -0,0 +1,84 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.Location;
@ -19,8 +19,8 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Fired when an Entity decides to start moving towards a location.
@ -28,16 +28,17 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+ * This event does not fire for the entities actual movement. Only when it
+ * is choosing to start moving to a location.
+ */
+@NullMarked
+public class EntityPathfindEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @Nullable private final Entity targetEntity;
+ @NotNull private final Location location;
+ private final @Nullable Entity targetEntity;
+ private final Location location;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location location, @Nullable Entity targetEntity) {
+ public EntityPathfindEvent(final Entity entity, final Location location, final @Nullable Entity targetEntity) {
+ super(entity);
+ this.targetEntity = targetEntity;
+ this.location = location;
@ -48,7 +49,7 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+ *
+ * @return The Entity that is pathfinding.
+ */
+ @NotNull
+ @Override
+ public Entity getEntity() {
+ return this.entity;
+ }
@ -56,12 +57,11 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+ /**
+ * If the Entity is trying to pathfind to an entity, this is the entity in relation.
+ * <br>
+ * Otherwise this will return {@code null}.
+ * Otherwise, this will return {@code null}.
+ *
+ * @return The entity target or {@code null}
+ */
+ @Nullable
+ public Entity getTargetEntity() {
+ public @Nullable Entity getTargetEntity() {
+ return this.targetEntity;
+ }
+
@ -72,7 +72,6 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+ *
+ * @return Location of where the entity is trying to pathfind to.
+ */
+ @NotNull
+ public Location getLoc() {
+ return this.location.clone();
+ }
@ -83,17 +82,15 @@ index 0000000000000000000000000000000000000000..8267e8f1f0ade29a284831069e1268ee
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -10,10 +10,10 @@ Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbb635686e9108b9d3df5d373e6972cca07c0621
index 0000000000000000000000000000000000000000..9ff2bbf7f99df45cc626cad60bec4d14a8a04e3e
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java
@@ -0,0 +1,86 @@
@@ -0,0 +1,85 @@
+package com.destroystokyo.paper.event.player;
+
+import org.bukkit.entity.Player;
@ -23,8 +23,8 @@ index 0000000000000000000000000000000000000000..dbb635686e9108b9d3df5d373e6972cc
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents an event that is called when a player right-clicks an unknown entity.
@ -33,17 +33,18 @@ index 0000000000000000000000000000000000000000..dbb635686e9108b9d3df5d373e6972cc
+ * This event may be called multiple times per interaction with different interaction hands
+ * and with or without the clicked position.
+ */
+@NullMarked
+public class PlayerUseUnknownEntityEvent extends PlayerEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final int entityId;
+ private final boolean attack;
+ private final @NotNull EquipmentSlot hand;
+ private final EquipmentSlot hand;
+ private final @Nullable Vector clickedPosition;
+
+ @ApiStatus.Internal
+ public PlayerUseUnknownEntityEvent(@NotNull Player player, int entityId, boolean attack, @NotNull EquipmentSlot hand, @Nullable Vector clickedPosition) {
+ public PlayerUseUnknownEntityEvent(final Player player, final int entityId, final boolean attack, final EquipmentSlot hand, final @Nullable Vector clickedPosition) {
+ super(player);
+ this.entityId = entityId;
+ this.attack = attack;
@ -74,7 +75,7 @@ index 0000000000000000000000000000000000000000..dbb635686e9108b9d3df5d373e6972cc
+ *
+ * @return the hand used to interact
+ */
+ public @NotNull EquipmentSlot getHand() {
+ public EquipmentSlot getHand() {
+ return this.hand;
+ }
+
@ -89,13 +90,11 @@ index 0000000000000000000000000000000000000000..dbb635686e9108b9d3df5d373e6972cc
+ return this.clickedPosition != null ? this.clickedPosition.clone() : null;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,13 +7,14 @@ Subject: [PATCH] Add handshake event to allow plugins to handle client
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4ce03ef477
index 0000000000000000000000000000000000000000..aea04fb357f5728195fd9c9bdcd6304a0b953c45
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java
@@ -0,0 +1,267 @@
@@ -0,0 +1,257 @@
+package com.destroystokyo.paper.event.player;
+
+import com.google.common.base.Preconditions;
+import java.util.UUID;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
@ -21,10 +22,8 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * This event is fired during a player handshake.
@ -34,16 +33,17 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * <p>WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS</p>
+ */
+@NullMarked
+public class PlayerHandshakeEvent extends Event implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final String originalHandshake;
+ @NotNull private final String originalSocketAddressHostname;
+ @Nullable private String serverHostname;
+ @Nullable private String socketAddressHostname;
+ @Nullable private UUID uniqueId;
+ @Nullable private String propertiesJson;
+ private final String originalHandshake;
+ private final String originalSocketAddressHostname;
+ private @Nullable String serverHostname;
+ private @Nullable String socketAddressHostname;
+ private @Nullable UUID uniqueId;
+ private @Nullable String propertiesJson;
+ private boolean failed;
+ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW);
+
@ -51,12 +51,12 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+
+ @Deprecated
+ @ApiStatus.Internal
+ public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) {
+ public PlayerHandshakeEvent(final String originalHandshake, final boolean cancelled) {
+ this(originalHandshake, "127.0.0.1", cancelled);
+ }
+
+ @ApiStatus.Internal
+ public PlayerHandshakeEvent(@NotNull String originalHandshake, @NotNull String originalSocketAddressHostname, boolean cancelled) {
+ public PlayerHandshakeEvent(final String originalHandshake, final String originalSocketAddressHostname, final boolean cancelled) {
+ super(true);
+ this.originalHandshake = originalHandshake;
+ this.originalSocketAddressHostname = originalSocketAddressHostname;
@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ * @param cancel {@code true} if this event is cancelled, {@code false} otherwise
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
@ -94,7 +94,6 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the original handshake string
+ */
+ @NotNull
+ public String getOriginalHandshake() {
+ return this.originalHandshake;
+ }
@ -107,7 +106,6 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the original socket address hostname
+ */
+ @NotNull
+ public String getOriginalSocketAddressHostname() {
+ return this.originalSocketAddressHostname;
+ }
@ -119,8 +117,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the server hostname string
+ */
+ @Nullable
+ public String getServerHostname() {
+ public @Nullable String getServerHostname() {
+ return this.serverHostname;
+ }
+
@ -131,7 +128,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param serverHostname the server hostname string
+ */
+ public void setServerHostname(@NotNull String serverHostname) {
+ public void setServerHostname(final String serverHostname) {
+ this.serverHostname = serverHostname;
+ }
+
@ -142,8 +139,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the socket address hostname string
+ */
+ @Nullable
+ public String getSocketAddressHostname() {
+ public @Nullable String getSocketAddressHostname() {
+ return this.socketAddressHostname;
+ }
+
@ -154,7 +150,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param socketAddressHostname the socket address hostname string
+ */
+ public void setSocketAddressHostname(@NotNull String socketAddressHostname) {
+ public void setSocketAddressHostname(final String socketAddressHostname) {
+ this.socketAddressHostname = socketAddressHostname;
+ }
+
@ -163,8 +159,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the unique id
+ */
+ @Nullable
+ public UUID getUniqueId() {
+ public @Nullable UUID getUniqueId() {
+ return this.uniqueId;
+ }
+
@ -173,7 +168,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param uniqueId the unique id
+ */
+ public void setUniqueId(@NotNull UUID uniqueId) {
+ public void setUniqueId(final UUID uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
@ -184,8 +179,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the profile properties, as JSON
+ */
+ @Nullable
+ public String getPropertiesJson() {
+ public @Nullable String getPropertiesJson() {
+ return this.propertiesJson;
+ }
+
@ -209,7 +203,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param failed {@code true} if authentication failed, {@code false} otherwise
+ */
+ public void setFailed(boolean failed) {
+ public void setFailed(final boolean failed) {
+ this.failed = failed;
+ }
+
@ -220,7 +214,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param propertiesJson the profile properties, as JSON
+ */
+ public void setPropertiesJson(@NotNull String propertiesJson) {
+ public void setPropertiesJson(final String propertiesJson) {
+ this.propertiesJson = propertiesJson;
+ }
+
@ -229,7 +223,6 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @return the message to display to the client
+ */
+ @NotNull
+ public Component failMessage() {
+ return this.failMessage;
+ }
@ -239,7 +232,7 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ *
+ * @param failMessage the message to display to the client
+ */
+ public void failMessage(@NotNull Component failMessage) {
+ public void failMessage(final Component failMessage) {
+ this.failMessage = failMessage;
+ }
+
@ -249,7 +242,6 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ * @return the message to display to the client
+ * @deprecated use {@link #failMessage()}
+ */
+ @NotNull
+ @Deprecated
+ public String getFailMessage() {
+ return LegacyComponentSerializer.legacySection().serialize(this.failMessage());
@ -262,18 +254,16 @@ index 0000000000000000000000000000000000000000..7c049bad187b94331f42f96833d1cf4c
+ * @deprecated use {@link #failMessage(Component)}
+ */
+ @Deprecated
+ public void setFailMessage(@NotNull String failMessage) {
+ public void setFailMessage(final String failMessage) {
+ Preconditions.checkArgument(failMessage != null && !failMessage.isEmpty(), "fail message cannot be null or empty");
+ this.failMessage(LegacyComponentSerializer.legacySection().deserialize(failMessage));
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -12,96 +12,98 @@ Provides methods to determine players looted state for an object
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
new file mode 100644
index 0000000000000000000000000000000000000000..92d7b853a2ccaae5afa8ac141bead840942944ef
index 0000000000000000000000000000000000000000..6a03252d66a3e13c1960568ea23f6dcc673f34af
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
@@ -0,0 +1,17 @@
+package com.destroystokyo.paper.loottable;
+
+import org.bukkit.block.Block;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts
+ */
+@NullMarked
+public interface LootableBlockInventory extends LootableInventory {
+
+ /**
+ * Gets the block that is lootable
+ * @return The Block
+ */
+ @NotNull
+ Block getBlock();
+}
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b387894fe8001edb41ad2ad2b70ebabe065b682e
index 0000000000000000000000000000000000000000..31ca54dea65dc0363a0ff7991ba5be3b06533876
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
@@ -0,0 +1,17 @@
+package com.destroystokyo.paper.loottable;
+
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts
+ */
+@NullMarked
+public interface LootableEntityInventory extends LootableInventory {
+
+ /**
+ * Gets the entity that is lootable
+ * @return The Entity
+ */
+ @NotNull
+ Entity getEntity();
+}
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b18a0b50c12fe8d8c954e5c070f2ecd1854a2583
index 0000000000000000000000000000000000000000..9fb621200fb3969e8e440341e906acc3547b4039
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
@@ -0,0 +1,124 @@
@@ -0,0 +1,128 @@
+package com.destroystokyo.paper.loottable;
+
+import java.util.UUID;
+import org.bukkit.entity.Player;
+import org.bukkit.loot.Lootable;
+
+import java.util.UUID;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents an Inventory that contains a Loot Table associated to it that will
+ * automatically fill on first open.
+ *
+ * <p>
+ * A new feature and API is provided to support automatically refreshing the contents
+ * of the inventory based on that Loot Table after a configurable amount of time has passed.
+ *
+ * <p>
+ * The behavior of how the Inventory is filled based on the loot table may vary based
+ * on Minecraft versions and the Loot Table feature.
+ */
+@NullMarked
+public interface LootableInventory extends Lootable {
+
+ /**
+ * Server owners have to enable whether or not an object in a world should refill
+ * Server owners have to enable whether an object in a world should refill
+ *
+ * @return If the world this inventory is currently in has Replenishable Lootables enabled
+ */
+ boolean isRefillEnabled();
+
+ /**
+ * Whether or not this object has ever been filled
+ * Whether this object has ever been filled
+ *
+ * @return Has ever been filled
+ */
+ boolean hasBeenFilled();
+
+ /**
+ * Has this player ever looted this block
+ *
+ * @param player The player to check
+ * @return Whether or not this player has looted this block
+ * @return Whether this player has looted this block
+ */
+ default boolean hasPlayerLooted(final @NotNull Player player) {
+ default boolean hasPlayerLooted(final Player player) {
+ return this.hasPlayerLooted(player.getUniqueId());
+ }
+
@ -109,17 +111,17 @@ index 0000000000000000000000000000000000000000..b18a0b50c12fe8d8c954e5c070f2ecd1
+ * Checks if this player can loot this block. Takes into account the "restrict player reloot" settings
+ *
+ * @param player the player to check
+ *
+ * @return Whether this player can loot this block
+ */
+ boolean canPlayerLoot(@NotNull UUID player);
+ boolean canPlayerLoot(UUID player);
+
+ /**
+ * Has this player ever looted this block
+ *
+ * @param player The player to check
+ * @return Whether or not this player has looted this block
+ * @return Whether this player has looted this block
+ */
+ boolean hasPlayerLooted(@NotNull UUID player);
+ boolean hasPlayerLooted(UUID player);
+
+ /**
+ * Gets the timestamp, in milliseconds, of when the player last looted this object
@ -127,7 +129,7 @@ index 0000000000000000000000000000000000000000..b18a0b50c12fe8d8c954e5c070f2ecd1
+ * @param player The player to check
+ * @return Timestamp last looted, or null if player has not looted this object
+ */
+ default @Nullable Long getLastLooted(final @NotNull Player player) {
+ default @Nullable Long getLastLooted(final Player player) {
+ return this.getLastLooted(player.getUniqueId());
+ }
+
@ -137,29 +139,31 @@ index 0000000000000000000000000000000000000000..b18a0b50c12fe8d8c954e5c070f2ecd1
+ * @param player The player to check
+ * @return Timestamp last looted, or null if player has not looted this object
+ */
+ @Nullable
+ Long getLastLooted(@NotNull UUID player);
+ @Nullable Long getLastLooted(UUID player);
+
+ /**
+ * Change the state of whether or not a player has looted this block
+ * Change the state of whether a player has looted this block
+ *
+ * @param player The player to change state for
+ * @param looted true to add player to looted list, false to remove
+ * @return The previous state of whether the player had looted this or not
+ */
+ default boolean setHasPlayerLooted(final @NotNull Player player, final boolean looted) {
+ default boolean setHasPlayerLooted(final Player player, final boolean looted) {
+ return this.setHasPlayerLooted(player.getUniqueId(), looted);
+ }
+
+ /**
+ * Change the state of whether or not a player has looted this block
+ * Change the state of whether a player has looted this block
+ *
+ * @param player The player to change state for
+ * @param looted true to add player to looted list, false to remove
+ * @return The previous state of whether the player had looted this or not
+ */
+ boolean setHasPlayerLooted(@NotNull UUID player, boolean looted);
+ boolean setHasPlayerLooted(UUID player, boolean looted);
+
+ /**
+ * Returns Whether or not this object has been filled and now has a pending refill
+ * Returns Whether this object has been filled and now has a pending refill
+ *
+ * @return Has pending refill
+ */
+ boolean hasPendingRefill();
@ -188,10 +192,10 @@ index 0000000000000000000000000000000000000000..b18a0b50c12fe8d8c954e5c070f2ecd1
+}
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ee1a04aaaa4ef09559f2cf757811e463e2a1be6
index 0000000000000000000000000000000000000000..994c2183db89fc40d5991d5e1906e4bd04db6291
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
@@ -0,0 +1,47 @@
@@ -0,0 +1,46 @@
+package com.destroystokyo.paper.loottable;
+
+import org.bukkit.entity.Player;
@ -199,22 +203,22 @@ index 0000000000000000000000000000000000000000..5ee1a04aaaa4ef09559f2cf757811e46
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final LootableInventory inventory;
+ private final LootableInventory inventory;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public LootableInventoryReplenishEvent(@NotNull Player player, @NotNull LootableInventory inventory) {
+ public LootableInventoryReplenishEvent(final Player player, final LootableInventory inventory) {
+ super(player);
+ this.inventory = inventory;
+ }
+
+ @NotNull
+ public LootableInventory getInventory() {
+ return this.inventory;
+ }
@ -225,16 +229,15 @@ index 0000000000000000000000000000000000000000..5ee1a04aaaa4ef09559f2cf757811e46
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -6,34 +6,34 @@ Subject: [PATCH] Add EntityZapEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc6d15975a47e68c5bd939e68ddd2773028a6ac8
index 0000000000000000000000000000000000000000..af2b1629f845ffe1559e7d580b482636cc6441d9
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java
@@ -0,0 +1,69 @@
@@ -0,0 +1,65 @@
+package com.destroystokyo.paper.event.entity;
+
+import java.util.Collections;
+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.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when lightning strikes an entity
+ */
+@NullMarked
+public class EntityZapEvent extends EntityTransformEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final LightningStrike bolt;
+ private final LightningStrike bolt;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) {
+ public EntityZapEvent(final Entity entity, final LightningStrike bolt, final Entity replacementEntity) {
+ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING);
+ this.bolt = bolt;
+ }
@ -43,7 +43,6 @@ index 0000000000000000000000000000000000000000..dc6d15975a47e68c5bd939e68ddd2773
+ *
+ * @return The lightning bolt responsible for this event
+ */
+ @NotNull
+ public LightningStrike getBolt() {
+ return this.bolt;
+ }
@ -53,7 +52,6 @@ index 0000000000000000000000000000000000000000..dc6d15975a47e68c5bd939e68ddd2773
+ *
+ * @return The entity that will replace the struck entity
+ */
+ @NotNull
+ public Entity getReplacementEntity() {
+ return super.getTransformedEntity();
+ }
@ -64,17 +62,15 @@ index 0000000000000000000000000000000000000000..dc6d15975a47e68c5bd939e68ddd2773
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -6,41 +6,44 @@ Subject: [PATCH] Misc Utils
diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java
new file mode 100644
index 0000000000000000000000000000000000000000..5bb677ce585b856b3d3e589e29786a29619c56a7
index 0000000000000000000000000000000000000000..ebaa12ecacd169f00e184fed95720d047eda8b9d
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java
@@ -0,0 +1,34 @@
@@ -0,0 +1,37 @@
+package com.destroystokyo.paper.utils;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+@ApiStatus.Internal
+public class CachedSizeConcurrentLinkedQueue<E> extends ConcurrentLinkedQueue<E> {
+
+ private final LongAdder cachedSize = new LongAdder();
+
+ @Override
+ public boolean add(@NotNull E e) {
+ boolean result = super.add(e);
+ public boolean add(final E e) {
+ final boolean result = super.add(e);
+ if (result) {
+ cachedSize.increment();
+ this.cachedSize.increment();
+ }
+ return result;
+ }
+
+ @Nullable
+ @Override
+ public E poll() {
+ E result = super.poll();
+ public @Nullable E poll() {
+ final E result = super.poll();
+ if (result != null) {
+ cachedSize.decrement();
+ this.cachedSize.decrement();
+ }
+ return result;
+ }
+
+ @Override
+ public int size() {
+ return cachedSize.intValue();
+ return this.cachedSize.intValue();
+ }
+}

View file

@ -7,7 +7,7 @@ Allows you to access the Gateway being used in a teleport event
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..40bd79fbe30f19bc93e34da52d2b2bf0768be974
index 0000000000000000000000000000000000000000..4488154d3f99f4281b08eef8a44c13fd896e538f
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java
@@ -0,0 +1,32 @@
@ -18,17 +18,18 @@ index 0000000000000000000000000000000000000000..40bd79fbe30f19bc93e34da52d2b2bf0
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when a teleport is triggered for an End Gateway
+ */
+@NullMarked
+public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent {
+
+ @NotNull private final EndGateway gateway;
+ private final EndGateway gateway;
+
+ @ApiStatus.Internal
+ public PlayerTeleportEndGatewayEvent(@NotNull Player player, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) {
+ public PlayerTeleportEndGatewayEvent(final Player player, final Location from, final Location to, final EndGateway gateway) {
+ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY);
+ this.gateway = gateway;
+ }
@ -38,7 +39,6 @@ index 0000000000000000000000000000000000000000..40bd79fbe30f19bc93e34da52d2b2bf0
+ *
+ * @return EndGateway used
+ */
+ @NotNull
+ public EndGateway getGateway() {
+ return this.gateway;
+ }

View file

@ -74,6 +74,20 @@ index 0cf808356a1a5c6fc4bcf97a694ed9beb80a776a..dc765dea47a9a1c1520fb16ddb24f814
* @param z Z-coordinate (0-15)
* @return temperature at given coordinate
*/
diff --git a/src/main/java/org/bukkit/HeightMap.java b/src/main/java/org/bukkit/HeightMap.java
index db6fcd635e295e561642d49941fd8e611247d38e..344b2b5d9207d2645bc5417d1ec00dd0a0b95604 100644
--- a/src/main/java/org/bukkit/HeightMap.java
+++ b/src/main/java/org/bukkit/HeightMap.java
@@ -12,8 +12,7 @@ public enum HeightMap {
*/
MOTION_BLOCKING,
/**
- * The highest block that blocks motion or contains a fluid or is in the
- * {@link Tag#LEAVES}.
+ * The highest block that blocks motion or contains a fluid, excluding leaves.
*/
MOTION_BLOCKING_NO_LEAVES,
/**
diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java
index 62a8bb18855be13ed1c466b4be7afcd3c91dc7aa..de9fd0fadd6d16ffe883a618bf499214878f443d 100644
--- a/src/main/java/org/bukkit/Particle.java
@ -186,10 +200,10 @@ index 9885fd1adc1f93a80d650e6d42dfa3a0b084db9f..c4f2f03ec31998d486dad1d45ef83df3
* <p>
* The {@code radius} is not a rigid square radius. Each structure may alter
diff --git a/src/main/java/org/bukkit/attribute/AttributeModifier.java b/src/main/java/org/bukkit/attribute/AttributeModifier.java
index d66502c9df2592cd18694481e7e90a71a5c3a359..ee39c0b83e558681e8b006172d34c98e2c83cda2 100644
index 6ffc895138088162cab827b3ca6c68961b7bcc64..8c53ac6b4381f3cf8b5e989c8b2a3ba77bd4e475 100644
--- a/src/main/java/org/bukkit/attribute/AttributeModifier.java
+++ b/src/main/java/org/bukkit/attribute/AttributeModifier.java
@@ -117,8 +117,7 @@ public class AttributeModifier implements ConfigurationSerializable, Keyed {
@@ -129,8 +129,7 @@ public class AttributeModifier implements ConfigurationSerializable, Keyed {
}
/**
@ -416,7 +430,7 @@ index 4e1fb0974d061d5bb64899cac576318d2e6f8bf6..539b3527d0c66611e21712f29b90fba9
public int getEntityId();
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
index 274f3ccbc39d4d6ff0665abf334d526317275dd0..a7bfaa874cbd3fc8d24fffe2f7f14594b37fa18c 100644
index 40214a136894270695746ac83fb5f7bcc406f34a..2bb4d2da99d3f0f70e19381c13b43c147c34f944 100644
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
@@ -22,6 +22,11 @@ import org.jetbrains.annotations.Nullable;
@ -444,6 +458,19 @@ index b688b3856cb3068a539fcecfbfa113f8ab4160a9..c275b881cbd11307a6dcc7190d7a7d40
*
* @return whether the item frame is visible or not
*/
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index cafa79f80eec5ec6d8d31d40cc2b46acc06831f9..b0fbad5de65c33710ec46734ad6c69ec9b2769d5 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -502,7 +502,7 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
/**
* Sets the leash on this entity to be held by the supplied entity.
* <p>
- * This method has no effect on EnderDragons, Withers, Players, or Bats.
+ * This method has no effect on players.
* Non-living entities excluding leashes will not persist as leash
* holders.
*
diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java
index f3f62e13cc1b6172808c52f2d5f520f1f584e6db..ad5dbf310fe7b34c997bb339f09697222f862005 100644
--- a/src/main/java/org/bukkit/entity/Mob.java
@ -687,7 +714,7 @@ index be0a2d1f234d8265d98e54e518a994957b1f3ab7..4e3c406ba883aae553e8d69b6b719b87
* than BLOCK_CANBUILD, as this refers to a player, not universe-physics
* rule like cactus on dirt.
diff --git a/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java b/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java
index fc2120e03737f5882d6ae916db93fdcf4939b2ba..f2edd4a9357832e9dec3fb0aafa006335d7b289b 100644
index 035c647f4d4e3c34f171bb7d7fa6b2b7b3442669..7ae338bcecff2ce25939035181457ced505b3a49 100644
--- a/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java
+++ b/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java
@@ -81,7 +81,7 @@ public class PrepareItemEnchantEvent extends InventoryEvent implements Cancellab
@ -999,7 +1026,7 @@ index 9013d043503d175004ad276799e5935b7fa59dc4..ceae092eb782698803c6c3df41267dde
public class InventoryOpenEvent extends InventoryEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
diff --git a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
index 6782024735a885ba0b1b4dba4a576740c1410366..8977f7609431c3c46324a82de84d4a32f4b71c57 100644
index 08a7c564fe5d3d232998d1789d4d4723a59c1430..8a5be3f0322ac19aeac3f00df54add0e73bc87ed 100644
--- a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
+++ b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
@@ -24,6 +24,20 @@ public class PrepareAnvilEvent extends PrepareInventoryResultEvent {
@ -1022,7 +1049,35 @@ index 6782024735a885ba0b1b4dba4a576740c1410366..8977f7609431c3c46324a82de84d4a32
+
@NotNull
@Override
public HandlerList getHandlers() {
public AnvilView getView() {
diff --git a/src/main/java/org/bukkit/event/player/PlayerCommandPreprocessEvent.java b/src/main/java/org/bukkit/event/player/PlayerCommandPreprocessEvent.java
index 48a00fb50fe32c732a578d5179b3bb43ffd68b69..6d7ee2c6e053ea9af9116e7c2adb521f12b914df 100644
--- a/src/main/java/org/bukkit/event/player/PlayerCommandPreprocessEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerCommandPreprocessEvent.java
@@ -106,7 +106,9 @@ public class PlayerCommandPreprocessEvent extends PlayerEvent implements Cancell
*
* @param player New player which this event will execute as
* @throws IllegalArgumentException if the player provided is null
+ * @deprecated Only works for sign commands; use {@link Player#performCommand(String)}, including those cases
*/
+ @Deprecated(forRemoval = true)
public void setPlayer(@NotNull final Player player) throws IllegalArgumentException {
Preconditions.checkArgument(player != null, "Player cannot be null");
this.player = player;
@@ -123,11 +125,10 @@ public class PlayerCommandPreprocessEvent extends PlayerEvent implements Cancell
* unmodifiable set.
*
* @return All Players who will see this chat message
- * @deprecated This method is provided for backward compatibility with no
- * guarantee to the effect of viewing or modifying the set.
+ * @deprecated This is simply the online players. Modifications have no effect
*/
@NotNull
- @Deprecated
+ @Deprecated(forRemoval = true)
public Set<Player> getRecipients() {
return recipients;
}
diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
index e4c32b21ab013703a6a1b07a1ad564d914ebe83f..e58fecf0fe54db06e0e944027923a352fd8005d8 100644
--- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
@ -1430,7 +1485,7 @@ index f1918027c3a8735b31566856218611656b56db20..476fe14faa39f02444cab8ad95d44010
* @return the currently held item
* @see #getItemInMainHand()
diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
index a601bc38e322e5810cf883708541e2d199f09ebb..d89068a37de1dcad0b82dee09cc7829109921a05 100644
index 16c10d75dd28f6bbe843935e8bc91f2bccbd360a..c414ccf03572d48f5c096516fc60a59bb1e8efd7 100644
--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
@@ -24,8 +24,6 @@ public class ShapedRecipe extends CraftingRecipe {
@ -1442,8 +1497,8 @@ index a601bc38e322e5810cf883708541e2d199f09ebb..d89068a37de1dcad0b82dee09cc78291
* @see ShapedRecipe#setIngredient(char, RecipeChoice)
* @deprecated Recipes must have keys. Use {@link #ShapedRecipe(NamespacedKey, ItemStack)}
* instead.
@@ -44,8 +42,6 @@ public class ShapedRecipe extends CraftingRecipe {
* @param result The item you want the recipe to create.
@@ -45,8 +43,6 @@ public class ShapedRecipe extends CraftingRecipe {
* @exception IllegalArgumentException if the {@code result} is an empty item (AIR)
* @see ShapedRecipe#shape(String...)
* @see ShapedRecipe#setIngredient(char, Material)
- * @see ShapedRecipe#setIngredient(char, Material, int)
@ -1452,12 +1507,12 @@ index a601bc38e322e5810cf883708541e2d199f09ebb..d89068a37de1dcad0b82dee09cc78291
*/
public ShapedRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result) {
diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
index 3d50775da447175b2a94ed9056ef36aa1e69c2eb..03839302c94adc3175d0a88065cd230257ffd20d 100644
index bc924ae23fa10d87537aebbfd126aa44f199b65c..b7f46a048633945dc71e8efec9a7ebeed5832fd7 100644
--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
@@ -30,11 +30,8 @@ public class ShapelessRecipe extends CraftingRecipe {
* @param key the unique recipe key
@@ -31,11 +31,8 @@ public class ShapelessRecipe extends CraftingRecipe {
* @param result The item you want the recipe to create.
* @exception IllegalArgumentException if the {@code result} is an empty item (AIR)
* @see ShapelessRecipe#addIngredient(Material)
- * @see ShapelessRecipe#addIngredient(MaterialData)
- * @see ShapelessRecipe#addIngredient(Material,int)
@ -1467,8 +1522,8 @@ index 3d50775da447175b2a94ed9056ef36aa1e69c2eb..03839302c94adc3175d0a88065cd2302
+ * @see ShapelessRecipe#addIngredient(RecipeChoice)
*/
public ShapelessRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result) {
super(key, result);
@@ -174,7 +171,7 @@ public class ShapelessRecipe extends CraftingRecipe {
super(key, checkResult(result));
@@ -175,7 +172,7 @@ public class ShapelessRecipe extends CraftingRecipe {
/**
* Removes multiple instances of an ingredient from the list. If there are
@ -1548,21 +1603,6 @@ index 35c6594fd1040a1af1029e7260e5e3a9307b107d..d58719ee75bef8bc265bfc81bc5d88a4
*/
void addChargedProjectile(@NotNull ItemStack item);
}
diff --git a/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java b/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
index cdbcc8dbab2456cc2bc1f3084cbb1ced1698b7f5..d528b066c2aaa3fb097931914ff2181f8f64e520 100644
--- a/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
+++ b/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
@@ -86,8 +86,8 @@ public interface FireworkMeta extends ItemMeta {
* Sets the approximate power of the firework. Each level of power is half
* a second of flight time.
*
- * @param power the power of the firework, from 0-127
- * @throws IllegalArgumentException if {@literal height<0 or height>127}
+ * @param power the power of the firework, from 0-255
+ * @throws IllegalArgumentException if {@literal power < 0 or power > 255}
*/
void setPower(int power) throws IllegalArgumentException;
diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
index 014c1a0379e532a5c924694a8e0715eb0ba50ec2..10ca843e57c74dfa32d539acd174c8867dfd56ec 100644
--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
@ -1707,6 +1747,32 @@ index b84b37fe27d84574dc5897285f1d9a1437bd322c..281ae60a6be7e39aab4f27b4c7de3d49
*
* @return Set containing all the channels that this client may accept.
*/
diff --git a/src/main/java/org/bukkit/projectiles/ProjectileSource.java b/src/main/java/org/bukkit/projectiles/ProjectileSource.java
index eabd8b926ec1c934cd7e77b7cc6adfae16771021..8557bfefaf02538dec95adb29734ae2cf50f3f8c 100644
--- a/src/main/java/org/bukkit/projectiles/ProjectileSource.java
+++ b/src/main/java/org/bukkit/projectiles/ProjectileSource.java
@@ -12,6 +12,10 @@ public interface ProjectileSource {
/**
* Launches a {@link Projectile} from the ProjectileSource.
+ * <p>
+ * The family of launchProjectile methods only promise the ability to launch projectile types
+ * that the {@link ProjectileSource} is capable of firing in vanilla.
+ * Any other types of projectiles *may* be implemented but are not part of the method contract.
*
* @param <T> a projectile subclass
* @param projectile class of the projectile to launch
@@ -23,6 +27,10 @@ public interface ProjectileSource {
/**
* Launches a {@link Projectile} from the ProjectileSource with an
* initial velocity.
+ * <p>
+ * The family of launchProjectile methods only promise the ability to launch projectile types
+ * that the {@link ProjectileSource} is capable of firing in vanilla.
+ * Any other types of projectiles *may* be implemented but are not part of the method contract.
*
* @param <T> a projectile subclass
* @param projectile class of the projectile to launch
diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java
index 22b1dc5fd4d453161a5ee520072f8e8f955b3a80..a625bcab8e77b05b3341a52c708fae1542b7e3d5 100644
--- a/src/main/java/org/bukkit/scoreboard/Objective.java

View file

@ -6,10 +6,10 @@ Subject: [PATCH] PlayerAttemptPickupItemEvent
diff --git a/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..13e4b1309ea9965a07fc8b276d5a7e606e205824
index 0000000000000000000000000000000000000000..eff29875f6282d8bd04a33cb572c90090742d3b2
--- /dev/null
+++ b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java
@@ -0,0 +1,96 @@
@@ -0,0 +1,94 @@
+package org.bukkit.event.player;
+
+import org.bukkit.entity.Item;
@ -17,16 +17,17 @@ index 0000000000000000000000000000000000000000..13e4b1309ea9965a07fc8b276d5a7e60
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Thrown when a player attempts to pick an item up from the ground
+ */
+@NullMarked
+public class PlayerAttemptPickupItemEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Item item;
+ private final Item item;
+ private final int remaining;
+ private boolean flyAtPlayer = true;
+
@ -34,12 +35,12 @@ index 0000000000000000000000000000000000000000..13e4b1309ea9965a07fc8b276d5a7e60
+
+ @Deprecated // Remove in 1.13 // Remove in 1.14?
+ @ApiStatus.Internal
+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item) {
+ public PlayerAttemptPickupItemEvent(final Player player, final Item item) {
+ this(player, item, 0);
+ }
+
+ @ApiStatus.Internal
+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item, final int remaining) {
+ public PlayerAttemptPickupItemEvent(final Player player, final Item item, final int remaining) {
+ super(player);
+ this.item = item;
+ this.remaining = remaining;
@ -50,7 +51,6 @@ index 0000000000000000000000000000000000000000..13e4b1309ea9965a07fc8b276d5a7e60
+ *
+ * @return Item
+ */
+ @NotNull
+ public Item getItem() {
+ return this.item;
+ }
@ -95,13 +95,11 @@ index 0000000000000000000000000000000000000000..13e4b1309ea9965a07fc8b276d5a7e60
+ this.flyAtPlayer = !cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Add UnknownCommandEvent
diff --git a/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b06a58a76
index 0000000000000000000000000000000000000000..58fe8f60ad5e7ca0ffddebb7ba5748bbfb129ddd
--- /dev/null
+++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java
@@ -0,0 +1,110 @@
@@ -0,0 +1,105 @@
+package org.bukkit.event.command;
+
+import net.kyori.adventure.text.Component;
@ -19,22 +19,23 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Thrown when a player executes a command that is not defined
+ */
+@NullMarked
+public class UnknownCommandEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final CommandSender sender;
+ @NotNull private final String commandLine;
+ @Nullable private Component message;
+ private final CommandSender sender;
+ private final String commandLine;
+ private @Nullable Component message;
+
+ @ApiStatus.Internal
+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final Component message) {
+ public UnknownCommandEvent(final CommandSender sender, final String commandLine, final @Nullable Component message) {
+ super(false);
+ this.sender = sender;
+ this.commandLine = commandLine;
@ -46,7 +47,6 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+ *
+ * @return Sender of the command
+ */
+ @NotNull
+ public CommandSender getSender() {
+ return this.sender;
+ }
@ -56,7 +56,6 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+ *
+ * @return Command sent
+ */
+ @NotNull
+ public String getCommandLine() {
+ return this.commandLine;
+ }
@ -67,9 +66,8 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+ * @return Unknown command message
+ * @deprecated use {@link #message()}
+ */
+ @Nullable
+ @Deprecated
+ public String getMessage() {
+ public @Nullable String getMessage() {
+ return this.message == null ? null : LegacyComponentSerializer.legacySection().serialize(this.message);
+ }
+
@ -91,9 +89,8 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+ *
+ * @return Unknown command message
+ */
+ @Nullable
+ @Contract(pure = true)
+ public Component message() {
+ public @Nullable Component message() {
+ return this.message;
+ }
+
@ -108,13 +105,11 @@ index 0000000000000000000000000000000000000000..9bdeeecdb6021d61fd9141270011e56b
+ this.message = message;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,29 +7,30 @@ Provides basic elements of a PlayerProfile to be used by future API/events
diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c274a1ec4cd
index 0000000000000000000000000000000000000000..324c1cba46c9eef95cc22ffa231b04f9298a5e00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java
@@ -0,0 +1,234 @@
@@ -0,0 +1,246 @@
+package com.destroystokyo.paper.profile;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.UUID;
+
+import java.util.concurrent.CompletableFuture;
+import org.bukkit.profile.PlayerTextures;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents a players profile for the game, such as UUID, Name, and textures.
+ */
+@NullMarked
+public interface PlayerProfile extends org.bukkit.profile.PlayerProfile {
+
+ /**
+ * @return The players name, if set
+ */
+ @Override
+ @Nullable
+ String getName();
+
@ -39,14 +40,14 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ * @param name The new Name
+ * @return The previous Name
+ */
+ @NotNull
+ @Deprecated(forRemoval = true, since = "1.18.1")
+ String setName(@Nullable String name);
+
+ /**
+ * @return The players unique identifier, if set
+ */
+ @Nullable UUID getId();
+ @Nullable
+ UUID getId();
+
+ /**
+ * Sets this profiles UUID
@ -54,8 +55,8 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ * @param uuid The new UUID
+ * @return The previous UUID
+ */
+ @Nullable
+ @Deprecated(forRemoval = true, since = "1.18.1")
+ @Nullable
+ UUID setId(@Nullable UUID uuid);
+
+ /**
@ -65,7 +66,7 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ *
+ * @return the textures, not <code>null</code>
+ */
+ @NotNull
+ @Override
+ PlayerTextures getTextures();
+
+ /**
@ -74,16 +75,18 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ * @param textures the textures to copy, or <code>null</code> to clear the
+ * textures
+ */
+ @Override
+ void setTextures(@Nullable PlayerTextures textures);
+
+ /**
+ * @return A Mutable set of this players properties, such as textures.
+ * Values specified here are subject to implementation details.
+ */
+ @NotNull Set<ProfileProperty> getProperties();
+ Set<ProfileProperty> getProperties();
+
+ /**
+ * Check if the Profile has the specified property
+ *
+ * @param property Property name to check
+ * @return If the property is set
+ */
@ -95,17 +98,19 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ * @param property Property to set.
+ * @throws IllegalArgumentException if setting the property results in more than 16 properties
+ */
+ void setProperty(@NotNull ProfileProperty property);
+ void setProperty(ProfileProperty property);
+
+ /**
+ * Sets multiple properties. If any of the set properties already exist, it will be replaced
+ *
+ * @param properties The properties to set
+ * @throws IllegalArgumentException if the number of properties exceeds 16
+ */
+ void setProperties(@NotNull Collection<ProfileProperty> properties);
+ void setProperties(Collection<ProfileProperty> properties);
+
+ /**
+ * Removes a specific property from this profile
+ *
+ * @param property The property to remove
+ * @return If a property was removed
+ */
@ -113,22 +118,24 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+
+ /**
+ * Removes a specific property from this profile
+ *
+ * @param property The property to remove
+ * @return If a property was removed
+ */
+ default boolean removeProperty(@NotNull ProfileProperty property) {
+ return removeProperty(property.getName());
+ default boolean removeProperty(final ProfileProperty property) {
+ return this.removeProperty(property.getName());
+ }
+
+ /**
+ * Removes all properties in the collection
+ *
+ * @param properties The properties to remove
+ * @return If any property was removed
+ */
+ default boolean removeProperties(@NotNull Collection<ProfileProperty> properties) {
+ default boolean removeProperties(final Collection<ProfileProperty> properties) {
+ boolean removed = false;
+ for (ProfileProperty property : properties) {
+ if (removeProperty(property)) {
+ for (final ProfileProperty property : properties) {
+ if (this.removeProperty(property)) {
+ removed = true;
+ }
+ }
@ -143,6 +150,7 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ /**
+ * @return If the profile is now complete (has UUID and Name)
+ */
+ @Override
+ boolean isComplete();
+
+ /**
@ -175,21 +183,23 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ /**
+ * If this profile is not complete, then make the API call to complete it.
+ * This is a blocking operation and should be done asynchronously.
+ *
+ * <p>
+ * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}}
+ *
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
+ */
+ default boolean complete() {
+ return complete(true);
+ return this.complete(true);
+ }
+
+ /**
+ * If this profile is not complete, then make the API call to complete it.
+ * This is a blocking operation and should be done asynchronously.
+ *
+ * <p>
+ * Optionally will also fill textures.
+ *
+ * <p>
+ * Online mode will be automatically determined
+ *
+ * @param textures controls if we should fill the profile with texture properties
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
+ */
@ -198,8 +208,9 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ /**
+ * If this profile is not complete, then make the API call to complete it.
+ * This is a blocking operation and should be done asynchronously.
+ *
+ * <p>
+ * Optionally will also fill textures.
+ *
+ * @param textures controls if we should fill the profile with texture properties
+ * @param onlineMode Treat this server as online mode or not
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
@ -235,43 +246,45 @@ index 0000000000000000000000000000000000000000..b4f9ffbebab8eef99dbd81c816c16c27
+ * </pre>
+ */
+ @Override
+ @NotNull CompletableFuture<PlayerProfile> update();
+ CompletableFuture<PlayerProfile> update();
+
+ /**
+ * Whether this Profile has textures associated to it
+ *
+ * @return If it has a textures property
+ */
+ default boolean hasTextures() {
+ return hasProperty("textures");
+ return this.hasProperty("textures");
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f913a078dd692a9feafb98a6e6c9583f3253bd4
index 0000000000000000000000000000000000000000..35341d8f1ac2d80f339084ef80d099a545027554
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java
@@ -0,0 +1,75 @@
@@ -0,0 +1,73 @@
+package com.destroystokyo.paper.profile;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Objects;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents a property on a {@link PlayerProfile}
+ */
+public class ProfileProperty {
+@NullMarked
+public final class ProfileProperty {
+
+ private final String name;
+ private final String value;
+ private final String signature;
+ private final @Nullable String signature;
+
+ public ProfileProperty(@NotNull String name, @NotNull String value) {
+ public ProfileProperty(final String name, final String value) {
+ this(name, value, null);
+ }
+
+ public ProfileProperty(@NotNull String name, @NotNull String value, @Nullable String signature) {
+ public ProfileProperty(final String name, final String value, final @Nullable String signature) {
+ this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null");
+ this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null");
+ this.signature = signature;
@ -283,25 +296,22 @@ index 0000000000000000000000000000000000000000..8f913a078dd692a9feafb98a6e6c9583
+ /**
+ * @return The property name, ie "textures"
+ */
+ @NotNull
+ public String getName() {
+ return name;
+ return this.name;
+ }
+
+ /**
+ * @return The property value, likely to be base64 encoded
+ */
+ @NotNull
+ public String getValue() {
+ return value;
+ return this.value;
+ }
+
+ /**
+ * @return A signature from Mojang for signed properties
+ */
+ @Nullable
+ public String getSignature() {
+ return signature;
+ public @Nullable String getSignature() {
+ return this.signature;
+ }
+
+ /**
@ -312,18 +322,18 @@ index 0000000000000000000000000000000000000000..8f913a078dd692a9feafb98a6e6c9583
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ public boolean equals(final @Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ProfileProperty that = (ProfileProperty) o;
+ return Objects.equals(name, that.name) &&
+ Objects.equals(value, that.value) &&
+ Objects.equals(signature, that.signature);
+ if (o == null || this.getClass() != o.getClass()) return false;
+ final ProfileProperty that = (ProfileProperty) o;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.value, that.value) &&
+ Objects.equals(this.signature, that.signature);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ return Objects.hash(this.name);
+ }
+}
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Shoulder Entities Release API
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
index a7bfaa874cbd3fc8d24fffe2f7f14594b37fa18c..8cc6f8547380d567aef7910ef309193bd79ced09 100644
index 2bb4d2da99d3f0f70e19381c13b43c147c34f944..b8431d9722ef9fce0ac9e18367abef22717997ca 100644
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
@@ -335,6 +335,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
@@ -346,6 +346,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
*/
public int getExpToLevel();

View file

@ -8,19 +8,18 @@ profiles that had to be looked up.
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ad2782aafe76f8b10565c0f0419d6b9c665b267
index 0000000000000000000000000000000000000000..9e8ae0ab13cac9a260c9959eb6bf5b93a3c15018
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java
@@ -0,0 +1,48 @@
@@ -0,0 +1,45 @@
+package com.destroystokyo.paper.event.profile;
+
+import com.destroystokyo.paper.profile.PlayerProfile;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Allows a plugin to be notified anytime AFTER a Profile has been looked up from the Mojang API
@ -29,14 +28,15 @@ index 0000000000000000000000000000000000000000..2ad2782aafe76f8b10565c0f0419d6b9
+ * No guarantees are made about thread execution context for this event. If you need to know, check
+ * {@link Event#isAsynchronous()}
+ */
+@NullMarked
+public class LookupProfileEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final PlayerProfile profile;
+ private final PlayerProfile profile;
+
+ @ApiStatus.Internal
+ public LookupProfileEvent(@NotNull PlayerProfile profile) {
+ public LookupProfileEvent(final PlayerProfile profile) {
+ super(!Bukkit.isPrimaryThread());
+ this.profile = profile;
+ }
@ -44,41 +44,37 @@ index 0000000000000000000000000000000000000000..2ad2782aafe76f8b10565c0f0419d6b9
+ /**
+ * @return The profile that was recently looked up. This profile can be mutated
+ */
+ @NotNull
+ public PlayerProfile getPlayerProfile() {
+ return this.profile;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533dfa474356
index 0000000000000000000000000000000000000000..07416cc9e2b8156be2cc92d6d974b881b427fd99
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java
@@ -0,0 +1,112 @@
@@ -0,0 +1,107 @@
+package com.destroystokyo.paper.event.profile;
+
+import com.destroystokyo.paper.profile.ProfileProperty;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Allows a plugin to intercept a Profile Lookup for a Profile by name
@ -90,17 +86,18 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ * No guarantees are made about thread execution context for this event. If you need to know, check
+ * {@link Event#isAsynchronous()}
+ */
+@NullMarked
+public class PreLookupProfileEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final String name;
+ private final String name;
+
+ private UUID uuid;
+ @NotNull private Set<ProfileProperty> properties = new HashSet<>();
+ private @Nullable UUID uuid;
+ private Set<ProfileProperty> properties = new HashSet<>();
+
+ @ApiStatus.Internal
+ public PreLookupProfileEvent(@NotNull String name) {
+ public PreLookupProfileEvent(final String name) {
+ super(!Bukkit.isPrimaryThread());
+ this.name = name;
+ }
@ -108,7 +105,6 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ /**
+ * @return Name of the profile
+ */
+ @NotNull
+ public String getName() {
+ return this.name;
+ }
@ -120,8 +116,7 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ *
+ * @return The UUID of the profile if it has already been provided by a plugin
+ */
+ @Nullable
+ public UUID getUUID() {
+ public @Nullable UUID getUUID() {
+ return this.uuid;
+ }
+
@ -132,7 +127,7 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ *
+ * @param uuid the UUID to set for the profile or {@code null} to reset
+ */
+ public void setUUID(@Nullable UUID uuid) {
+ public void setUUID(final @Nullable UUID uuid) {
+ this.uuid = uuid;
+ }
+
@ -140,7 +135,6 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ * @return The currently pending pre-populated properties.
+ * Any property in this Set will be automatically prefilled on this Profile
+ */
+ @NotNull
+ public Set<ProfileProperty> getProfileProperties() {
+ return this.properties;
+ }
@ -151,7 +145,7 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ *
+ * @param properties The properties to add
+ */
+ public void setProfileProperties(@NotNull Set<ProfileProperty> properties) {
+ public void setProfileProperties(final Set<ProfileProperty> properties) {
+ this.properties = new HashSet<>();
+ this.properties.addAll(properties);
+ }
@ -162,17 +156,15 @@ index 0000000000000000000000000000000000000000..3f73ec52f9b581001bef3a19a5f1533d
+ *
+ * @param properties The properties to add
+ */
+ public void addProfileProperties(@NotNull Set<ProfileProperty> properties) {
+ public void addProfileProperties(final Set<ProfileProperty> properties) {
+ this.properties.addAll(properties);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -8,14 +8,16 @@ and access their saddle state separately from an interface shared with Armor.
diff --git a/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java
new file mode 100644
index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb6a56950d
index 0000000000000000000000000000000000000000..994f34ac2062c092c2b4e5ff364067482d19588c
--- /dev/null
+++ b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java
@@ -0,0 +1,21 @@
@@ -0,0 +1,22 @@
+package org.bukkit.inventory;
+
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+public interface ArmoredHorseInventory extends AbstractHorseInventory {
+
+ /**
@ -23,8 +25,7 @@ index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb
+ *
+ * @return the armor item
+ */
+ @Nullable
+ ItemStack getArmor();
+ @Nullable ItemStack getArmor();
+
+ /**
+ * Sets the item in the horse's armor slot.
@ -74,10 +75,14 @@ index 2fa2c9d07ecbafaf2396d913af90f1f4d432b238..5ac1afb8a213fa0fe344db4730ecbc5d
* Gets the item in the llama's decor slot.
diff --git a/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7944f26a3e2a92601c3be0e55c00c39cc16cf177
index 0000000000000000000000000000000000000000..0f508a8df87f1e23764152d00e02a3da5131f034
--- /dev/null
+++ b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java
@@ -0,0 +1,3 @@
@@ -0,0 +1,7 @@
+package org.bukkit.inventory;
+
+public interface SaddledHorseInventory extends AbstractHorseInventory {}
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public interface SaddledHorseInventory extends AbstractHorseInventory {
+}

View file

@ -9,10 +9,10 @@ Allows you to do dynamic whitelisting and change of kick message
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab8133478f7c6
index 0000000000000000000000000000000000000000..901efb61fdc02b3228cc25649926d691c4617512
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java
@@ -0,0 +1,147 @@
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017 - Daniel Ennis (Aikar) - MIT License
+ *
@ -44,8 +44,9 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Contract;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Fires when the server needs to verify if a player is whitelisted.
@ -53,24 +54,25 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+ * Plugins may override/control the servers whitelist with this event,
+ * and dynamically change the kick message.
+ */
+@NullMarked
+public class ProfileWhitelistVerifyEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final PlayerProfile profile;
+ private final PlayerProfile profile;
+ private final boolean whitelistEnabled;
+ private final boolean isOp;
+ private boolean whitelisted;
+ @Nullable private Component kickMessage;
+ private @Nullable Component kickMessage;
+
+ @Deprecated
+ @ApiStatus.Internal
+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable String kickMessage) {
+ public ProfileWhitelistVerifyEvent(final PlayerProfile profile, final boolean whitelistEnabled, final boolean whitelisted, final boolean isOp, final @Nullable String kickMessage) {
+ this(profile, whitelistEnabled, whitelisted, isOp, kickMessage == null ? null : LegacyComponentSerializer.legacySection().deserialize(kickMessage));
+ }
+
+ @ApiStatus.Internal
+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable Component kickMessage) {
+ public ProfileWhitelistVerifyEvent(final PlayerProfile profile, final boolean whitelistEnabled, final boolean whitelisted, final boolean isOp, final @Nullable Component kickMessage) {
+ this.profile = profile;
+ this.whitelistEnabled = whitelistEnabled;
+ this.whitelisted = whitelisted;
@ -83,8 +85,7 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+ * @deprecated use {@link #kickMessage()}
+ */
+ @Deprecated
+ @Nullable
+ public String getKickMessage() {
+ public @Nullable String getKickMessage() {
+ return this.kickMessage == null ? null : LegacyComponentSerializer.legacySection().serialize(this.kickMessage);
+ }
+
@ -93,35 +94,34 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+ * @deprecated Use {@link #kickMessage(Component)}
+ */
+ @Deprecated
+ public void setKickMessage(@Nullable String kickMessage) {
+ public void setKickMessage(final @Nullable String kickMessage) {
+ this.kickMessage(kickMessage == null ? null : LegacyComponentSerializer.legacySection().deserialize(kickMessage));
+ }
+
+ /**
+ * @return the currently planned message to send to the user if they are not whitelisted
+ */
+ @Nullable
+ public Component kickMessage() {
+ @Contract(pure = true)
+ public @Nullable Component kickMessage() {
+ return this.kickMessage;
+ }
+
+ /**
+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to {@code null} to use the server configured default
+ */
+ public void kickMessage(@Nullable Component kickMessage) {
+ public void kickMessage(final @Nullable Component kickMessage) {
+ this.kickMessage = kickMessage;
+ }
+
+ /**
+ * @return The profile of the player trying to connect
+ */
+ @NotNull
+ public PlayerProfile getPlayerProfile() {
+ return this.profile;
+ }
+
+ /**
+ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why its true)
+ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why it's true)
+ */
+ public boolean isWhitelisted() {
+ return this.whitelisted;
@ -129,9 +129,10 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+
+ /**
+ * Changes the players whitelisted state. {@code false} will deny the login
+ *
+ * @param whitelisted The new whitelisted state
+ */
+ public void setWhitelisted(boolean whitelisted) {
+ public void setWhitelisted(final boolean whitelisted) {
+ this.whitelisted = whitelisted;
+ }
+
@ -149,13 +150,11 @@ index 0000000000000000000000000000000000000000..52959c2d19c5b73ccd85afce6b2ab813
+ return this.whitelistEnabled;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -14,7 +14,7 @@ it without having to shade it in the plugin and going through
several layers of logging abstraction.
diff --git a/build.gradle.kts b/build.gradle.kts
index 258d7010d24c529c9bbc76cc26adf226c641ee58..4da053d427f3f9c5e7fc144408836ebef80026c6 100644
index 3c50362de25617d878ef58f14f67c240005ff624..76aa23da778b0fe8a093429c56cb29b044359b40 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,6 +12,8 @@ java {
@ -35,7 +35,7 @@ index 258d7010d24c529c9bbc76cc26adf226c641ee58..4da053d427f3f9c5e7fc144408836ebe
implementation("org.ow2.asm:asm:9.7")
implementation("org.ow2.asm:asm-commons:9.7")
@@ -138,6 +142,8 @@ tasks.withType<Javadoc> {
@@ -140,6 +144,8 @@ tasks.withType<Javadoc> {
"https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
@ -45,7 +45,7 @@ index 258d7010d24c529c9bbc76cc26adf226c641ee58..4da053d427f3f9c5e7fc144408836ebe
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper
)
diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java
index 8c76716249e44ed8bf6be94c1f5c7b6d9bb35be2..4eb639fbb46a0848be207149ea433455550fae1c 100644
index 68a0ed5f0ed25e98f4ab4d1e482ec2ccfda9cd3a..46fc37a36403c8fbc4c0c9f863d4d57eb3896bd4 100644
--- a/src/main/java/org/bukkit/plugin/Plugin.java
+++ b/src/main/java/org/bukkit/plugin/Plugin.java
@@ -198,6 +198,22 @@ public interface Plugin extends TabExecutor {

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Add PlayerJumpEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272ad3a67b6f
index 0000000000000000000000000000000000000000..1d07c3d6bf3b9283371ca45698178979113085fa
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java
@@ -0,0 +1,106 @@
@@ -0,0 +1,105 @@
+package com.destroystokyo.paper.event.player;
+
+import com.google.common.base.Preconditions;
@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called when the server detects the player is jumping.
@ -29,17 +29,18 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ * when checking for jumps via {@link PlayerMoveEvent}, this event is fired whenever
+ * the server detects that the player is jumping.
+ */
+@NullMarked
+public class PlayerJumpEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Location to;
+ @NotNull private Location from;
+ private final Location to;
+ private Location from;
+
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) {
+ public PlayerJumpEvent(final Player player, final Location from, final Location to) {
+ super(player);
+ this.from = from;
+ this.to = to;
@ -54,6 +55,7 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ *
+ * @return {@code true} if this event is cancelled
+ */
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
@ -67,7 +69,8 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ *
+ * @param cancel {@code true} if you wish to cancel this event
+ */
+ public void setCancelled(boolean cancel) {
+ @Override
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
@ -76,7 +79,6 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ *
+ * @return Location the player jumped from
+ */
+ @NotNull
+ public Location getFrom() {
+ return this.from;
+ }
@ -86,7 +88,7 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ *
+ * @param from New location to mark as the players previous location
+ */
+ public void setFrom(@NotNull Location from) {
+ public void setFrom(final Location from) {
+ Preconditions.checkArgument(from != null, "Cannot use null from location!");
+ Preconditions.checkArgument(from.getWorld() != null, "Cannot use from location with null world!");
+ this.from = from;
@ -100,18 +102,15 @@ index 0000000000000000000000000000000000000000..8c2fd2c1120d634052f9bc345365272a
+ *
+ * @return Location the player jumped to
+ */
+ @NotNull
+ public Location getTo() {
+ return this.to.clone();
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -14,33 +14,31 @@ parent of the plugin logger to avoid this.
diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d90a18f9f8
index 0000000000000000000000000000000000000000..c78a359566a11904d2dd41098ced556a91a7fa36
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java
@@ -0,0 +1,48 @@
@@ -0,0 +1,46 @@
+package com.destroystokyo.paper.utils;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import org.bukkit.plugin.PluginDescriptionFile;
+
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import org.jetbrains.annotations.NotNull;
+import org.bukkit.plugin.PluginDescriptionFile;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger.
+ */
+@NullMarked
+public class PaperPluginLogger extends Logger {
+
+ @Deprecated(forRemoval = true)
+ @NotNull
+ public static Logger getLogger(@NotNull PluginDescriptionFile description) {
+ public static Logger getLogger(final PluginDescriptionFile description) {
+ return getLogger((PluginMeta) description);
+ }
+
+ @NotNull
+ public static Logger getLogger(@NotNull PluginMeta meta) {
+ public static Logger getLogger(final PluginMeta meta) {
+ Logger logger = new PaperPluginLogger(meta);
+ if (!LogManager.getLogManager().addLogger(logger)) {
+ // Disable this if it's going to happen across reloads anyways...
@ -51,14 +49,14 @@ index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d9
+ return logger;
+ }
+
+ private PaperPluginLogger(@NotNull PluginMeta meta) {
+ private PaperPluginLogger(final PluginMeta meta) {
+ super(meta.getLoggerPrefix() != null ? meta.getLoggerPrefix() : meta.getName(), null);
+ }
+
+ @Override
+ public void setParent(@NotNull Logger parent) {
+ if (getParent() != null) {
+ warning("Ignoring attempt to change parent of plugin logger");
+ public void setParent(final Logger parent) {
+ if (this.getParent() != null) {
+ this.warning("Ignoring attempt to change parent of plugin logger");
+ } else {
+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent);
+ super.setParent(parent);
@ -67,7 +65,7 @@ index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d9
+
+}
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
index f81e335a4e533221529355bec2f5d588aa79e60c..d359ea9b02952f981b9cf9d778c56eb995454c60 100644
index 801578de8599d6b546cde63b3f2655fab48eee03..2d64fc065d53dcd8c01d05215c3e63aaf4428177 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
@@ -292,10 +292,10 @@ public abstract class JavaPlugin extends PluginBase {

View file

@ -6,22 +6,21 @@ Subject: [PATCH] Add PlayerArmorChangeEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180b335bf20
index 0000000000000000000000000000000000000000..c7cc612ec81b0c7da6ee6676167e047e69347966
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java
@@ -0,0 +1,127 @@
@@ -0,0 +1,120 @@
+package com.destroystokyo.paper.event.player;
+
+import java.util.Set;
+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.Set;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+import static org.bukkit.Material.*;
+
@ -30,16 +29,17 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ * <p>
+ * Not currently called for environmental factors though it <strong>MAY BE IN THE FUTURE</strong>
+ */
+@NullMarked
+public class PlayerArmorChangeEvent extends PlayerEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final SlotType slotType;
+ @NotNull private final ItemStack oldItem;
+ @NotNull private final ItemStack newItem;
+ private final SlotType slotType;
+ private final ItemStack oldItem;
+ private final ItemStack newItem;
+
+ @ApiStatus.Internal
+ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @NotNull ItemStack oldItem, @NotNull ItemStack newItem) {
+ public PlayerArmorChangeEvent(final Player player, final SlotType slotType, final ItemStack oldItem, final ItemStack newItem) {
+ super(player);
+ this.slotType = slotType;
+ this.oldItem = oldItem;
@ -51,7 +51,6 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ *
+ * @return type of slot being altered
+ */
+ @NotNull
+ public SlotType getSlotType() {
+ return this.slotType;
+ }
@ -61,7 +60,6 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ *
+ * @return old item
+ */
+ @NotNull
+ public ItemStack getOldItem() {
+ return this.oldItem;
+ }
@ -71,18 +69,15 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ *
+ * @return new item
+ */
+ @NotNull
+ public ItemStack getNewItem() {
+ return this.newItem;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
@ -95,7 +90,7 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+
+ private final Set<Material> types;
+
+ SlotType(Material... types) {
+ SlotType(final Material... types) {
+ this.types = Set.of(types);
+ }
+
@ -105,7 +100,6 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ *
+ * @return immutable set of material types
+ */
+ @NotNull
+ public Set<Material> getTypes() {
+ return this.types;
+ }
@ -116,9 +110,8 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ * @param material material to get slot by
+ * @return slot type the material will go in, or {@code null} if it won't
+ */
+ @Nullable
+ public static SlotType getByMaterial(@NotNull Material material) {
+ for (SlotType slotType : values()) {
+ public static @Nullable SlotType getByMaterial(final Material material) {
+ for (final SlotType slotType : values()) {
+ if (slotType.getTypes().contains(material)) {
+ return slotType;
+ }
@ -132,7 +125,7 @@ index 0000000000000000000000000000000000000000..ab08219497f7e362f113321c4bcfd180
+ * @param material material to check
+ * @return whether this material can be equipped
+ */
+ public static boolean isEquipable(@NotNull Material material) {
+ public static boolean isEquipable(final Material material) {
+ return getByMaterial(material) != null;
+ }
+ }

View file

@ -11,14 +11,16 @@ and avoid going to main for tab completions.
Especially useful if you need to query a database in order to obtain the results for tab
completion, such as offline players.
Also Enforces mutability of the existing TabCompleteEvent.
Co-authored-by: Aikar <aikar@aikar.co>
diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98d2e9595f
index 0000000000000000000000000000000000000000..0482ecf5b84ba8e0260679049f384f3449bbe7b5
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java
@@ -0,0 +1,339 @@
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
+ *
@ -46,6 +48,10 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+
+import com.google.common.base.Preconditions;
+import io.papermc.paper.util.TransformingRandomAccessList;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+import net.kyori.adventure.text.Component;
+import net.kyori.examination.Examinable;
+import net.kyori.examination.ExaminableProperty;
@ -56,14 +62,9 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Allows plugins to compute tab completion results asynchronously.
@ -74,15 +75,15 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ * <p>
+ * Only 1 process will be allowed to provide completions, the Async Event, or the standard process.
+ */
+@NullMarked
+public class AsyncTabCompleteEvent extends Event implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final CommandSender sender;
+ @NotNull private final String buffer;
+ private final CommandSender sender;
+ private final String buffer;
+ private final boolean isCommand;
+ @Nullable
+ private final Location location;
+ private final @Nullable Location location;
+ private final List<Completion> completions = new ArrayList<>();
+ private final List<String> stringCompletions = new TransformingRandomAccessList<>(
+ this.completions,
@ -93,7 +94,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, boolean isCommand, @Nullable Location loc) {
+ public AsyncTabCompleteEvent(final CommandSender sender, final String buffer, final boolean isCommand, final @Nullable Location loc) {
+ super(true);
+ this.sender = sender;
+ this.buffer = buffer;
@ -103,7 +104,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+
+ @Deprecated
+ @ApiStatus.Internal
+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List<String> completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) {
+ public AsyncTabCompleteEvent(final CommandSender sender, final List<String> completions, final String buffer, final boolean isCommand, final @Nullable Location loc) {
+ super(true);
+ this.sender = sender;
+ this.completions.addAll(fromStrings(completions));
@ -117,7 +118,6 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @return the {@link CommandSender} instance
+ */
+ @NotNull
+ public CommandSender getSender() {
+ return this.sender;
+ }
@ -132,7 +132,6 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @return a list of offered completions
+ */
+ @NotNull
+ public List<String> getCompletions() {
+ return this.stringCompletions;
+ }
@ -147,7 +146,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @param completions the new completions
+ */
+ public void setCompletions(@NotNull List<String> completions) {
+ public void setCompletions(final List<String> completions) {
+ Preconditions.checkArgument(completions != null, "Completions list cannot be null");
+ if (completions == this.stringCompletions) {
+ return;
@ -166,7 +165,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @return a list of offered completions
+ */
+ public @NotNull List<Completion> completions() {
+ public List<Completion> completions() {
+ return this.completions;
+ }
+
@ -180,7 +179,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @param newCompletions the new completions
+ */
+ public void completions(final @NotNull List<Completion> newCompletions) {
+ public void completions(final List<Completion> newCompletions) {
+ Preconditions.checkArgument(newCompletions != null, "new completions cannot be null");
+ this.completions.clear();
+ this.completions.addAll(newCompletions);
@ -191,7 +190,6 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @return command buffer, as entered
+ */
+ @NotNull
+ public String getBuffer() {
+ return this.buffer;
+ }
@ -206,8 +204,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ /**
+ * @return The position looked at by the sender, or {@code null} if none
+ */
+ @Nullable
+ public Location getLocation() {
+ public @Nullable Location getLocation() {
+ return this.location != null ? this.location.clone() : null;
+ }
+
@ -228,7 +225,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @param handled if this completion should be marked as being handled
+ */
+ public void setHandled(boolean handled) {
+ public void setHandled(final boolean handled) {
+ this.handled = handled;
+ }
+
@ -243,21 +240,20 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ * Will provide no completions, and will not fire the synchronous process
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
+ private static @NotNull List<Completion> fromStrings(final @NotNull List<String> suggestions) {
+ private static List<Completion> fromStrings(final List<String> suggestions) {
+ final List<Completion> list = new ArrayList<>(suggestions.size());
+ for (final String suggestion : suggestions) {
+ list.add(new CompletionImpl(suggestion, null));
@ -275,7 +271,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ *
+ * @return suggestion string
+ */
+ @NotNull String suggestion();
+ String suggestion();
+
+ /**
+ * Get the suggestion tooltip for this {@link Completion}.
@ -285,7 +281,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ @Nullable Component tooltip();
+
+ @Override
+ default @NotNull Stream<? extends ExaminableProperty> examinableProperties() {
+ default Stream<? extends ExaminableProperty> examinableProperties() {
+ return Stream.of(ExaminableProperty.of("suggestion", this.suggestion()), ExaminableProperty.of("tooltip", this.tooltip()));
+ }
+
@ -295,7 +291,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ * @param suggestion suggestion string
+ * @return new completion instance
+ */
+ static @NotNull Completion completion(final @NotNull String suggestion) {
+ static Completion completion(final String suggestion) {
+ return new CompletionImpl(suggestion, null);
+ }
+
@ -308,7 +304,7 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ * @param tooltip tooltip component, or {@code null}
+ * @return new completion instance
+ */
+ static @NotNull Completion completion(final @NotNull String suggestion, final @Nullable Component tooltip) {
+ static Completion completion(final String suggestion, final @Nullable Component tooltip) {
+ return new CompletionImpl(suggestion, tooltip);
+ }
+ }
@ -317,15 +313,15 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ static final class CompletionImpl implements Completion {
+
+ private final String suggestion;
+ private final Component tooltip;
+ private final @Nullable Component tooltip;
+
+ CompletionImpl(final @NotNull String suggestion, final @Nullable Component tooltip) {
+ CompletionImpl(final String suggestion, final @Nullable Component tooltip) {
+ this.suggestion = suggestion;
+ this.tooltip = tooltip;
+ }
+
+ @Override
+ public @NotNull String suggestion() {
+ public String suggestion() {
+ return this.suggestion;
+ }
+
@ -353,22 +349,19 @@ index 0000000000000000000000000000000000000000..8965974988ad20fbe1d45885f20a3a98
+ }
+
+ @Override
+ public @NotNull String toString() {
+ public String toString() {
+ return StringExaminer.simpleEscaping().examine(this);
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276118c1c7b
index 0000000000000000000000000000000000000000..488250fdcdc93ca1aba5042f63fb6286db518014
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java
@@ -0,0 +1,169 @@
@@ -0,0 +1,172 @@
+package io.papermc.paper.util;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.AbstractList;
+import java.util.Iterator;
+import java.util.List;
@ -376,6 +369,8 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+import java.util.RandomAccess;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
@ -385,7 +380,10 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ * @param <F> backing list element type
+ * @param <T> transformed list element type
+ */
+@NullMarked
+@ApiStatus.Internal
+public final class TransformingRandomAccessList<F, T> extends AbstractList<T> implements RandomAccess {
+
+ final List<F> fromList;
+ final Function<? super F, ? extends T> toFunction;
+ final Function<? super T, ? extends F> fromFunction;
@ -393,14 +391,14 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ /**
+ * Create a new {@link TransformingRandomAccessList}.
+ *
+ * @param fromList backing list
+ * @param toFunction function mapping backing list element type to transformed list element type
+ * @param fromList backing list
+ * @param toFunction function mapping backing list element type to transformed list element type
+ * @param fromFunction function mapping transformed list element type to backing list element type
+ */
+ public TransformingRandomAccessList(
+ final @NonNull List<F> fromList,
+ final @NonNull Function<? super F, ? extends T> toFunction,
+ final @NonNull Function<? super T, ? extends F> fromFunction
+ final List<F> fromList,
+ final Function<? super F, ? extends T> toFunction,
+ final Function<? super T, ? extends F> fromFunction
+ ) {
+ this.fromList = checkNotNull(fromList);
+ this.toFunction = checkNotNull(toFunction);
@ -413,25 +411,25 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ }
+
+ @Override
+ public T get(int index) {
+ public T get(final int index) {
+ return this.toFunction.apply(this.fromList.get(index));
+ }
+
+ @Override
+ public @NotNull Iterator<T> iterator() {
+ public Iterator<T> iterator() {
+ return this.listIterator();
+ }
+
+ @Override
+ public @NotNull ListIterator<T> listIterator(int index) {
+ return new TransformedListIterator<F, T>(this.fromList.listIterator(index)) {
+ public ListIterator<T> listIterator(final int index) {
+ return new TransformedListIterator<>(this.fromList.listIterator(index)) {
+ @Override
+ T transform(F from) {
+ T transform(final F from) {
+ return TransformingRandomAccessList.this.toFunction.apply(from);
+ }
+
+ @Override
+ F transformBack(T from) {
+ F transformBack(final T from) {
+ return TransformingRandomAccessList.this.fromFunction.apply(from);
+ }
+ };
@ -443,13 +441,13 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ }
+
+ @Override
+ public boolean removeIf(Predicate<? super T> filter) {
+ public boolean removeIf(final Predicate<? super T> filter) {
+ checkNotNull(filter);
+ return this.fromList.removeIf(element -> filter.test(this.toFunction.apply(element)));
+ }
+
+ @Override
+ public T remove(int index) {
+ public T remove(final int index) {
+ return this.toFunction.apply(this.fromList.remove(index));
+ }
+
@ -459,19 +457,20 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ }
+
+ @Override
+ public T set(int i, T t) {
+ public T set(final int i, final T t) {
+ return this.toFunction.apply(this.fromList.set(i, this.fromFunction.apply(t)));
+ }
+
+ @Override
+ public void add(int i, T t) {
+ public void add(final int i, final T t) {
+ this.fromList.add(i, this.fromFunction.apply(t));
+ }
+
+ static abstract class TransformedListIterator<F, T> implements ListIterator<T>, Iterator<T> {
+ abstract static class TransformedListIterator<F, T> implements ListIterator<T>, Iterator<T> {
+
+ final Iterator<F> backingIterator;
+
+ TransformedListIterator(ListIterator<F> backingIterator) {
+ TransformedListIterator(final ListIterator<F> backingIterator) {
+ this.backingIterator = checkNotNull((Iterator<F>) backingIterator);
+ }
+
@ -479,7 +478,7 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ return cast(this.backingIterator);
+ }
+
+ static <A> ListIterator<A> cast(Iterator<A> iterator) {
+ static <A> ListIterator<A> cast(final Iterator<A> iterator) {
+ return (ListIterator<A>) iterator;
+ }
+
@ -504,12 +503,12 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ }
+
+ @Override
+ public void set(T element) {
+ public void set(final T element) {
+ this.backingIterator().set(this.transformBack(element));
+ }
+
+ @Override
+ public void add(T element) {
+ public void add(final T element) {
+ this.backingIterator().add(this.transformBack(element));
+ }
+
@ -534,10 +533,10 @@ index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276
+ }
+}
diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
index 270e6d8ad4358baa256cee5f16cff281f063ce3b..b43c3cb5c88eada186d6f81712c244aaa18fb53e 100644
index 270e6d8ad4358baa256cee5f16cff281f063ce3b..6465e290c090d82986352d5ab7ba5dc65bd3dc17 100644
--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
@@ -29,6 +29,13 @@ public class TabCompleteEvent extends Event implements Cancellable {
@@ -29,13 +29,20 @@ public class TabCompleteEvent extends Event implements Cancellable {
private boolean cancelled;
public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List<String> completions) {
@ -551,6 +550,14 @@ index 270e6d8ad4358baa256cee5f16cff281f063ce3b..b43c3cb5c88eada186d6f81712c244aa
Preconditions.checkArgument(sender != null, "sender");
Preconditions.checkArgument(buffer != null, "buffer");
Preconditions.checkArgument(completions != null, "completions");
this.sender = sender;
this.buffer = buffer;
- this.completions = completions;
+ this.completions = new java.util.ArrayList<>(completions); // Paper - Completions must be mutable
}
/**
@@ -69,14 +76,35 @@ public class TabCompleteEvent extends Event implements Cancellable {
return completions;
}
@ -584,12 +591,12 @@ index 270e6d8ad4358baa256cee5f16cff281f063ce3b..b43c3cb5c88eada186d6f81712c244aa
public void setCompletions(@NotNull List<String> completions) {
Preconditions.checkArgument(completions != null);
- this.completions = completions;
+ this.completions = new java.util.ArrayList<>(completions); // Paper
+ this.completions = new java.util.ArrayList<>(completions); // Paper - completions must be mutable
}
@Override
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
index d9091ba1e5a55e03adca98305233cce9d6888609..b82f07a2879412f6b30643ca93a97439aa49a98a 100644
index 7ff939ea41417bad3a436a87c89d5efa7ecefe86..88d5db2995829cba919d78f988d5c735cf70cb1b 100644
--- a/src/test/java/org/bukkit/AnnotationTest.java
+++ b/src/test/java/org/bukkit/AnnotationTest.java
@@ -48,6 +48,8 @@ public class AnnotationTest {

View file

@ -11,20 +11,20 @@ Add a NetworkClient interface that provides access to:
diff --git a/src/main/java/com/destroystokyo/paper/network/NetworkClient.java b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b851aa04f
index 0000000000000000000000000000000000000000..c84ce3fc874eea3d8f0b1cf5273996d9b4af6225
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java
@@ -0,0 +1,41 @@
@@ -0,0 +1,39 @@
+package com.destroystokyo.paper.network;
+
+import java.net.InetSocketAddress;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents a client connected to the server.
+ */
+@NullMarked
+public interface NetworkClient {
+
+ /**
@ -32,7 +32,6 @@ index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b
+ *
+ * @return The client's socket address
+ */
+ @NotNull
+ InetSocketAddress getAddress();
+
+ /**
@ -52,8 +51,7 @@ index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b
+ *
+ * @return The client's virtual host, or {@code null} if unknown
+ */
+ @Nullable
+ InetSocketAddress getVirtualHost();
+ @Nullable InetSocketAddress getVirtualHost();
+
+}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java

View file

@ -10,25 +10,25 @@ on the players login.
Plugin authors need to define a key to keep it consistent between server restarts.
diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
index 9f9c67e935940833bbfe58e6bfa398e6c86980d5..71e494177473c62449aafda1699b26a0c4c81a68 100644
index c414ccf03572d48f5c096516fc60a59bb1e8efd7..e9bac744c5b173e6767e2de8480a6697969fdbb0 100644
--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
@@ -31,6 +31,7 @@ public class ShapedRecipe extends CraftingRecipe {
@Deprecated
public ShapedRecipe(@NotNull ItemStack result) {
super(NamespacedKey.randomKey(), result);
this(NamespacedKey.randomKey(), result);
+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
}
/**
diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
index 03839302c94adc3175d0a88065cd230257ffd20d..d6e38c7ccfe3b6e85eafb611da20b1a29fb74d97 100644
index b7f46a048633945dc71e8efec9a7ebeed5832fd7..a7513c1aa09b88e3f99e7db40661fd83e682de96 100644
--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
@@ -20,6 +20,7 @@ public class ShapelessRecipe extends CraftingRecipe {
@Deprecated
public ShapelessRecipe(@NotNull ItemStack result) {
super(NamespacedKey.randomKey(), result);
this(NamespacedKey.randomKey(), result);
+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
}

View file

@ -7,10 +7,10 @@ Allows plugins to cancel a player picking up an experience orb
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ef10ac6bac990837e21520c800d89420a18e3d4
index 0000000000000000000000000000000000000000..0c6ddf0724780245ad01a3b5a5b0e477c25fc62e
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java
@@ -0,0 +1,83 @@
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
+ *
@ -42,20 +42,21 @@ index 0000000000000000000000000000000000000000..0ef10ac6bac990837e21520c800d8942
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when a player is attempting to pick up an experience orb
+ */
+@NullMarked
+public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final ExperienceOrb experienceOrb;
+ private final ExperienceOrb experienceOrb;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) {
+ public PlayerPickupExperienceEvent(final Player player, final ExperienceOrb experienceOrb) {
+ super(player);
+ this.experienceOrb = experienceOrb;
+ }
@ -63,7 +64,6 @@ index 0000000000000000000000000000000000000000..0ef10ac6bac990837e21520c800d8942
+ /**
+ * @return Returns the Orb that the player is picking up
+ */
+ @NotNull
+ public ExperienceOrb getExperienceOrb() {
+ return this.experienceOrb;
+ }
@ -79,17 +79,15 @@ index 0000000000000000000000000000000000000000..0ef10ac6bac990837e21520c800d8942
+ * If {@code true}, cancels picking up the experience orb, leaving it in the world
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -12,10 +12,10 @@ Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c520e5517861c4686806df233d1ef5e6bfb76ad3
index 0000000000000000000000000000000000000000..5902e6d6c0516a1249c72b405a49dfc5cc490e0e
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
@@ -0,0 +1,91 @@
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
+ *
@ -46,22 +46,23 @@ index 0000000000000000000000000000000000000000..c520e5517861c4686806df233d1ef5e6
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired anytime the server is about to merge 2 experience orbs into one
+ */
+@NullMarked
+public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final ExperienceOrb mergeTarget;
+ @NotNull private final ExperienceOrb mergeSource;
+ private final ExperienceOrb mergeTarget;
+ private final ExperienceOrb mergeSource;
+
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) {
+ public ExperienceOrbMergeEvent(final ExperienceOrb mergeTarget, final ExperienceOrb mergeSource) {
+ super(mergeTarget);
+ this.mergeTarget = mergeTarget;
+ this.mergeSource = mergeSource;
@ -70,7 +71,6 @@ index 0000000000000000000000000000000000000000..c520e5517861c4686806df233d1ef5e6
+ /**
+ * @return The orb that will absorb the other experience orb
+ */
+ @NotNull
+ public ExperienceOrb getMergeTarget() {
+ return this.mergeTarget;
+ }
@ -78,7 +78,6 @@ index 0000000000000000000000000000000000000000..c520e5517861c4686806df233d1ef5e6
+ /**
+ * @return The orb that is subject to being removed and merged into the target orb
+ */
+ @NotNull
+ public ExperienceOrb getMergeSource() {
+ return this.mergeSource;
+ }
@ -92,17 +91,15 @@ index 0000000000000000000000000000000000000000..c520e5517861c4686806df233d1ef5e6
+ * @param cancel {@code true} if you wish to cancel this event, and prevent the orbs from merging
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -16,10 +16,10 @@ See: https://github.com/PaperMC/Paper/issues/917
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f93ffc2a4
index 0000000000000000000000000000000000000000..c1c96f93a4a5450381cb5bdb198b056a37ba0fbe
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java
@@ -0,0 +1,109 @@
@@ -0,0 +1,105 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.Location;
@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * WARNING: This event only fires for a limited number of cases, and not for every case that {@link CreatureSpawnEvent} does.
@ -41,19 +41,20 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ * 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.
+ */
+@NullMarked
+public class PreCreatureSpawnEvent extends Event implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Location location;
+ @NotNull private final EntityType type;
+ @NotNull private final CreatureSpawnEvent.SpawnReason reason;
+ private final Location location;
+ private final EntityType type;
+ private final CreatureSpawnEvent.SpawnReason reason;
+ private boolean shouldAbortSpawn;
+
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) {
+ public PreCreatureSpawnEvent(final Location location, final EntityType type, final CreatureSpawnEvent.SpawnReason reason) {
+ this.location = location;
+ this.type = type;
+ this.reason = reason;
@ -62,7 +63,6 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ /**
+ * @return The location this creature is being spawned at
+ */
+ @NotNull
+ public Location getSpawnLocation() {
+ return this.location.clone();
+ }
@ -70,7 +70,6 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ /**
+ * @return The type of creature being spawned
+ */
+ @NotNull
+ public EntityType getType() {
+ return this.type;
+ }
@ -78,7 +77,6 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ /**
+ * @return Reason this creature is spawning (ie, NATURAL vs SPAWNER)
+ */
+ @NotNull
+ public CreatureSpawnEvent.SpawnReason getReason() {
+ return this.reason;
+ }
@ -96,7 +94,7 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ *
+ * @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts
+ */
+ public void setShouldAbortSpawn(boolean shouldAbortSpawn) {
+ public void setShouldAbortSpawn(final boolean shouldAbortSpawn) {
+ this.shouldAbortSpawn = shouldAbortSpawn;
+ }
+
@ -114,17 +112,15 @@ index 0000000000000000000000000000000000000000..633ef4dcc701916f2dbfefbbebd5994f
+ * @param cancel {@code true} if you wish to cancel this event, and abort the spawn of this creature
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -10,10 +10,10 @@ Also a highly more effecient way to blanket block spawns in a world
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7fcee73d61347165cefef7b92f0e63e0bed8ad73
index 0000000000000000000000000000000000000000..a3267a283b39e8db1e9b7e5338d2909320f1421c
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java
@@ -0,0 +1,66 @@
@@ -0,0 +1,65 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.entity.Player;
@ -21,11 +21,12 @@ index 0000000000000000000000000000000000000000..7fcee73d61347165cefef7b92f0e63e0
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event
+ */
+@NullMarked
+public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
@ -34,7 +35,7 @@ index 0000000000000000000000000000000000000000..7fcee73d61347165cefef7b92f0e63e0
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) {
+ public PlayerNaturallySpawnCreaturesEvent(final Player player, final byte radius) {
+ super(player);
+ this.radius = radius;
+ }
@ -49,12 +50,12 @@ index 0000000000000000000000000000000000000000..7fcee73d61347165cefef7b92f0e63e0
+ /**
+ * @param radius The radius of chunks around this player to be included in natural spawn selection
+ */
+ public void setSpawnRadius(byte radius) {
+ public void setSpawnRadius(final byte radius) {
+ this.radius = radius;
+ }
+
+ /**
+ * @return If this players chunks will be excluded from natural spawns
+ * @return If this player's chunks will be excluded from natural spawns
+ */
+ @Override
+ public boolean isCancelled() {
@ -62,20 +63,18 @@ index 0000000000000000000000000000000000000000..7fcee73d61347165cefef7b92f0e63e0
+ }
+
+ /**
+ * @param cancel {@code true} if you wish to cancel this event, and not include this players chunks for natural spawning
+ * @param cancel {@code true} if you wish to cancel this event, and not include this player's chunks for natural spawning
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,10 +7,10 @@ Co-authored-by: The456gamer <the456gamer@the456gamer.dev>
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d738dde7ae
index 0000000000000000000000000000000000000000..0fb316e34ec9728610237a08f37fffb61fd5afa8
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java
@@ -0,0 +1,84 @@
@@ -0,0 +1,80 @@
+package com.destroystokyo.paper.event.player;
+
+import org.bukkit.advancement.Advancement;
@ -20,24 +20,25 @@ index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d7
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called after a player is granted a criteria in an advancement.
+ * If cancelled the criteria will be revoked.
+ */
+@NullMarked
+public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Advancement advancement;
+ @NotNull private final String criterion;
+ @NotNull private final AdvancementProgress advancementProgress;
+ private final Advancement advancement;
+ private final String criterion;
+ private final AdvancementProgress advancementProgress;
+
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public PlayerAdvancementCriterionGrantEvent(@NotNull Player player, @NotNull Advancement advancement, @NotNull String criterion) {
+ public PlayerAdvancementCriterionGrantEvent(final Player player, final Advancement advancement, final String criterion) {
+ super(player);
+ this.advancement = advancement;
+ this.criterion = criterion;
@ -49,7 +50,6 @@ index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d7
+ *
+ * @return affected advancement
+ */
+ @NotNull
+ public Advancement getAdvancement() {
+ return this.advancement;
+ }
@ -59,7 +59,6 @@ index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d7
+ *
+ * @return granted criterion
+ */
+ @NotNull
+ public String getCriterion() {
+ return this.criterion;
+ }
@ -69,7 +68,6 @@ index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d7
+ *
+ * @return advancement progress
+ */
+ @NotNull
+ public AdvancementProgress getAdvancementProgress() {
+ return this.advancementProgress;
+ }
@ -80,17 +78,15 @@ index 0000000000000000000000000000000000000000..9502f94b3567fc22c4b61fea5aa251d7
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -12,10 +12,10 @@ This is useful for implementing a ProfileCache for Player Skulls
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c97ded9f9ef1c550cca7d0a3a3b09a85e5999cdf
index 0000000000000000000000000000000000000000..8625d60eb822f39140152f2f74ec5bfe5ecd0039
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java
@@ -0,0 +1,79 @@
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
+ *
@ -43,24 +43,24 @@ index 0000000000000000000000000000000000000000..c97ded9f9ef1c550cca7d0a3a3b09a85
+
+import com.destroystokyo.paper.profile.PlayerProfile;
+import com.destroystokyo.paper.profile.ProfileProperty;
+import java.util.Set;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.Set;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired once a profiles additional properties (such as textures) has been filled
+ */
+@NullMarked
+public class FillProfileEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final PlayerProfile profile;
+ private final PlayerProfile profile;
+
+ @ApiStatus.Internal
+ public FillProfileEvent(@NotNull PlayerProfile profile) {
+ public FillProfileEvent(final PlayerProfile profile) {
+ super(!org.bukkit.Bukkit.isPrimaryThread());
+ this.profile = profile;
+ }
@ -68,7 +68,6 @@ index 0000000000000000000000000000000000000000..c97ded9f9ef1c550cca7d0a3a3b09a85
+ /**
+ * @return The Profile that had properties filled
+ */
+ @NotNull
+ public PlayerProfile getPlayerProfile() {
+ return this.profile;
+ }
@ -76,31 +75,28 @@ index 0000000000000000000000000000000000000000..c97ded9f9ef1c550cca7d0a3a3b09a85
+ /**
+ * Same as .getPlayerProfile().getProperties()
+ *
+ * @see PlayerProfile#getProperties()
+ * @return The new properties on the profile.
+ * @see PlayerProfile#getProperties()
+ */
+ @NotNull
+ public Set<ProfileProperty> getProperties() {
+ return this.profile.getProperties();
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2a47c4af2c368a361e4a370a01111abe8e48062
index 0000000000000000000000000000000000000000..177c23274d6dad709b05706117303b70ae8b4c7b
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java
@@ -0,0 +1,81 @@
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
+ *
@ -128,26 +124,26 @@ index 0000000000000000000000000000000000000000..e2a47c4af2c368a361e4a370a01111ab
+
+import com.destroystokyo.paper.profile.PlayerProfile;
+import com.destroystokyo.paper.profile.ProfileProperty;
+import java.util.Collection;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.Collection;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when the server is requesting to fill in properties of an incomplete profile, such as textures.
+ * <p>
+ * Allows plugins to pre-populate cached properties and avoid a call to the Mojang API
+ */
+@NullMarked
+public class PreFillProfileEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final PlayerProfile profile;
+ private final PlayerProfile profile;
+
+ @ApiStatus.Internal
+ public PreFillProfileEvent(@NotNull PlayerProfile profile) {
+ public PreFillProfileEvent(final PlayerProfile profile) {
+ super(!org.bukkit.Bukkit.isPrimaryThread());
+ this.profile = profile;
+ }
@ -155,7 +151,6 @@ index 0000000000000000000000000000000000000000..e2a47c4af2c368a361e4a370a01111ab
+ /**
+ * @return The profile that needs its properties filled
+ */
+ @NotNull
+ public PlayerProfile getPlayerProfile() {
+ return this.profile;
+ }
@ -163,21 +158,19 @@ index 0000000000000000000000000000000000000000..e2a47c4af2c368a361e4a370a01111ab
+ /**
+ * Sets the properties on the profile, avoiding the call to the Mojang API
+ * Same as .getPlayerProfile().setProperties(properties);
+ *
+ * @see PlayerProfile#setProperties(Collection)
+ *
+ * @param properties The properties to set/append
+ * @see PlayerProfile#setProperties(Collection)
+ */
+ public void setProperties(@NotNull Collection<ProfileProperty> properties) {
+ public void setProperties(final Collection<ProfileProperty> properties) {
+ this.profile.setProperties(properties);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -8,7 +8,7 @@ client that does not support all of the features provided in the
event.
diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9dcca2802 100644
index 517d15238ed117f38bbd39f570874014cecf7bb5..a8437bbd80b3a20772352a3b1797990ea13806ad 100644
--- a/src/main/java/com/destroystokyo/paper/network/StatusClient.java
+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
@@ -10,4 +10,16 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
@ -17,7 +17,7 @@ index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9
+ /**
+ * Returns whether the client is using an older version that doesn't
+ * support all of the features in {@link PaperServerListPingEvent}.
+ * support all the features in {@link PaperServerListPingEvent}.
+ *
+ * <p>For Vanilla, this returns {@code true} for all clients older than 1.7.</p>
+ *

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Add openSign method to HumanEntity
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
index 8cc6f8547380d567aef7910ef309193bd79ced09..48bb08cc7c0af6ebb905d1e175ada0fd7944ca48 100644
index b8431d9722ef9fce0ac9e18367abef22717997ca..0d01fe9c96a1b9076dbd6d031fa8cd41954ea8db 100644
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
@@ -496,6 +496,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
@@ -507,6 +507,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
*/
@Deprecated
public void setShoulderEntityRight(@Nullable Entity entity);

View file

@ -9,10 +9,10 @@ You may cancel this, enabling ranged attacks to damage the enderman for example.
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6be848c44d5efaca3fbc03c3be7451411943c24
index 0000000000000000000000000000000000000000..ae72916972dbe86bfbca499eb7b6f97b1a6eae25
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java
@@ -0,0 +1,86 @@
@@ -0,0 +1,83 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.entity.Enderman;
@ -20,22 +20,22 @@ index 0000000000000000000000000000000000000000..f6be848c44d5efaca3fbc03c3be74514
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Reason reason;
+ private final Reason reason;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) {
+ public EndermanEscapeEvent(final Enderman entity, final Reason reason) {
+ super(entity);
+ this.reason = reason;
+ }
+
+ @NotNull
+ @Override
+ public Enderman getEntity() {
+ return (Enderman) super.getEntity();
@ -44,7 +44,6 @@ index 0000000000000000000000000000000000000000..f6be848c44d5efaca3fbc03c3be74514
+ /**
+ * @return The reason the enderman is trying to escape
+ */
+ @NotNull
+ public Reason getReason() {
+ return this.reason;
+ }
@ -57,21 +56,19 @@ index 0000000000000000000000000000000000000000..f6be848c44d5efaca3fbc03c3be74514
+ /**
+ * Cancels the escape.
+ * <p>
+ * If this escape normally would of resulted in damage avoidance such as indirect,
+ * If this escape normally had resulted in damage avoidance such as indirect,
+ * the enderman will now take damage.
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -10,46 +10,45 @@ This adds a new Builder API which is much friendlier to use.
diff --git a/src/main/java/com/destroystokyo/paper/ParticleBuilder.java b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0337f279c
index 0000000000000000000000000000000000000000..6c405755f4507d6fbc6c3877c611a7191206f3ff
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java
@@ -0,0 +1,583 @@
@@ -0,0 +1,582 @@
+package com.destroystokyo.paper;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+import java.util.Collection;
+import java.util.List;
+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.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Helps prepare a particle to be sent to players.
+ *
+ * <p>
+ * Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API
+ */
+@NullMarked
+public class ParticleBuilder implements Cloneable {
+
+ private Particle particle;
+ private List<Player> receivers;
+ private Player source;
+ private Location location;
+ private @Nullable List<Player> receivers;
+ private @Nullable Player source;
+ private @Nullable Location location;
+ private int count = 1;
+ private double offsetX = 0, offsetY = 0, offsetZ = 0;
+ private double extra = 1;
+ private Object data;
+ private @Nullable Object data;
+ private boolean force = true;
+
+ public ParticleBuilder(@NotNull Particle particle) {
+ public ParticleBuilder(final Particle particle) {
+ this.particle = particle;
+ }
+
@ -59,14 +58,14 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ *
+ * @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
+ this.location.getWorld().spawnParticle(
+ this.particle, this.receivers, this.source,
+ this.location.getX(), this.location.getY(), this.location.getZ(),
+ this.count, this.offsetX, this.offsetY, this.offsetZ, this.extra, this.data, this.force
+ );
+ return this;
+ }
@ -74,9 +73,8 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ /**
+ * @return The particle going to be sent
+ */
+ @NotNull
+ public Particle particle() {
+ return particle;
+ return this.particle;
+ }
+
+ /**
@ -85,8 +83,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param particle The particle
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder particle(@NotNull Particle particle) {
+ public ParticleBuilder particle(final Particle particle) {
+ this.particle = particle;
+ return this;
+ }
@ -94,32 +91,30 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ /**
+ * @return List of players who will receive the particle, or null for all in world
+ */
+ @Nullable
+ public List<Player> receivers() {
+ return receivers;
+ public @Nullable List<Player> receivers() {
+ return this.receivers;
+ }
+
+ /**
+ * Example use:
+ *
+ * <p>
+ * 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());
+ return (this.receivers == null && this.location != null && !this.location.getWorld().getPlayers().isEmpty()) || (
+ this.receivers != null && !this.receivers.isEmpty());
+ }
+
+ /**
+ * Sends this particle to all players in the world. This is rather silly and you should likely not
+ * Sends this particle to all players in the world. This is rather silly, and you should likely not
+ * be doing this.
+ *
+ * <p>
+ * 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;
@ -127,11 +122,10 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+
+ /**
+ * @param receivers List of players to receive this particle, or null for all players in the
+ * world
+ * world
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder receivers(@Nullable List<Player> receivers) {
+ public ParticleBuilder receivers(final @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;
@ -140,22 +134,20 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+
+ /**
+ * @param receivers List of players to receive this particle, or null for all players in the
+ * world
+ * world
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder receivers(@Nullable Collection<Player> receivers) {
+ public ParticleBuilder receivers(final @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
+ * @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 Player... receivers) {
+ public ParticleBuilder receivers(final Player @Nullable... receivers) {
+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
+ return this;
+ }
@ -168,9 +160,8 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param radius amount to add on all axis
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder receivers(int radius) {
+ return receivers(radius, radius);
+ public ParticleBuilder receivers(final int radius) {
+ return this.receivers(radius, radius);
+ }
+
+ /**
@ -178,22 +169,24 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * 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 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) {
+ public ParticleBuilder receivers(final int radius, final boolean byDistance) {
+ if (!byDistance) {
+ return receivers(radius, radius, radius);
+ return this.receivers(radius, radius, radius);
+ } else {
+ if (this.location == null) {
+ throw new IllegalStateException("Please set location first");
+ }
+ 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());
+ for (final Player nearbyPlayer : this.location.getWorld()
+ .getNearbyPlayers(this.location, radius, radius, radius)) {
+ final Location loc = nearbyPlayer.getLocation();
+ final double x = NumberConversions.square(this.location.getX() - loc.getX());
+ final double y = NumberConversions.square(this.location.getY() - loc.getY());
+ final double z = NumberConversions.square(this.location.getZ() - loc.getZ());
+ if (Math.sqrt(x + y + z) > radius) {
+ continue;
+ }
@ -210,12 +203,11 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * see {@link #receivers(int, boolean)}
+ *
+ * @param xzRadius amount to add on the x/z axis
+ * @param yRadius amount to add on the y 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);
+ public ParticleBuilder receivers(final int xzRadius, final int yRadius) {
+ return this.receivers(xzRadius, yRadius, xzRadius);
+ }
+
+ /**
@ -223,25 +215,28 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * 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 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.
+ * @throws IllegalStateException if a location hasn't been specified yet
+ */
+ @NotNull
+ public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) {
+ public ParticleBuilder receivers(final int xzRadius, final int yRadius, final boolean byDistance) {
+ if (!byDistance) {
+ return receivers(xzRadius, yRadius, xzRadius);
+ return this.receivers(xzRadius, yRadius, xzRadius);
+ } else {
+ if (this.location == null) {
+ throw new IllegalStateException("Please set location first");
+ }
+ this.receivers = Lists.newArrayList();
+ for (Player nearbyPlayer : location.getWorld()
+ .getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) {
+ Location loc = nearbyPlayer.getLocation();
+ for (final Player nearbyPlayer : this.location.getWorld()
+ .getNearbyPlayers(this.location, xzRadius, yRadius, xzRadius)) {
+ final 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());
+ final double x = NumberConversions.square(this.location.getX() - loc.getX());
+ final double z = NumberConversions.square(this.location.getZ() - loc.getZ());
+ if (x + z > NumberConversions.square(xzRadius)) {
+ continue;
+ }
@ -261,20 +256,18 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @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) {
+ public ParticleBuilder receivers(final int xRadius, final int yRadius, final int zRadius) {
+ if (this.location == null) {
+ throw new IllegalStateException("Please set location first");
+ }
+ return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius));
+ return this.receivers(this.location.getWorld().getNearbyPlayers(this.location, xRadius, yRadius, zRadius));
+ }
+
+ /**
+ * @return The player considered the source of this particle (for Visibility concerns), or null
+ */
+ @Nullable
+ public Player source() {
+ return source;
+ public @Nullable Player source() {
+ return this.source;
+ }
+
+ /**
@ -283,8 +276,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param source The player who is considered the source
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder source(@Nullable Player source) {
+ public ParticleBuilder source(final @Nullable Player source) {
+ this.source = source;
+ return this;
+ }
@ -292,9 +284,8 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ /**
+ * @return Location of where the particle will spawn
+ */
+ @Nullable
+ public Location location() {
+ return location;
+ public @Nullable Location location() {
+ return this.location;
+ }
+
+ /**
@ -303,8 +294,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param location The location of the particle
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder location(@NotNull Location location) {
+ public ParticleBuilder location(final Location location) {
+ this.location = location.clone();
+ return this;
+ }
@ -313,13 +303,12 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * 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
+ * @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) {
+ public ParticleBuilder location(final World world, final double x, final double y, final double z) {
+ this.location = new Location(world, x, y, z);
+ return this;
+ }
@ -328,7 +317,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return Number of particles to spawn
+ */
+ public int count() {
+ return count;
+ return this.count;
+ }
+
+ /**
@ -337,8 +326,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param count Number of particles
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder count(int count) {
+ public ParticleBuilder count(final int count) {
+ this.count = count;
+ return this;
+ }
@ -349,7 +337,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return Particle offset X.
+ */
+ public double offsetX() {
+ return offsetX;
+ return this.offsetX;
+ }
+
+ /**
@ -358,7 +346,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return Particle offset Y.
+ */
+ public double offsetY() {
+ return offsetY;
+ return this.offsetY;
+ }
+
+ /**
@ -367,7 +355,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return Particle offset Z.
+ */
+ public double offsetZ() {
+ return offsetZ;
+ return this.offsetZ;
+ }
+
+ /**
@ -378,8 +366,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param offsetZ Particle offset Z
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) {
+ public ParticleBuilder offset(final double offsetX, final double offsetY, final double offsetZ) {
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+ this.offsetZ = offsetZ;
@ -392,7 +379,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return the extra particle data
+ */
+ public double extra() {
+ return extra;
+ return this.extra;
+ }
+
+ /**
@ -401,8 +388,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param extra the extra particle data
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder extra(double extra) {
+ public ParticleBuilder extra(final double extra) {
+ this.extra = extra;
+ return this;
+ }
@ -413,21 +399,19 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param <T> The Particle data type
+ * @return the ParticleData for this particle
+ */
+ @Nullable
+ public <T> T data() {
+ public @Nullable <T> T data() {
+ //noinspection unchecked
+ return (T) data;
+ return (T) this.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
+ * @param <T> The Particle data type
+ * @return a reference to this object.
+ */
+ @NotNull
+ public <T> ParticleBuilder data(@Nullable T data) {
+ public <T> ParticleBuilder data(final @Nullable T data) {
+ this.data = data;
+ return this;
+ }
@ -436,7 +420,7 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @return whether the particle is forcefully shown to players.
+ */
+ public boolean force() {
+ return force;
+ return this.force;
+ }
+
+ /**
@ -447,74 +431,94 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * @param force true to force, false for normal
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder force(boolean force) {
+ public ParticleBuilder force(final boolean force) {
+ this.force = force;
+ return this;
+ }
+
+ /**
+ * Sets the particle Color.
+ * Only valid for {@link Particle#DUST}.
+ * Only valid for particles with a data type of {@link Color} or {@link Particle.DustOptions}.
+ *
+ * @param color the new particle color
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder color(@Nullable Color color) {
+ return color(color, 1);
+ public ParticleBuilder color(final @Nullable Color color) {
+ if (this.particle.getDataType() == Color.class) {
+ return this.data(color);
+ }
+ return this.color(color, 1);
+ }
+
+ /**
+ * Sets the particle Color and size.
+ * Only valid for {@link Particle#DUST}.
+ * Only valid for particles with a data type of {@link Particle.DustOptions}.
+ *
+ * @param color the new particle color
+ * @param size the size of the particle
+ * @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.DUST && color != null) {
+ throw new IllegalStateException("Color may only be set on particle DUST.");
+ public ParticleBuilder color(final @Nullable Color color, final float size) {
+ if (this.particle.getDataType() != Particle.DustOptions.class && color != null) {
+ throw new IllegalStateException("The combination of Color and size cannot be set on this particle type.");
+ }
+
+ // We don't officially support reusing these objects, but here we go
+ if (color == null) {
+ if (data instanceof Particle.DustOptions) {
+ return data(null);
+ if (this.data instanceof Particle.DustOptions) {
+ return this.data(null);
+ } else {
+ return this;
+ }
+ }
+
+ return data(new Particle.DustOptions(color, size));
+ return this.data(new Particle.DustOptions(color, size));
+ }
+
+ /**
+ * Sets the particle Color.
+ * Only valid for {@link Particle#DUST}.
+ * Only valid for particles with a data type of {@link Color} or {@link Particle.DustOptions}.
+ *
+ * @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));
+ public ParticleBuilder color(final int r, final int g, final int b) {
+ return this.color(Color.fromRGB(r, g, b));
+ }
+
+ /**
+ * Sets the particle Color.
+ * Only valid for {@link Particle#DUST}.
+ * Only valid for particles with a data type of {@link Color} or {@link Particle.DustOptions}.
+ * <p>
+ * This method detects if the provided color integer is in RGB or ARGB format.
+ * If the alpha channel is zero, it treats the color as RGB. Otherwise, it treats it as ARGB.
+ *
+ * @param rgb an integer representing the red, green, and blue color components
+ * @param color an integer representing the color components. If the highest byte (alpha channel) is zero,
+ * the color is treated as RGB. Otherwise, it is treated as ARGB.
+ * @return a reference to this object.
+ */
+ @NotNull
+ public ParticleBuilder color(final int rgb) {
+ return color(Color.fromRGB(rgb));
+ public ParticleBuilder color(final int color) {
+ final int alpha = (color >> 24) & 0xFF;
+ if (alpha == 0) {
+ return this.color(Color.fromRGB(color));
+ }
+ return this.color(Color.fromARGB(color));
+ }
+
+ /**
+ * Sets the particle Color.
+ * Only valid for particles with a data type of {@link Color} or {@link Particle.DustOptions}.
+ *
+ * @param a alpha color component
+ * @param r red color component
+ * @param g green color component
+ * @param b blue color component
+ * @return a reference to this object.
+ */
+ public ParticleBuilder color(final int a, final int r, final int g, final int b) {
+ return this.color(Color.fromARGB(a, r, g, b));
+ }
+
+ /**
@ -522,69 +526,64 @@ index 0000000000000000000000000000000000000000..52f639b838e8b49952c560f20bacbad0
+ * Only valid for {@link Particle#DUST_COLOR_TRANSITION}.
+ *
+ * @param fromColor the new particle from color
+ * @param toColor the new particle to color
+ * @param toColor the new particle to color
+ * @return a reference to this object.
+ * @throws IllegalArgumentException if the particle builder's {@link #particle()} isn't {@link Particle#DUST_COLOR_TRANSITION}.
+ */
+ @NotNull
+ public ParticleBuilder colorTransition(@NotNull final Color fromColor, @NotNull final Color toColor) {
+ return colorTransition(fromColor, toColor, 1);
+ public ParticleBuilder colorTransition(final Color fromColor, final Color toColor) {
+ return this.colorTransition(fromColor, toColor, 1);
+ }
+
+ /**
+ * Sets the particle Color Transition.
+ * Only valid for {@link Particle#DUST_COLOR_TRANSITION}.
+ *
+ * @param fromRed red color component for the from color
+ * @param fromGreen green color component for the from color
+ * @param fromBlue blue color component for the from color
+ * @param toRed red color component for the to color
+ * @param toGreen green color component for the to color
+ * @param toBlue blue color component for the to color
+ * @param fromRed red color component for the "from" color
+ * @param fromGreen green color component for the "from" color
+ * @param fromBlue blue color component for the "from" color
+ * @param toRed red color component for the to color
+ * @param toGreen green color component for the to color
+ * @param toBlue blue color component for the to color
+ * @return a reference to this object.
+ * @throws IllegalArgumentException if the particle builder's {@link #particle()} isn't {@link Particle#DUST_COLOR_TRANSITION}.
+ */
+ @NotNull
+ public ParticleBuilder colorTransition(final int fromRed, final int fromGreen, final int fromBlue,
+ final int toRed, final int toGreen, final int toBlue) {
+ return colorTransition(Color.fromRGB(fromRed, fromGreen, fromBlue), Color.fromRGB(toRed, toGreen, toBlue));
+ public ParticleBuilder colorTransition(
+ final int fromRed, final int fromGreen, final int fromBlue,
+ final int toRed, final int toGreen, final int toBlue
+ ) {
+ return this.colorTransition(Color.fromRGB(fromRed, fromGreen, fromBlue), Color.fromRGB(toRed, toGreen, toBlue));
+ }
+
+ /**
+ * Sets the particle Color Transition.
+ * Only valid for {@link Particle#DUST_COLOR_TRANSITION}.
+ *
+ * @param fromRgb an integer representing the red, green, and blue color components for the from color
+ * @param toRgb an integer representing the red, green, and blue color components for the to color
+ * @param fromRgb an integer representing the red, green, and blue color components for the "from" color
+ * @param toRgb an integer representing the red, green, and blue color components for the "to" color
+ * @return a reference to this object.
+ * @throws IllegalArgumentException if the particle builder's {@link #particle()} isn't {@link Particle#DUST_COLOR_TRANSITION}.
+ */
+ @NotNull
+ public ParticleBuilder colorTransition(final int fromRgb, final int toRgb) {
+ return colorTransition(Color.fromRGB(fromRgb), Color.fromRGB(toRgb));
+ return this.colorTransition(Color.fromRGB(fromRgb), Color.fromRGB(toRgb));
+ }
+
+ /**
+ * Sets the particle Color Transition and size.
+ * Only valid for {@link Particle#DUST_COLOR_TRANSITION}.
+ *
+ * @param fromColor the new particle color for the from color.
+ * @param toColor the new particle color for the to color.
+ * @param size the size of the particle
+ * @param fromColor the new particle color for the "from" color.
+ * @param toColor the new particle color for the "to" color.
+ * @param size the size of the particle
+ * @return a reference to this object.
+ * @throws IllegalArgumentException if the particle builder's {@link #particle()} isn't {@link Particle#DUST_COLOR_TRANSITION}.
+ */
+ @NotNull
+ public ParticleBuilder colorTransition(@NotNull final Color fromColor,
+ @NotNull final Color toColor,
+ final float size) {
+ public ParticleBuilder colorTransition(final Color fromColor, final Color toColor, final float size) {
+ Preconditions.checkArgument(fromColor != null, "Cannot define color transition with null fromColor.");
+ Preconditions.checkArgument(toColor != null, "Cannot define color transition with null toColor.");
+ Preconditions.checkArgument(this.particle() == Particle.DUST_COLOR_TRANSITION, "Can only define a color transition on particle DUST_COLOR_TRANSITION.");
+ return data(new Particle.DustTransition(fromColor, toColor, size));
+ return this.data(new Particle.DustTransition(fromColor, toColor, size));
+ }
+
+ @NotNull
+ @Override
+ public ParticleBuilder clone() {
+ try {

View file

@ -9,10 +9,10 @@ This allows you to override/extend the pumpkin/stare logic.
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272743a8f35
index 0000000000000000000000000000000000000000..34adc77de2d1f06b2b10cc26b60240c6a3ef259c
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java
@@ -0,0 +1,101 @@
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
+ *
@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when an Enderman determines if it should attack a player or not.
@ -52,15 +52,16 @@ index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272
+ * Starts off cancelled if the player is wearing a pumpkin head or is not looking
+ * at the Enderman, according to Vanilla rules.
+ */
+@NullMarked
+public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final Player player;
+ private final Player player;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) {
+ public EndermanAttackPlayerEvent(final Enderman entity, final Player player) {
+ super(entity);
+ this.player = player;
+ }
@ -70,7 +71,6 @@ index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272
+ *
+ * @return The enderman considering attacking
+ */
+ @NotNull
+ @Override
+ public Enderman getEntity() {
+ return (Enderman) super.getEntity();
@ -81,7 +81,6 @@ index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272
+ *
+ * @return The player the Enderman is considering attacking
+ */
+ @NotNull
+ public Player getPlayer() {
+ return this.player;
+ }
@ -100,16 +99,15 @@ index 0000000000000000000000000000000000000000..ae34e679723a2ef436da04c116038272
+ * Cancels if the Enderman will attack this player
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,10 +7,10 @@ Fires when a witch consumes the potion in their hand
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..773079aa92280bb97e9b4c0e62d9ead08135610a
index 0000000000000000000000000000000000000000..43ee765dedf5001fadf1af317b6ab323fde34851
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java
@@ -0,0 +1,73 @@
@@ -0,0 +1,71 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.entity.Witch;
@ -19,26 +19,26 @@ index 0000000000000000000000000000000000000000..773079aa92280bb97e9b4c0e62d9ead0
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Fired when a witch consumes the potion in their hand to buff themselves.
+ */
+@NullMarked
+public class WitchConsumePotionEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @Nullable private ItemStack potion;
+ private @Nullable ItemStack potion;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
+ public WitchConsumePotionEvent(final Witch witch, final @Nullable ItemStack potion) {
+ super(witch);
+ this.potion = potion;
+ }
+
+ @NotNull
+ @Override
+ public Witch getEntity() {
+ return (Witch) super.getEntity();
@ -47,8 +47,7 @@ index 0000000000000000000000000000000000000000..773079aa92280bb97e9b4c0e62d9ead0
+ /**
+ * @return the potion the witch will consume and have the effects applied.
+ */
+ @Nullable
+ public ItemStack getPotion() {
+ public @Nullable ItemStack getPotion() {
+ return this.potion;
+ }
+
@ -57,7 +56,7 @@ index 0000000000000000000000000000000000000000..773079aa92280bb97e9b4c0e62d9ead0
+ *
+ * @param potion The potion
+ */
+ public void setPotion(@Nullable ItemStack potion) {
+ public void setPotion(final @Nullable ItemStack potion) {
+ this.potion = potion != null ? potion.clone() : null;
+ }
+
@ -70,16 +69,15 @@ index 0000000000000000000000000000000000000000..773079aa92280bb97e9b4c0e62d9ead0
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,10 +7,10 @@ Fired when a witch throws a potion at a player
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f621ea043a
index 0000000000000000000000000000000000000000..02395582b680f4baa3dc2251a8a79f41241b96ec
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java
@@ -0,0 +1,85 @@
@@ -0,0 +1,81 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.entity.LivingEntity;
@ -20,28 +20,28 @@ index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f6
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Fired when a witch throws a potion at a player
+ */
+@NullMarked
+public class WitchThrowPotionEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final LivingEntity target;
+ @Nullable private ItemStack potion;
+ private final LivingEntity target;
+ private @Nullable ItemStack potion;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) {
+ public WitchThrowPotionEvent(final Witch witch, final LivingEntity target, final @Nullable ItemStack potion) {
+ super(witch);
+ this.target = target;
+ this.potion = potion;
+ }
+
+ @NotNull
+ @Override
+ public Witch getEntity() {
+ return (Witch) super.getEntity();
@ -50,7 +50,6 @@ index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f6
+ /**
+ * @return The target of the potion
+ */
+ @NotNull
+ public LivingEntity getTarget() {
+ return this.target;
+ }
@ -58,8 +57,7 @@ index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f6
+ /**
+ * @return The potion the witch will throw at a player
+ */
+ @Nullable
+ public ItemStack getPotion() {
+ public @Nullable ItemStack getPotion() {
+ return this.potion;
+ }
+
@ -68,7 +66,7 @@ index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f6
+ *
+ * @param potion The potion
+ */
+ public void setPotion(@Nullable ItemStack potion) {
+ public void setPotion(final @Nullable ItemStack potion) {
+ this.potion = potion != null ? potion.clone() : null;
+ }
+
@ -81,17 +79,15 @@ index 0000000000000000000000000000000000000000..f1d546a3576a170ecb3608e07befa0f6
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -7,10 +7,10 @@ Control what potion the witch readies to use
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7feca06e72bd585bbfa219df38a2161b77e8d4c4
index 0000000000000000000000000000000000000000..bda48563cc9e00bd9a537ddec0c730b5e784c9a4
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java
@@ -0,0 +1,68 @@
@@ -0,0 +1,65 @@
+package com.destroystokyo.paper.event.entity;
+
+import org.bukkit.entity.Witch;
@ -19,23 +19,23 @@ index 0000000000000000000000000000000000000000..7feca06e72bd585bbfa219df38a2161b
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+public class WitchReadyPotionEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private ItemStack potion;
+ private @Nullable ItemStack potion;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
+ public WitchReadyPotionEvent(final Witch witch, final @Nullable ItemStack potion) {
+ super(witch);
+ this.potion = potion;
+ }
+
+ @NotNull
+ @Override
+ public Witch getEntity() {
+ return (Witch) super.getEntity();
@ -44,8 +44,7 @@ index 0000000000000000000000000000000000000000..7feca06e72bd585bbfa219df38a2161b
+ /**
+ * @return the potion the witch is readying to use
+ */
+ @Nullable
+ public ItemStack getPotion() {
+ public @Nullable ItemStack getPotion() {
+ return this.potion;
+ }
+
@ -54,7 +53,7 @@ index 0000000000000000000000000000000000000000..7feca06e72bd585bbfa219df38a2161b
+ *
+ * @param potion The potion
+ */
+ public void setPotion(@Nullable ItemStack potion) {
+ public void setPotion(final @Nullable ItemStack potion) {
+ this.potion = potion != null ? potion.clone() : null;
+ }
+
@ -64,17 +63,15 @@ index 0000000000000000000000000000000000000000..7feca06e72bd585bbfa219df38a2161b
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Add EntityTeleportEndGatewayEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..88b9c059f9d66877260c66496443ad0aefaf8f47
index 0000000000000000000000000000000000000000..cea029bfbd526d21509dee69bbfad44323107cf2
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java
@@ -0,0 +1,33 @@
@ -17,17 +17,18 @@ index 0000000000000000000000000000000000000000..88b9c059f9d66877260c66496443ad0a
+import org.bukkit.entity.Entity;
+import org.bukkit.event.entity.EntityTeleportEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired any time an entity attempts to teleport in an end gateway
+ */
+@NullMarked
+public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent {
+
+ @NotNull private final EndGateway gateway;
+ private final EndGateway gateway;
+
+ @ApiStatus.Internal
+ public EntityTeleportEndGatewayEvent(@NotNull Entity entity, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) {
+ public EntityTeleportEndGatewayEvent(final Entity entity, final Location from, final Location to, final EndGateway gateway) {
+ super(entity, from, to);
+ this.gateway = gateway;
+ }
@ -37,7 +38,6 @@ index 0000000000000000000000000000000000000000..88b9c059f9d66877260c66496443ad0a
+ *
+ * @return EndGateway used
+ */
+ @NotNull
+ public EndGateway getGateway() {
+ return this.gateway;
+ }

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index f154c5607b1dc3585052d9f02cf8b28cf8a3c886..7b53064364e206bc1a0f4b7af4931f6c658b7c55 100644
index e6bdfd14bffa394cd717de7118de951a997f50b3..2d4d93a4fc3f712a21bd61e203407f3a84e16310 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -837,5 +837,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@@ -847,5 +847,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
*/
@Deprecated
void setArrowsStuck(int arrows);

View file

@ -8,10 +8,10 @@ Plugins can skip selection of certain arrows and control which is used.
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f30c4c372c92a79fb6c3fe80c4b51b5c8c0d4d3b
index 0000000000000000000000000000000000000000..3eadfae8860a4f6cde107cc3c7048368ade29d28
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java
@@ -0,0 +1,94 @@
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
+ *
@ -42,21 +42,22 @@ index 0000000000000000000000000000000000000000..f30c4c372c92a79fb6c3fe80c4b51b5c
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called when a player is firing a bow and the server is choosing an arrow to use.
+ */
+@NullMarked
+public class PlayerReadyArrowEvent extends PlayerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ @NotNull private final ItemStack bow;
+ @NotNull private final ItemStack arrow;
+ private final ItemStack bow;
+ private final ItemStack arrow;
+
+ private boolean cancelled;
+
+ public PlayerReadyArrowEvent(@NotNull Player player, @NotNull ItemStack bow, @NotNull ItemStack arrow) {
+ public PlayerReadyArrowEvent(final Player player, final ItemStack bow, final ItemStack arrow) {
+ super(player);
+ this.bow = bow;
+ this.arrow = arrow;
@ -65,7 +66,6 @@ index 0000000000000000000000000000000000000000..f30c4c372c92a79fb6c3fe80c4b51b5c
+ /**
+ * @return the player is using to fire the arrow
+ */
+ @NotNull
+ public ItemStack getBow() {
+ return this.bow;
+ }
@ -73,7 +73,6 @@ index 0000000000000000000000000000000000000000..f30c4c372c92a79fb6c3fe80c4b51b5c
+ /**
+ * @return the arrow that is attempting to be used
+ */
+ @NotNull
+ public ItemStack getArrow() {
+ return this.arrow;
+ }
@ -92,16 +91,15 @@ index 0000000000000000000000000000000000000000..f30c4c372c92a79fb6c3fe80c4b51b5c
+ * Cancel use of this arrow. On cancel, the server will try the next arrow available and fire another event.
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }

View file

@ -12,10 +12,10 @@ Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..beb1715e30ec476e3031c247285d0d3219e8a8ea
index 0000000000000000000000000000000000000000..6f376e1ac0f2f44255993b3d5b144f5559d13cc3
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java
@@ -0,0 +1,51 @@
@@ -0,0 +1,52 @@
+package com.destroystokyo.paper.event.entity;
+
+import io.papermc.paper.event.entity.EntityKnockbackEvent;
@ -23,19 +23,20 @@ index 0000000000000000000000000000000000000000..beb1715e30ec476e3031c247285d0d32
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.util.Vector;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * 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.
+ */
+@NullMarked
+public class EntityKnockbackByEntityEvent extends EntityPushedByEntityAttackEvent {
+
+ private final float knockbackStrength;
+
+ @ApiStatus.Internal
+ public EntityKnockbackByEntityEvent(final @NonNull LivingEntity entity, final @NonNull Entity hitBy, final EntityKnockbackEvent.@NonNull Cause cause, final float knockbackStrength, final @NonNull Vector knockback) {
+ public EntityKnockbackByEntityEvent(final LivingEntity entity, final Entity hitBy, final EntityKnockbackEvent.Cause cause, final float knockbackStrength, final Vector knockback) {
+ super(entity, cause, hitBy, knockback);
+ this.knockbackStrength = knockbackStrength;
+ }
@ -44,7 +45,7 @@ index 0000000000000000000000000000000000000000..beb1715e30ec476e3031c247285d0d32
+ * @return the entity which was knocked back
+ */
+ @Override
+ public @NonNull LivingEntity getEntity() {
+ public LivingEntity getEntity() {
+ return (LivingEntity) super.getEntity();
+ }
+
@ -62,17 +63,17 @@ index 0000000000000000000000000000000000000000..beb1715e30ec476e3031c247285d0d32
+ *
+ * @return the Entity which hit
+ */
+ public @NonNull Entity getHitBy() {
+ public Entity getHitBy() {
+ return super.getPushedBy();
+ }
+
+}
diff --git a/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b103e03a6
index 0000000000000000000000000000000000000000..bc120d4928dc41ea827e2a06f7d30d0e3d484ce0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java
@@ -0,0 +1,116 @@
@@ -0,0 +1,117 @@
+package io.papermc.paper.event.entity;
+
+import com.google.common.base.Preconditions;
@ -81,14 +82,15 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.util.Vector;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called when an entity receives knockback.
+ * @see EntityPushedByEntityAttackEvent
+ * @see com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent
+ */
+@NullMarked
+public class EntityKnockbackEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
@ -98,7 +100,7 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public EntityKnockbackEvent(final @NonNull Entity entity, final EntityKnockbackEvent.@NonNull Cause cause, final @NonNull Vector knockback) {
+ public EntityKnockbackEvent(final Entity entity, final EntityKnockbackEvent.Cause cause, final Vector knockback) {
+ super(entity);
+ this.cause = cause;
+ this.knockback = knockback;
@ -109,7 +111,7 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+ *
+ * @return the cause of the knockback
+ */
+ public EntityKnockbackEvent.@NonNull Cause getCause() {
+ public EntityKnockbackEvent.Cause getCause() {
+ return this.cause;
+ }
+
@ -121,7 +123,7 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+ *
+ * @return the knockback
+ */
+ public @NonNull Vector getKnockback() {
+ public Vector getKnockback() {
+ return this.knockback.clone();
+ }
+
@ -130,7 +132,7 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+ *
+ * @param knockback the knockback
+ */
+ public void setKnockback(final @NonNull Vector knockback) {
+ public void setKnockback(final Vector knockback) {
+ Preconditions.checkArgument(knockback != null, "knockback");
+ this.knockback = knockback.clone();
+ }
@ -146,11 +148,11 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+ }
+
+ @Override
+ public @NonNull HandlerList getHandlers() {
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static @NonNull HandlerList getHandlerList() {
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
@ -191,17 +193,17 @@ index 0000000000000000000000000000000000000000..8aaafa4ea837f54b32497010d121f02b
+}
diff --git a/src/main/java/io/papermc/paper/event/entity/EntityPushedByEntityAttackEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityPushedByEntityAttackEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9d2a7a5bc4e67d8c36047da616046cbedce1d4a
index 0000000000000000000000000000000000000000..7655c3694b9d6b37206fc46bf892004686e0a7dd
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/entity/EntityPushedByEntityAttackEvent.java
@@ -0,0 +1,66 @@
@@ -0,0 +1,67 @@
+package io.papermc.paper.event.entity;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.util.Vector;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Fired when an entity is pushed by another entity's attack. The acceleration vector can be
@ -210,12 +212,13 @@ index 0000000000000000000000000000000000000000..b9d2a7a5bc4e67d8c36047da616046cb
+ * Note: Some entities might trigger this multiple times on the same entity
+ * as multiple acceleration calculations are done.
+ */
+@NullMarked
+public class EntityPushedByEntityAttackEvent extends EntityKnockbackEvent implements Cancellable {
+
+ private final Entity pushedBy;
+
+ @ApiStatus.Internal
+ public EntityPushedByEntityAttackEvent(final @NonNull Entity entity, final EntityKnockbackEvent.@NonNull Cause cause, final @NonNull Entity pushedBy, final @NonNull Vector knockback) {
+ public EntityPushedByEntityAttackEvent(final Entity entity, final EntityKnockbackEvent.Cause cause, final Entity pushedBy, final Vector knockback) {
+ super(entity, cause, knockback);
+ this.pushedBy = pushedBy;
+ }
@ -225,7 +228,7 @@ index 0000000000000000000000000000000000000000..b9d2a7a5bc4e67d8c36047da616046cb
+ *
+ * @return the pushing entity
+ */
+ public @NonNull Entity getPushedBy() {
+ public Entity getPushedBy() {
+ return this.pushedBy;
+ }
+
@ -236,7 +239,7 @@ index 0000000000000000000000000000000000000000..b9d2a7a5bc4e67d8c36047da616046cb
+ * @deprecated use {@link #getKnockback()}
+ */
+ @Deprecated(since = "1.20.6", forRemoval = true)
+ public @NonNull Vector getAcceleration() {
+ public Vector getAcceleration() {
+ return this.knockback; // TODO Clone in 1.21 to not instantly break what was technically already modifiable (call super.getKnockback())
+ }
+
@ -247,7 +250,7 @@ index 0000000000000000000000000000000000000000..b9d2a7a5bc4e67d8c36047da616046cb
+ * @deprecated use {@link #setKnockback(Vector)}
+ */
+ @Deprecated(since = "1.20.6", forRemoval = true)
+ public void setAcceleration(final @NonNull Vector acceleration) {
+ public void setAcceleration(final Vector acceleration) {
+ super.setKnockback(acceleration);
+ }
+

View file

@ -5,6 +5,9 @@ Subject: [PATCH] Expand Explosions API
Add Entity as a Source capability, and add more API choices, and on Location.
Co-authored-by: Esoteric Enderman <90862990+EsotericEnderman@users.noreply.github.com>
Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java
index 3161eae2fa5f03b7d3a5e9945ab659c15cf568c6..af737017ee397f80c44ee02c6cc60cefa07f59c1 100644
--- a/src/main/java/org/bukkit/Location.java
@ -108,10 +111,10 @@ index 3161eae2fa5f03b7d3a5e9945ab659c15cf568c6..af737017ee397f80c44ee02c6cc60cef
/**
* Returns a list of entities within a bounding box centered around a Location.
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 44a74f15bea60ecd8380520e8faaea41a6c261c5..50c1e4957f66826feb0a2eb04293dbd6b5595700 100644
index 44a74f15bea60ecd8380520e8faaea41a6c261c5..c2b5fdaace13c8bd46c073ac6d427fe411d96367 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -1424,6 +1424,88 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@@ -1424,6 +1424,104 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*/
public boolean createExplosion(@NotNull Location loc, float power, boolean setFire);
@ -125,9 +128,25 @@ index 44a74f15bea60ecd8380520e8faaea41a6c261c5..50c1e4957f66826feb0a2eb04293dbd6
+ * @param power The power of explosion, where 4F is TNT
+ * @param setFire Whether or not to set blocks on fire
+ * @param breakBlocks Whether or not to have blocks be destroyed
+ * @param excludeSourceFromDamage whether the explosion should exclude the passed source from taking damage like vanilla explosions do.
+ * @return false if explosion was canceled, otherwise true
+ */
+ public boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire, boolean breakBlocks);
+ public boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire, boolean breakBlocks, boolean excludeSourceFromDamage);
+
+ /**
+ * Creates explosion at given location with given power and optionally
+ * setting blocks on fire, with the specified entity as the source.
+ *
+ * @param source The source entity of the explosion
+ * @param loc Location to blow up
+ * @param power The power of explosion, where 4F is TNT
+ * @param setFire Whether or not to set blocks on fire
+ * @param breakBlocks Whether or not to have blocks be destroyed
+ * @return false if explosion was canceled, otherwise true
+ */
+ default boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire, boolean breakBlocks) {
+ return createExplosion(source, loc, power, setFire, breakBlocks, true);
+ }
+
+ /**
+ * Creates explosion at given location with given power and optionally

View file

@ -9,10 +9,10 @@ such as a bow or eating food.
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
index 48bb08cc7c0af6ebb905d1e175ada0fd7944ca48..ee3086661e11d3d8faec30590be7131648d3b82a 100644
index 0d01fe9c96a1b9076dbd6d031fa8cd41954ea8db..b0cb4377e14da5ef1e155513046c2340ab6e525e 100644
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
@@ -325,7 +325,9 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
@@ -336,7 +336,9 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
* blocking).
*
* @return Whether their hand is raised
@ -23,7 +23,7 @@ index 48bb08cc7c0af6ebb905d1e175ada0fd7944ca48..ee3086661e11d3d8faec30590be71316
/**
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index 7b53064364e206bc1a0f4b7af4931f6c658b7c55..0ed64618b3f62ee984fe4f99dc6a52d5fad7b3cc 100644
index 2d4d93a4fc3f712a21bd61e203407f3a84e16310..434ad8b07b6ee0b0919de8044d14fe3c789e203f 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -202,15 +202,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@ -56,7 +56,7 @@ index 7b53064364e206bc1a0f4b7af4931f6c658b7c55..0ed64618b3f62ee984fe4f99dc6a52d5
public void setItemInUseTicks(int ticks);
/**
@@ -852,4 +858,130 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@@ -862,4 +868,130 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
*/
void setShieldBlockingDelay(int delay);
// Paper end

View file

@ -8,16 +8,17 @@ and to perform an attack.
diff --git a/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..46e0e62d620def237dab44ad24708f1b93a8a1a7
index 0000000000000000000000000000000000000000..09c82908f63233febfe1e07fe756f1c39d23d44f
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java
@@ -0,0 +1,35 @@
@@ -0,0 +1,36 @@
+package com.destroystokyo.paper.entity;
+
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Mob;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public interface RangedEntity extends Mob {
+ /**
+ * Attack the specified entity using a ranged attack.
@ -26,7 +27,7 @@ index 0000000000000000000000000000000000000000..46e0e62d620def237dab44ad24708f1b
+ * @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);
+ void rangedAttack(LivingEntity target, float charge);
+
+ /**
+ * Sets that the Entity is "charging" up an attack, by raising its hands
@ -44,7 +45,7 @@ index 0000000000000000000000000000000000000000..46e0e62d620def237dab44ad24708f1b
+ */
+ @Deprecated(since = "1.19.2")
+ default boolean isChargingAttack() {
+ return isHandRaised();
+ return this.isHandRaised();
+ }
+}
diff --git a/src/main/java/org/bukkit/entity/AbstractSkeleton.java b/src/main/java/org/bukkit/entity/AbstractSkeleton.java

Some files were not shown because too many files have changed in this diff Show more