Compare commits

...
285 Commits
Author SHA1 Message Date
retrooper 04ca446d44 real official commit for 1.8 pre 1 XD, javadoc attached 2021-01-25 13:01:19 +01:00
retrooper d8cfd826c0 official commit for 1.8 pre 1 2021-01-25 13:00:33 +01:00
retrooper 30689a74bd 1.8 pre 1 (removed WrappedPacketOutBlockChange) 2021-01-25 12:29:50 +01:00
retrooper 957adbb3a2 1.8 pre 1 2021-01-25 10:56:57 +01:00
retrooper e59ff04f2b * client version cleanup and enum constants with 2/more protocol versions renamed 2021-01-25 10:34:39 +01:00
retrooper 3511099f78 NMSUtils netty location issues fix attempt,
Direction#equals method implemented
2021-01-25 09:52:41 +01:00
retrooper 7dc6f89585 WrappedPacketOutAnimation cleanup, WrappedPacketOutNamedSoundEffect in the creation (unfinished), NMSUtils netty location issues with some weird obfuscation fix? Allegedly happens with zkm obfuscation, taking a different/better approach at finding the netty location. 2021-01-25 08:46:47 +01:00
retrooper e899b0cebb IllegalStateException thrown when calling a packet listener method causes an exception letting you know to help you find the error. 2021-01-23 13:18:59 +01:00
retrooper 40ba25d011 added PacketEvents#getAPI as a deprecated method for backwards compat 2021-01-23 09:38:01 +01:00
retrooper 43e5e0200a small packetevents cleanups 2021-01-19 18:50:48 +01:00
retrooper 7906ac7fa9 updated 2021-01-18 22:05:45 +01:00
terrarier2111 706f5331b6 Renamed field properly and improved other stuff 2021-01-18 12:34:44 +01:00
retrooper 3e13ea6aaa Merge remote-tracking branch 'origin/dev' into dev 2021-01-18 08:17:24 +01:00
retrooper fb13834048 HANDLER_NAME is now a static variable 2021-01-18 08:17:05 +01:00
retrooper 3e8bd7f649 Merge pull request #92 from LIWKK/patch-19
* Removed debugging mark
2021-01-17 15:55:19 +01:00
Johannes dfc898e0bf * Removed debugging mark 2021-01-17 16:50:15 +02:00
retrooper 38fc0cf4be Merge pull request #91 from LIWKK/patch-18
mSpigot support
2021-01-17 15:46:00 +01:00
Johannes 7204b85664 * Better try catch, it'll always be a or getEntity 2021-01-17 16:33:49 +02:00
retrooper c0642a69a1 Attempt to fix alleged 1.7.10 incompatibilities, possibly a redundant commit 2021-01-17 15:14:55 +01:00
retrooper 251e01f6e7 clientversion resolving caching 2021-01-16 14:10:19 +01:00
retrooper 612a7b50cf clientversion small optimization 2021-01-16 13:49:17 +01:00
retrooper c4d04d10d7 Moved Direction and Hand 2021-01-16 13:27:59 +01:00
retrooper e87bfe0ef9 Merge pull request #88 from Tecnio/dev
Added 3 wrappers
2021-01-16 10:39:30 +01:00
Tecnio 6d87a03412 Added Becaon wrapper 2021-01-16 12:20:37 +03:00
Tecnio 13bea01eac Added ItemName and PickItem wrappers 2021-01-16 12:00:53 +03:00
retrooper 9a8126cc1e WrappedPacketInTeleportAccept wrapper created by Tecnio
Added the WrappedPacketInTeleportAccept wrapper to the API
2021-01-16 09:07:13 +01:00
retrooper 45f705e351 stop shading plib 2021-01-16 09:04:49 +01:00
Tecnio 1c3577a5e7 Added the WrappedPacketInTeleportAccept wrapper to the API 2021-01-16 09:30:28 +03:00
retrooper a2aedf680a Direction util issues fixed 2021-01-15 22:54:48 +01:00
retrooper 14cfb6b8c5 clientversion small improvement 2021-01-15 20:42:25 +01:00
retrooper 5e98e8a192 fixed pom,xml 2021-01-15 18:00:37 +01:00
retrooper bb65610e74 PacketEventsSettings javadoc updated,
Direction is now a class
2021-01-15 16:32:10 +01:00
retrooper 19ccfb87e3 Merge remote-tracking branch 'origin/dev' into dev 2021-01-15 09:15:58 +01:00
retrooper 514298b942 * Use ProtocolLib if it is available (ONLY IF THE INJECTION IS A LATE INJECTION) 2021-01-15 09:15:46 +01:00
retrooper 267480b563 Redundant as we have a wiki page for this 2021-01-14 18:16:35 +01:00
retrooper a50a5f8f89 unwanted 2021-01-14 18:16:19 +01:00
retrooper f06cd69b27 * Project code cleanup
* Concurrent modification exceptions when accessing entities in some wrappers FIXED
2021-01-13 20:01:36 +01:00
retrooper c0bf7f7069 * WrappedPacketOutChat(BaseComponent,ChatPosition,UUID) created, WrappedPacketOutChat.Util removed 2021-01-12 22:12:48 +01:00
retrooper d884c5324d * WrappedPacketOutWorldParticles attempt
* ClientVErsion#isResolved
2021-01-12 21:27:06 +01:00
retrooper 16caeeee89 UpdateChecker code duplication removed 2021-01-12 12:19:02 +01:00
retrooper 17e5d84907 Events cleaned up a bit, using OOP and PostPlayerInjectEvent#isAsync added 2021-01-11 18:12:50 +01:00
retrooper fe4037b850 Cleaned up PacketTypeClasses 2021-01-10 09:22:25 +01:00
retrooper 564f65d2d2 Reinject a tick later if we fail,
and log the error if the second injection fails
2021-01-10 09:18:41 +01:00
retrooper 2a944d9376 back to official tiny attempt 2021-01-09 20:06:20 +01:00
retrooper 3dc1bbc671 back to official tiny attempt 2021-01-09 20:05:50 +01:00
retrooper 1a141b114e Even quicker channel caching 2021-01-09 19:24:26 +01:00
retrooper f9e7589d87 PlayerInjectEvent no longer requires channel as an argument 2021-01-09 19:08:21 +01:00
retrooper f77ab58b3b Channel cache a bit earlier in the early injector 2021-01-09 19:02:51 +01:00
retrooper a3e744d883 Injectors cleanup 2021-01-09 18:57:16 +01:00
retrooper 8680f0f43b Update NMSUtils.java 2021-01-09 16:49:13 +01:00
retrooper a981caa386 EventManagerDynamic fix attempt 2021-01-08 21:13:58 +01:00
retrooper 06644f5fe6 EventManagerDynamic#registerListener bug fix 2021-01-08 20:57:24 +01:00
retrooper bcb79a0ac5 Fixed clientversion in PostPlayerInjectEvent 2021-01-08 16:34:58 +01:00
retrooper b6c48d95db * Tiny optimizations to EventManagerLegacy 2021-01-08 16:25:54 +01:00
retrooper f28092bccb * EventManagerDynamic optimizations (WARNING, registering listeners is not thread safe)
* TurboSpigotUtils (I am developing a paper fork, thinking of optimizaitons I can give packetevents users using the spigot :D )
2021-01-08 16:16:11 +01:00
retrooper a566b6f8cb Cleaned up the injection systems.
Now using interfaces to help cleanup the injectors.
2021-01-07 22:40:25 +01:00
terrarier2111 ba7e178cb1 Cleaned up WrappedPacket 2021-01-07 08:03:48 +01:00
retrooper b88ac0191e Fixed/prevented concurrent modifications when a wrapper loads (on first usage) or when wrapper reads a field(looking into this later) 2021-01-06 22:06:17 +01:00
retrooper f864eeb646 * WrappedPacketOutChat.Util.createHoverMessagePacket(UUID, BaseComponent) :) 2021-01-05 21:44:17 +01:00
retrooper cc2f810be3 * Before last attempt to fix small bug fix for WrappedPacketOutChat.Util 2021-01-05 21:25:17 +01:00
retrooper d41da16c56 * Small bug fix to WrappedPacketOutChat.Util 2021-01-05 21:14:10 +01:00
retrooper 9d3390b1bb WrappedPacketOutChat.Util.createHoverMessagePacket method created for simpler hovering message usage without dealing with JSON 2021-01-05 21:05:16 +01:00
retrooper 3fe96333e1 * WrappedPacketOutChat.Util created 2021-01-05 19:51:08 +01:00
retrooper a17c782c2e * WrappedPacketInSetCreativeSlot#setItemStack(ItemStack) created
* PostPlayerInjectEvent now called async again, but similar approach to last commit (EXPERIMENTAL)
2021-01-05 18:33:18 +01:00
retrooper 2f9a2ce435 Fix WrappedPacketInSetCreativeSlot (UNTESTED WRAPPER) 2021-01-05 10:05:46 +01:00
retrooper d78776be6f * Attempt to fix keepalives and transactions sending 2021-01-05 10:00:21 +01:00
retrooper e23d1a87f6 Merge branch 'dev' of https://github.com/retrooper/packetevents 2021-01-05 09:56:49 +01:00
retrooper b27f86c073 * Now loading status server-bound packet type IDs and login client-bound packet type IDs 2021-01-05 09:56:14 +01:00
retrooper 2a5f5448a4 Merge pull request #86 from NikV2/master
Added wrapper for set creative slot
2021-01-05 01:50:41 +01:00
Nik c84472270e Added wrapper for set creative slot 2021-01-05 02:41:50 +02:00
retrooper e3b667d5b2 WrappedPacketInUseEntity hopefully fixing bugs for 1.7.10 trash modified spigot users xd 2021-01-03 21:13:59 +01:00
retrooper 7079c50deb WrappedPacketOutBlockChange#WrappedPacketOutBlockChange(int, int, int, World) constructor now works 2021-01-03 16:25:04 +01:00
retrooper b3e07b9188 * WrappedPacketInSpectate created 2021-01-03 13:16:40 +01:00
retrooper 41427d8698 * WrappedPacketInEnchantItem wrapper created 2021-01-03 11:53:05 +01:00
retrooper 6e2177e27c * NMSUtils bug fix 2021-01-02 21:59:04 +01:00
retrooper 25bba6e306 Early and Late channel injector issues fix attempt 2021-01-02 21:52:29 +01:00
retrooper 64c0c79edd * Cleaned up all files
* WrappedPacketOutBlockChange sendable FINISHED(UNTESTED, EXPERIMENTAL)
2021-01-02 18:50:24 +01:00
terrarier2111 9f6e79cb16 Improved performance of ClientVersion#isPreRelease 2021-01-02 18:34:57 +01:00
retrooper 917959743e * PostPlayerInjectEvent small bug fixes
* ClientVersion#isPreRelease added
2021-01-02 15:54:28 +01:00
retrooper 577660b58c * small temp fix for the shaders 2021-01-01 22:26:07 +01:00
retrooper 4377d85a05 * WrappedPacketOutBlockChange progress (UNFINISHED)
* WrappedPacketOutEntityMetadata progress (UNFINISHED)
* PostPlayerInjectEvent not being called fix ATTEMPT
2021-01-01 22:20:53 +01:00
terrarier2111 fb8fcf7d50 Cleaned up EventManagerDynamic 2021-01-01 21:19:14 +01:00
retrooper faf8e4664c * EventManagerDynamic using HashSets for the listeners in the map 2021-01-01 21:16:11 +01:00
retrooper 7e52b8e979 Merge remote-tracking branch 'origin/dev'
# Conflicts:
#	src/main/java/io/github/retrooper/packetevents/PacketEventsPlugin.java
#	src/main/java/io/github/retrooper/packetevents/packetwrappers/play/out/custompayload/WrappedPacketOutCustomPayload.java
2021-01-01 21:13:22 +01:00
retrooper 55ab2fa043 * WrappedPacketOutBlockChange wrapper created 2021-01-01 21:13:10 +01:00
terrarier2111 560a1b5e2f Fixed my stupidity 2021-01-01 20:46:54 +01:00
terrarier2111 db61b202c0 Merge branch 'dev' of https://github.com/retrooper/packetevents
 Conflicts:
	src/main/java/io/github/retrooper/packetevents/PacketEventsPlugin.java
2021-01-01 20:43:58 +01:00
terrarier2111 ebc697dd89 Cleaned up ByteBufUtil 2021-01-01 20:42:11 +01:00
retrooper 784d99c03d * ClientVersion resolving issues fix attempt 2020-12-31 19:24:30 +01:00
terrarier2111 d48ab480c9 Fixed a bug in ByteBufUtil 2020-12-31 18:35:58 +01:00
terrarier2111 052f1108c3 Took executor service type into account when naming threads 2020-12-31 16:35:25 +01:00
retrooper b42f5b68ca * PacketEvents executing listeners(when enabled in the settings and in the listener) on its own threads REMOVED due to event order processing incompatibilities, event cancelling incompatibilities, packet modification incompatibilities
* Attempted to fix the client version not being resolved
2020-12-24 13:01:09 +01:00
retrooper 3926c48114 * PacketEventsSettings#injectAndEjectThreadCount(int) and PacketEventsSettings#packetProcessingThreadCount(int) should now affect 2020-12-24 12:12:33 +01:00
terrarier2111 0a5f2d2b8e Added custom ThreadFactories to internal thread pools 2020-12-24 01:15:01 +01:00
retrooper 57f80b5196 minor change to readme 2020-12-21 23:50:55 +01:00
retrooper 7ac3b7e65b minor change 2020-12-21 23:49:24 +01:00
retrooper 4ce2f88d4a minor correction 2020-12-21 23:47:54 +01:00
retrooper 374025f5bf small changes 2020-12-21 23:47:10 +01:00
retrooper 450da1ce3f few corrections 2020-12-21 23:44:55 +01:00
retrooper 4a5cfd141a small correction 2020-12-21 23:40:23 +01:00
retrooper 56ea329b5c small corrections 2020-12-21 23:39:34 +01:00
retrooper 3104cda55e readme is a bit more professional now 2020-12-21 23:35:19 +01:00
retrooper 111b28ba7e Update README.md 2020-12-21 22:24:03 +01:00
retrooper 7754a6e183 Update README.md 2020-12-21 22:23:02 +01:00
retrooper 2d2063cac2 small bug fix 2020-12-21 20:07:09 +01:00
retrooper 494edfa095 fixed wrapper loading issues for sent wrappers 2020-12-21 19:40:46 +01:00
retrooper e3a9d4e6de * SubclassUtil#getSubClass potential NPEs prevented
* WrappedPacketInResourcePackStatus wrapper created
* WrappedPacketInTrSel (Trade Select) wrapper created
* WrappedPacketOutCamera wrapper created (and sendable)
* WrappedPacketOutUpdateTime wrapper created (and sendable)
2020-12-21 18:49:26 +01:00
retrooper c8f766735a * Player injection failures bug fix(early injector)
* Player disconnected bug fix

* PacketListenerDynamic#getThreadMode added, and added PacketListenerThreadMode to the PacketListenerDynamic constructor to decide what threads PE should use to process your listener
* PacketType ID resolving on all events bug fixed
2020-12-21 16:33:10 +01:00
terrarier2111 83899c8fac Removed redundant clone call in ServerVersion$reverse 2020-12-20 20:00:26 +01:00
retrooper 99d56a520e * Redundant imports removed 2020-12-20 15:31:09 +01:00
retrooper c1b2caad8b * Debugs removed 2020-12-20 15:30:48 +01:00
retrooper 53cd0feba3 * Documented all the early injectors, some internal utils, all non internal utils
TODO: document all internal utils, late injectors, packettype and packettypeclasses.

* public WrappedPacket(Object packet) -> public WrappedPacket(NMSPacket packet)

Only will affect dynamic wrapper system users.
WrappedPacket myWrapper = new WrappedPacket(object); -> WrappedPacket myWrapper = new WrappedPacket(new NMSPacket(object));
2020-12-20 15:28:51 +01:00
retrooper e83945d875 Update README.md 2020-12-20 06:45:38 +01:00
retrooper 31def9a711 fix to sending wrappedpacketoutkeepalive 2020-12-19 13:03:02 +01:00
retrooper b4514dca63 * Debug code removed 2020-12-18 19:00:46 +01:00
retrooper add5f9853d * WrappedPacketOutOpenWindow NOT SENDABLE YET, attempt
* MainExample.java -> PacketEventsPlugin
* EarlyChannelInjector documented
2020-12-18 19:00:14 +01:00
retrooper 419c08780f * PacketEvents.get().getPlayerUtils().getClientVersion(Player) won't return the server version(if viaversion, protocolsupport or other similar plugins are present), to be sure we return null until we get a response from their APIs 2020-12-17 20:55:33 +01:00
retrooper d39b50b02c Merge pull request #85 from LIWKK/patch-17
Added NamedEntitySpawn
2020-12-17 16:27:22 +01:00
Johannes 2d8b2ae523 Added NamedEntitySpawn 2020-12-17 17:09:19 +02:00
terrarier2111 3e5366f374 Improved caching in EventManagerDynamic 2020-12-16 23:37:08 +01:00
retrooper 2b10325f7f wrappedpacketoutresourcepacksend now working on 1.7.10 2020-12-16 23:00:43 +01:00
retrooper 4c5fdf6dce Update WrappedPacketOutResourcePackSend.java 2020-12-16 22:51:37 +01:00
retrooper 8a8616c124 wrappedpacketoutresourcepacksend syntax error fix 2020-12-16 22:42:50 +01:00
retrooper 8095e506e4 bug fix attempt for 1.7.10 on resourcepacksend wrapper 2020-12-16 22:37:41 +01:00
retrooper e067208755 Named Entity Spawn Packet ID by LIWKK 2020-12-16 18:26:46 +01:00
Johannes f9bf042178 Added Named entity spawn 2020-12-16 19:12:22 +02:00
retrooper 23db4a6506 * PacketEventPriority is now an enum
* WrappedPacketOutResourcePackSend wrapper(sendable) added
* WrappedPacketInCloseWindow wrapper added
* WrappedPacketOutCloseWindow wrapper(sendable) added
2020-12-15 17:33:39 +01:00
retrooper 2e0468ed74 * Should fix issues with multiple packetevents shades incompatibilities and they will all use ONE of the shaded ones.
The one that loaded as a plugin the first will be the selected one.

* Moved to maven-shade-plugin for shading, no longer using the outdated method
2020-12-15 16:40:15 +01:00
retrooper e932fb5707 * Lots and lots of documentation, all that is left is the injector classes, PacketType.java, All wrappers, PacketEventsSettings.java, UpdateChecker.java, all utilities and the PacketEvents.java class. 2020-12-13 16:19:41 +01:00
retrooper 337551119b * Fixed duplicate post player injection event calls 2020-12-13 11:50:52 +01:00
retrooper 7ec7336b9a Ton of refactoring
* PacketReceiveEvent.java -> PacketPlayReceiveEvent
* PacketSendEvent.java -> PacketPlaySendEvent

* PacketLoginEvent.java -> PacketLoginReceiveEvent & PacketLoginSendEvent

* PacketStatusEvent.java -> PacketStatusReceiveEvent & PacketStatusSendEvent

* PacketListenerDynamic#onPacketReceive -> PacketListenerDynamic#onPacketPlayReceive
* * PacketListenerDynamic#onPacketSend -> PacketListenerDynamic#onPacketPlaySend

* PacketListenerDynamic#onPacketLogin -> PacketListenerDynamic#onPacketLoginReceive & PacketListenerDynamic#onPacketLoginSend

* PacketListenerDynamic#onPacketStatus -> PacketListenerDynamic#onPacketStatusReceive & PacketListenerDynamic#onPacketStatusSend

* PacketListenerDynamic#onPostPacketReceive -> PacketListenerDynamic#onPostPacketPlayReceive
* PacketListenerDynamic#onPostPacketSend -> PacketListenerDynamic#onPostPacketPlaySend
2020-12-13 11:13:18 +01:00
retrooper a136729532 Merge remote-tracking branch 'origin/dev' into dev 2020-12-12 16:11:01 +01:00
retrooper 2da41d03ef * PostPlayerInjectEvent#getClientVersion now supports ViaBackwards and ViaRewind as they take longer to resolve client version, this results in the PostPlayerInjectEvent being called later 2020-12-12 16:10:40 +01:00
terrarier2111 3c65754fca Merge pull request #81 from retrooper/terrarier2111-patch-1
Create codeql-analysis.yml
2020-12-11 22:42:51 +01:00
terrarier2111 688931aa7e Create codeql-analysis.yml 2020-12-11 22:41:43 +01:00
terrarier2111 e5338caa29 Improved some stuff 2020-12-09 21:00:07 +01:00
retrooper b45bc73396 * Fixed bugs
* PacketReceiveEvent#getPlayer and PacketSendEvent#getPlayer are annotated with @NotNull now.
2020-12-09 20:28:04 +01:00
retrooper 918d5b89ef Merge remote-tracking branch 'origin/dev' into dev 2020-12-09 18:50:03 +01:00
retrooper 9f06d583ab * Test commit 2020-12-09 18:49:23 +01:00
retrooper 1c87cf7982 Created FUNDING.yml 2020-12-09 18:39:06 +01:00
retrooper 75f7eaf74f Created FUNDING.yml 2020-12-09 18:38:40 +01:00
retrooper a4f4163412 Created feature issue template 2020-12-09 15:19:50 +01:00
retrooper ef529b7949 Create feature issue template 2020-12-09 15:19:11 +01:00
retrooper 6e52acb677 Added Bug report template 2020-12-08 22:52:08 +01:00
retrooper 826695a677 Update bug template 2020-12-08 22:49:07 +01:00
retrooper e403469e52 Contributor Code of Conduct File added
Create CONTRIBUTOR_CODE_OF_CONDUCT.md
2020-12-08 22:32:04 +01:00
retrooper 084acb8894 Create CONTRIBUTOR_CODE_OF_CONDUCT.md 2020-12-08 22:31:29 +01:00
retrooper 948e260460 Merge remote-tracking branch 'origin/dev' into dev 2020-12-08 08:46:57 +01:00
retrooper f4efdea4b2 * WrappedPacketInAbilities now loads
* ClientVersion is removed when a client leaves.
2020-12-08 08:46:24 +01:00
terrarier2111 1cb7730c3c Improved some stuff 2020-12-07 19:59:21 +01:00
terrarier2111 5b558b50e2 Merge branch 'dev' of https://github.com/retrooper/packetevents
 Conflicts:
	src/main/java/io/github/retrooper/packetevents/utils/nms/NMSUtils.java
2020-12-07 19:48:06 +01:00
retrooper 00986f2341 * WrappedPacketInAbilities bug fix for 1.16 2020-12-07 18:18:35 +01:00
retrooper b83e8887ff * small bug fixes 2020-12-07 18:11:25 +01:00
retrooper 7bfadfa233 dev build 9 for 1.7.9
* pretty stable, all known bugs fixed
2020-12-07 17:58:35 +01:00
retrooper a3f75f1237 *nms util cache fix 2020-12-07 17:46:25 +01:00
retrooper 1e21d3f6ea * Bug fix with cached information not being deleted when a player quits
* All events having to do with a PACKET has the #getSocketAddress() method returning an InetSocketAddress.java
2020-12-07 17:44:35 +01:00
terrarier2111 73d0c6ea7d Readded caching for internal method 2020-12-07 16:04:58 +01:00
retrooper 278b27da6b * Bugs fixed on newer versions with the EarlyChannelInjector
* NMSUtils fixed some bugs
* PacketListenerDynamic new constructor, default priority is PacketEventPriority.NORMAL
* Reflection bugs fixed
2020-12-07 15:01:46 +01:00
retrooper fbb0692f80 Merge remote-tracking branch 'origin/dev' into dev 2020-12-06 09:59:46 +01:00
retrooper f4307ab524 * ProtocolLib support REMOVED
* PacketEventsSettings#useProtocolLibIfAvailable(boolean) removed
* Channel ejection fixed
2020-12-06 09:59:16 +01:00
terrarier2111 cafda14c89 Improved and cleaned up NMSUtils 2020-12-04 20:20:08 +01:00
terrarier2111 2e7e81be9f Improved NMSUtils 2020-12-04 20:01:05 +01:00
terrarier2111 83b5697d40 Renamed Direction method and optimized imports 2020-12-04 19:19:11 +01:00
terrarier2111 e0a1c39e54 Improved some stuff in Direction enum 2020-12-04 19:14:01 +01:00
retrooper 6608203ddc * Reflection#getMethod StackOverFlow fix 2020-12-04 18:08:58 +01:00
retrooper 1f811ba90e * Hotfix for ProtocolLib Support 2020-12-04 18:03:05 +01:00
retrooper 70f33f56e8 * Fix WrappedPacketInUseEntity 2020-12-04 17:59:30 +01:00
retrooper 39c2a157c4 * Quick fix to ProtocolLib support 2020-12-04 17:54:08 +01:00
retrooper 761352cbbc * PROTOCOLLIB LISTENER USAGE WHEN AVAILABLE SUPPORT ATTEMPT
This is untested.

* PacketLoginEvent#getChannel replaced with PacketLoginEvent#getSocketAddress
Same with PacketStatusEvent

* ClientVersion cached with a InetSocketAddress instead of netty channel
2020-12-04 17:39:46 +01:00
retrooper 44016e1a03 * Direction small changes
* Vector3i.INVALID created
* ClientVersion small changes
2020-12-04 11:12:24 +01:00
retrooper a2233c434a * Minor documentation change appended to NMSPacketEvent's documentation 2020-12-04 10:31:55 +01:00
retrooper fb4863cbe9 * Appended to NMSPacketEvent's documentation 2020-12-04 10:22:50 +01:00
retrooper e60d50a957 * Cleaned up all events to do with packets reducing documentation duplication 2020-12-04 10:19:42 +01:00
retrooper c53d69d03c * PacketType and PacketTypeClasses refactored issues fixed 2020-12-04 09:53:38 +01:00
retrooper 9e294d7185 * More documentation, a lot more to go :c 2020-12-04 09:33:13 +01:00
retrooper e9cd983131 * Nullable.java removed
* Direction minor optimization
* Documented a lot of files. More documentation to come.
2020-12-03 19:35:37 +01:00
terrarier2111 e6798d4901 Cleaned up some more reflect code 2020-12-03 18:38:58 +01:00
terrarier2111 1c0e8cdd91 Cleaned up some more reflect code 2020-12-03 18:02:23 +01:00
terrarier2111 a3f9fc9cb3 Fixed reflect read indexes 2020-12-03 15:57:32 +01:00
retrooper 808bbabff1 * Hand enum added to WrappedPacketInUseEntity
* Vector3d target vector added to WrappedPacketInUseEntity
* WrappedPacket has been cleaned up and optimized(basically all wrappers)
We no longer cache all fields, we only cache all fields that are accessed...
* WrappedPacketInTabComplete created only supporting the #getText() method as the text field is the only field that doesn't get removed across 1.7.10->1.16.4
2020-12-03 15:12:07 +01:00
terrarier2111 4a5e579256 Minor improvements 2020-12-03 14:01:05 +01:00
retrooper 7c74d22700 * PacketManager.java renamed to PacketHandlerInternal and moved. 2020-12-03 09:17:36 +01:00
retrooper cf11930f05 * Code optimizations(removal of redundant imports, ...) 2020-12-02 10:17:08 +01:00
retrooper f814d20cbb * Fixed bugs to do with the EarlyChannelInjector 2020-12-02 10:08:27 +01:00
retrooper 6313fca6fa NMSUtils compilation error fixed 2020-12-02 01:13:58 +01:00
retrooper f0bcfc62c8 NMSUtils Minecraft Server Instance bug fix
Only failed on newer minecraft versiobs
2020-12-02 01:02:10 +01:00
retrooper cf930c6013 * Fixed bugs 2020-12-01 16:55:48 +01:00
retrooper 052a65f6ef * PacketManager micro optimization with the channel caching
* Player ejected when they leave
2020-12-01 16:12:42 +01:00
retrooper 4078418376 * PostPlayerInjectEvent is now called BEFORE the first PacketReceive/Send event, will ALWAYS only be called on successful injections and is called async(due to me already being in an async context). 2020-12-01 15:32:14 +01:00
retrooper 68e8d4f788 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	src/main/java/io/github/retrooper/packetevents/packetmanager/tinyprotocol/TinyProtocol7.java
#	src/main/java/io/github/retrooper/packetevents/packetmanager/tinyprotocol/TinyProtocol8.java
2020-12-01 12:07:58 +01:00
retrooper be6e0ce222 * TinyProtocol removed, wrote my own similar version of it
* All play wrappers refactored to io.github.retrooper.packetevents.packetwrappers.play.(in/out)
* Vector3d utility class created and added to many wrappers that have to do with a position or delta(doubles).
2020-12-01 12:05:15 +01:00
terrarier2111 67dd097a0f Renamed constants properly 2020-11-30 15:12:07 +01:00
terrarier2111 ed9007da44 Improved caching 2020-11-30 14:58:04 +01:00
terrarier2111 81632cdf6d Revert "Improved caching"
This reverts commit 79c07642
2020-11-30 14:46:04 +01:00
terrarier2111 727e02a235 Revert "Renamed constants properly"
This reverts commit 05a981de
2020-11-30 14:46:00 +01:00
terrarier2111 39e105c69c Revert "Other improvements"
This reverts commit 1a2145b4
2020-11-30 14:45:51 +01:00
terrarier2111 1a2145b413 Other improvements 2020-11-30 14:44:04 +01:00
terrarier2111 05a981de6e Renamed constants properly 2020-11-30 14:43:51 +01:00
terrarier2111 79c07642a2 Improved caching 2020-11-30 14:39:49 +01:00
retrooper e2352fe3bf *.github file deleted 2020-11-30 14:06:55 +01:00
retrooper 2d9ac56f2e * Project code cleanup (Unused imports removed, code reformatted...) 2020-11-30 14:03:32 +01:00
retrooper 8e1d70b6be * pom.xml added 2020-11-30 13:15:53 +01:00
retrooper 7c6a675173 * Reverted back to maven
* Optimized dynamic event manager event calls
* WrappedPacketInBlockPlace#getDirection bug fixes
* WrappedPacketInBlockDig#getDirection bug fixes
* PacketEvents static usages reduced, API cleaned up
2020-11-30 13:03:35 +01:00
terrarier2111 feeff01654 Minor improvement 2020-11-29 22:36:32 +01:00
retrooper 0e53005867 CONTRIBUTING information file 2020-11-28 11:34:11 +01:00
retrooper 98b4ee2bac Created CONTRIBUTING.md
Please read this file if you are planning on contributing.
2020-11-28 11:33:29 +01:00
retrooper efc2dc1c54 Update README.md 2020-11-26 10:58:25 +01:00
retrooper 827c974908 * added gradle-wrapper.jar 2020-11-26 10:26:31 +01:00
retrooper 05b9c8efca * added gradle-wrapper.properties 2020-11-26 10:25:04 +01:00
retrooper 42a9745196 * removed gitgnore 2020-11-26 10:11:31 +01:00
retrooper 5a283b7ffa * Moved from maven to gradle.
pom.xml has been removed.
2020-11-26 10:09:01 +01:00
retrooper 59d25df76b Update NMSUtils.java 2020-11-25 19:34:24 +01:00
retrooper c42a00ddcf * WrappedPacketLoginOutCustomPayload load issues fix attempt
* WrapperPacketWriter#writeObject created and implemented in WrappedPacket, WrappedPacket#writeObject
2020-11-25 18:09:50 +01:00
retrooper b3e06caf7c * PEVersion#compare(PEVersion) renamed to PEVersion#compareTo(PEVersion) 2020-11-25 17:55:23 +01:00
retrooper a0b84c0552 * PEVersion cleaned up and optimized and updated its usages 2020-11-25 17:49:31 +01:00
retrooper e8be5eb8ba * PacketEvents.getSettings().injectionFailureMessage(String) can be used to modify the injection failure kick message
* PacketType.Login and PacketType.Status now easier to use
PacketType.Status.Client are the client side status packets and PacketType.Status.Server are the server side status packets, same applies to the Login class.
* WrappedPacketLoginInCustomPayload & WrappedPacketLoginOutCustomPayload bugs fixed

* All login and status wrappers' package locations have been moved

* Small potential bug fix for TinyProtocol async player injection failures
2020-11-25 14:20:02 +01:00
retrooper 2531988a59 * WrappedPacketLoginOutSetCompression is now sendable
* WrappedPacketLoginInCustomPayload has been finished
* WrappedPacketLoginOutCustomPayload created and is sendable
* PacketType.Login.Client and PacketType.Login.Server created for easier usage
* PacketType.Login.Server.SET_COMPRESSION id newly created
2020-11-25 08:52:50 +01:00
retrooper 7204b06870 * PacketEvents.getAPI().getPlayerUtils().sendPacket(NETTY_CHANNEL, SENDABLE_WRAPPER); created
* PacketEvents.getAPI().getPlayerUtils().sendPacket(NETTY_CHANNEL, RAW_NMS_PACKET); created
2020-11-25 07:57:53 +01:00
retrooper 6289543ea5 * PostPlayerInjectEvent now supported in the new event system. 2020-11-24 15:16:09 +01:00
retrooper 6a1ce5e234 * Issues with ClientVersion, when one minecraft instance is on the server and another one on the server list, the one on the server list overwrites the online client's version
* ClientVersion class small cleanup and optimization
2020-11-24 10:04:04 +01:00
retrooper bd1e4e7e6d 1.7.9 release
Update!
2020-11-23 13:00:47 +01:00
retrooper feda5b96b6 * PostPlayerInjectEvent added, called after successful injection 2020-11-23 12:58:54 +01:00
retrooper 809396ff21 1.7.9 release 2020-11-23 12:36:11 +01:00
retrooper 2428487eb1 * UpdateChecker bugs fixed, PEVersion#equals(PEVersion) now works 2020-11-23 08:41:20 +01:00
retrooper df0c769111 * VersionLookupUtils prioritization changed up, 1. ViaVersion, 2. ProtocolLib, 3. ProtocolSupport 2020-11-23 07:45:22 +01:00
retrooper 5e0cd75bb0 attempt to fix protoclsupport/viaversion erroring when asked for protocolversion, but not successful 2020-11-22 17:57:55 +01:00
retrooper b21e6b4a67 * PacketEvents injecting is done with event priority on LOW for late injections, and ClientVersion resolving with HIGH event priority 2020-11-22 17:46:56 +01:00
retrooper bfc3aa7ad8 * PacketEvents.onJoin priority set to HIGHEST 2020-11-22 17:27:19 +01:00
retrooper 72458ddfd2 * PacketEvents failing to inject you and doesn't call any events for your player (RARE BUG) fixed. This bug could only happened if you had injectEarly set to true. 2020-11-22 17:07:21 +01:00
retrooper a8a04b137b * ClientVersion unresolvable on 1.16.3 and 1.16.4 bug FIXED 2020-11-22 16:40:39 +01:00
retrooper 4e11df1fc7 Update EventManagerDynamic.java 2020-11-21 21:19:48 +01:00
Retrooper c3ab35bd6b * reverted to old entity finder util 2020-11-21 13:11:20 +08:00
retrooper af1025da1f caching entity ID im wrappedpacketoutentityteleport now 2020-11-21 04:54:16 +01:00
retrooper f2ce9eacb1 WrappedPacketOutEntityTeleport Entity ID always 0 2020-11-21 04:50:20 +01:00
retrooper 27307e034b Merge branch 'dev' of https://github.com/retrooper/packetevents into dev 2020-11-20 11:00:16 +01:00
retrooper 808357735f * PacketEventsLoadFailureException now includes the cause exception.
* VersionLookupUtils now prioritizes ProtocolSupport over ViaVersion
2020-11-20 10:59:02 +01:00
retrooper ece8b6d395 WrappedPacketOutEntity Entity ID 0 Bug fix 2020-11-20 04:12:22 +01:00
retrooper 8643e14900 WrappedPacketOutEntity Entity ID 0 bug fix 2020-11-20 04:10:49 +01:00
retrooper cbfd52d926 * PacketEvents-Bungee utilities removed and bungee server startup error fix.
* PacketEventsMethodInvokeException now actually includes the cause of the error.
* PacketEventsNMSCachedEntityNotFoundException.java renamed to PacketEventsEntityByIDNotFoundException.java.
* Reflection methods to do with fields DEPRECATED, use the WrappedPacket utility class.
* ClassUtil.getClassSimpleName(Class<?> cls) potential bug fix, if a class was named "null" it would have not cached  do to a string null check.
2020-11-19 17:47:27 +01:00
retrooper e266e43d19 * WrappedPacketOutChat constructor
* pom.xml stopped compiling ProtocolSupport
* All event classes now cache packet ID
2020-11-19 10:00:07 +01:00
retrooper c9d58e08c9 1.7.8 release 2020-11-17 15:34:56 +01:00
retrooper 24eda2b3a5 1.7.8 release
* Official 1.16.4 support
ClientVersion.v_1_16_4, ServerVersion.v_1_16_4 created
* Unfortunately PacketEvents.getSettings().useProtocolLibIfAvailable(boolean) setting most likely won't be coming back
* Bungee client version resolving bug fixed
* Recommended to have ViaVersion, ProtocolSupport or ProtocolLib on your spigot server, as PacketEvents makes use of them to resolve client version ONLY if they are available.
They are required on the spigot server ONLY if you have a bungee network.
* Interruption of PacketEvents.stop() protected
2020-11-17 15:32:37 +01:00
retrooper 38c4f3234d Merge pull request #66 from retrooper/dev
1.7.7 release
2020-11-16 17:55:11 +01:00
retrooper e94b6f24dc 1.7.7 release
* Accessing Entity by ID on servers with more than one world ERROR FIX
* In the WrappedPacketOutChat(String, ChatPosition, UUID) constructor, the String(=message) shouldn't be passed in JSON string format, it can be passed in as an ordinary string message!
Example:
WrappedPacketOutChat packet = new WrappedPacketOutChat("Hello", ChatPosition.CHAT, uuid);
2020-11-16 17:52:37 +01:00
retrooper 85dab8eb7a 1.7.6 release
1.7.6 release
2020-11-15 12:48:42 +01:00
retrooper 5fb8634880 * PacketEventsNMSCachedEntityNotFoundException exception created and is thrown when the cached nms entity isn't found.
WrappedPacketOutBlockChange wrapper TODO
2020-11-15 12:08:42 +01:00
retrooper e551421867 Reverted to old legacy event manager code
* Lower event priorities aren't called before higher ones on the legacy event system.
* PacketEvents.getSettings().useProtocolLibIfAvailable temporarily removed, currently unsupported so has been removed.
It is recommended to slowly update to the new event system, the current might get cut off soon!
2020-11-15 11:27:19 +01:00
retrooper 3dfb1ce0b5 * EventManagerLegacy isn't working, about to revert to the old event manager code, keeping this just incase.
When joining the server I instantly get kicked for "Disconnected".
2020-11-15 11:08:25 +01:00
retrooper aca321c332 Small bug fix for event systems
* Using MONITOR event priority now works
2020-11-15 10:36:21 +01:00
retrooper e0f4891a72 * Legacy and Dynamic event system ATTEMPT
API wise working, contains debugs, but UNTESTED!!!
The legacy(last event listener system) has been deprecated!
2020-11-15 10:27:31 +01:00
retrooper 08b207d80a Cleaner errors with PacketEvents
* PacketEventsLoadFailureException exception thrown if PacketEvents fails to load.
* PacketEventsMethodAccessException exception thrown if PacketEvents fails to access a method of a PacketListener for invoking.
* PacketEventsMethodInvokeException exception thrown if an exception is thrown from the invoked method in the PacketListener.
2020-11-15 08:43:29 +01:00
Retrooper 6121349a6f bug fixes
* resolving clientversion on bungee servers issue fixed
* read me cleaned up
* Via and ProtocolSupport utils removed
2020-11-15 15:09:46 +08:00
Retrooper 2b58a9ad97 small bug fixes
* Bungee channel name changed from "packetevents" to "packetevents:channel"
* NPE when accessing player version with viaversion onJoin sometimes
2020-11-14 00:44:55 +08:00
Retrooper 8e922a7676 Merge branch 'dev' of https://github.com/retrooper/packetevents
 Conflicts:
	src/main/java/io/github/retrooper/packetevents/example/MainExample.java
2020-11-13 23:45:49 +08:00
Retrooper 7967b6851f a 2020-11-13 23:42:55 +08:00
retrooper 18b37abf5b Merge pull request #64 from LIWKK/patch-13
Return 0 instead of -1 in blockplace wrapper 1.9
2020-11-11 22:25:49 +01:00
retrooper 53b713f574 Merge pull request #63 from LIWKK/patch-12
Return 0 instead of -1 in blockplace wrapper 1.8
2020-11-11 22:24:58 +01:00
Johannes 655f162272 Return 0 instead of -1 to not fuckup (1.9) 2020-11-11 23:22:01 +02:00
Johannes 686c50a7bb Return 0 instead of -1 to not fuckup other things. 2020-11-11 23:21:14 +02:00
retrooper a88e95e116 Merge pull request #62 from retrooper/dev
1.7.5 release
2020-11-09 07:21:41 +01:00
retrooper 7c583bf8ec 1.7.5 release 2020-11-09 07:21:06 +01:00
retrooper c3911483a5 Fix of WrappedPacketInBlockPlace returning -1 on 1.8 servers (By @LIWKK) 2020-11-08 22:12:03 +01:00
Johannes f37d7f4040 Fixxxxx 2020-11-08 23:10:14 +02:00
retrooper c39c9691a8 * Attempt to fix a bug to do with block place on 1.9+ 2020-11-08 17:39:11 +01:00
retrooper a1c591a616 Merge pull request #60 from retrooper/dev
1.7.4 Release
2020-11-08 15:17:16 +01:00
retrooper 999e21bf77 1.7.4
* PacketEvents.getSettings().packetHandlingThreadCount(int) setting added, basically lets you decide how many threads packetevents should use when asynchronously injecting/ejecting players, processing packets(packetevents' end) and event calling(processing on your end).
PacketEvents' current default settings are the most recommended settings.
Having more than one thread doing all that processing might cause you (or packetevents, as that feature hasn't been tested that much) some concurrency issues where multiple threads are accessing/modifying the same data at the same time!
2020-11-08 15:15:19 +01:00
retrooper c8e5a37472 Bug fix
* paper(and it's forks) 1.16 bug fix(unsure if this bug also existed in spigot or lower versions)
2020-11-08 14:44:02 +01:00
retrooper c6fffca506 Bug fixes
* WrappedPacketInUpdateSign error when reading Text Lines fixed
* WrappedPacketOutHeldItemSlot wrapper created
2020-11-08 12:33:46 +01:00
retrooper f1206a1fc6 * Block dig wrapper fixed
* Update sign wrapper fixed
* NPEs in Packet Receive/Send event fixed
2020-11-05 20:52:44 +01:00
terrarier2111 29a4280b50 Improved MUCH 2020-11-04 18:29:00 +01:00
retrooper 552f63a27f Merge pull request #59 from retrooper/dev
1.7.3 release
2020-11-03 09:54:11 +01:00
retrooper 612608181d 1.7.3 release
* We no longer eject players when they exit
* Fixed error when you leave the server
* No reload support with inject early setting enabled
2020-11-03 09:51:57 +01:00
retrooper 8e652f0c44 Merge pull request #58 from retrooper/dev
1.7.2 Release
2020-11-02 16:27:54 +01:00
retrooper 4a3e89d713 1.7.2 release 2020-11-02 16:20:13 +01:00
retrooper 3dd6d1e0b9 Vehicle move wrapper created(fyi isn't present on 1.7.10 and 1.8, I'm unsure about 1.9 but 1.12+ has it) 2020-11-02 16:18:46 +01:00
retrooper f42e1ad71d PacketType.Status.SERVER_INFO supported, fixed a NPE for PacketSendEvent/PacketReceiveEvent, im unsure if its clientbound or serverbound, but no matter what, its fixed 2020-11-01 17:13:47 +01:00
retrooper b44f36185a PacketType.Status.SERVER_INFO supported, fixed a NPE for PacketSendEvent 2020-11-01 17:11:52 +01:00
retrooper 1621adad02 Cleanup 2020-11-01 15:56:50 +01:00
retrooper d2682242ae Merge pull request #57 from retrooper/dev
PacketEvents 1.7.1 Release
2020-11-01 08:06:38 +01:00
Retrooper 0b26fe3266 1.7.1 release 2020-11-01 15:03:50 +08:00
Retrooper 0354ddf765 Merge branch 'dev' of https://github.com/retrooper/packetevents 2020-11-01 14:58:49 +08:00
retrooper 82e0d01c29 MainExample empty space removed 2020-11-01 07:56:22 +01:00
retrooper 57b68f185c Early player login bug fix
- This bug occurs when a user joins while the minecraft server is still starting up and spams out errors and PacketEvents fails to inject the player.
2020-10-31 23:46:11 +01:00
retrooper 8f9b8c0433 * Early server login fix second attempt 2020-10-31 22:46:39 +01:00
retrooper 27ced0fc36 * Early server login fix attempt 2020-10-31 22:11:25 +01:00
173 changed files with 8807 additions and 5973 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: retrooper
custom: ['https://paypal.me/retrooperdev']
+41
View File
@@ -0,0 +1,41 @@
---
name: Bug report
about: Report a bug to help us fix
title: "[BUG REPORT]"
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
*Example:*
1. Login on the 1.16.4 minecraft client.
2. Join the server while it is still starting up.
3. ....
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**About your server (please complete the following information):**
- Spigot: [eg. Paper or Tuinity]
We only accept reports that are reproducible
on one of the supported spigots.
- Server Version: [eg. 1.16.4]
Feel free to report bugs for versions newer than 1.7.10, even if we
don’t support them yet, but be aware that we might have already
found the bug and fixed it in a dev build, just before you reported it.
Please don’t get frustrated in such cases.
- Plugins List if possible: [eg. ViaVersion, ProtocolLib, HolographicDisplays]
**Additional context**
Add any other context about the problem here.
+21
View File
@@ -0,0 +1,21 @@
---
name: Feature request
about: Suggest an idea for this project
title: FEATURE REQUEST
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered to solve your solution without
us adding this as a feature?**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+67
View File
@@ -0,0 +1,67 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master, dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, dev ]
schedule:
- cron: '39 0 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
-30
View File
@@ -1,30 +0,0 @@
name: Generate and deploy JavaDocs
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn install
- name: List target/apidocs
run: ls target/apidocs
- name: GitHub Pages
uses: crazy-max/ghaction-github-pages@v2.1.2
env:
GH_PAT: ${{ secrets.GH_PAT }}
with:
target_branch: javadocs
keep_history: true
build_dir: target/apidocs
commit_message: Update JavaDocs
+72 -10
View File
@@ -1,20 +1,82 @@
# packetevents
# packetevents
A Spigot packet API with some nice utlities.
Some tasks require you to work at the packet level.
It is very common for people to write their own packet system and event manager.
PacketEvents is here to save you a ton of work.
We provide high level packet-wrappers.
The PacketEvents API focuses on providing you easy to use packet-wrappers supporting 1.7.10 spigots up to the current latest version!
This API even comes with two event systems.
The first one (currently deprecated) is extremely similar to Bukkit's event system making it really easy to use for
experienced Bukkit plugin developers.
The second one (recommended) prioritizes performance.
PacketEvents listens to its community.
Many users love shading the API into their plugin, so that their customers won't need to
download the API as an external dependency.
We have gone out of our way to support multiple plugins shading the API (resulting in duplicate PacketEvents APIs)
and they all work together.
## About
### Resources
* [Website](https://packetevents.github.io)
* [SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
* [JavaDoc](https://retrooper.github.io/packetevents)
This packetlistener is **only** supported on Spigot servers and has been tested to work on these Spigot forks: PaperMC, Tuinity
### Licensing
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\
PacketEvents is licensed under the MIT License.
We intentionally selected this license compared to stricter options.\
[Summary of the license](https://tldrlegal.com/license/mit-license)
* No dependencies
### Contributing
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CONTRIBUTOR_CODE_OF_CONDUCT.md)\
PacketEvents is an open source project.
We appreciate contributions.
It is amazing that you want to take an extra step to contribute a change to the API that will
hopefully benefit the majority of users.
Before taking this step, please read the Contributor Code Of Conduct. (click on the badge above)
Please also read [this](CONTRIBUTING.md) if you consider contributing.
Our discord server has a role for contributors.\
[Learn more about it in our discord server](https://discord.me/packetevents)
* Licensed under the MIT license
### Forking
We also appreciate forks.
It is always great news to us knowing someone is building their own API off of the PacketEvents API.
If you are developing a feature that is only going to benefit you and not the majority of the community,
please do not contribute!
Make a fork instead!
Our discord server has a discord role for forkers.\
[Learn more about it in our discord server](https://discord.me/packetevents)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
Our discord server: https://discord.me/packetevents
### Compilation
PacketEvents is built with Maven and all past releases have always used maven.
The majority of users (currently) in the Bukkit community use Maven.
It should be easier for most people to contribute if we use Maven too.
Just because PacketEvents is built with Maven doesn't mean you can't use other dependency managers to use the API.
### Setup
You can either use the API with a dependency manager(like Maven or Gradle), depend on a pre-built build or compile it yourself with the source code.
We recommend using a dependency manager.
#### 1. Using a dependency manager
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
[![](https://jitci.com/gh/retrooper/packetevents/svg)](https://jitci.com/gh/retrooper/packetevents)
#### 2. Using as an external pre-built dependency.
* Download the [latest build from SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
* Add PacketEvents as a depend or soft-depend to your plugin.yml like this:
```yml
depend: [packetevents]
```
Your customers are now required to download this external pre-built dependency on their minecraft server.\
It is an API and a Bukkit plugin at the same time.
The version of the pre-built dependency is recommended to be the same as the version
of the API you used in your plugin incase there have been API changes.
#### 3. Compiling source code.
When compiling the source code yourself, you are required to use Maven. (unless you switch yourself)\
We currently do not have a guide showing you how to do this, but it should be self explanatory if you know what you are doing.
### Author
PacketEvents was started by retrooper.
This API was initially for his private anti-cheat he was developing just to test around with.
He has quit anti-cheat development and is now prioritizing this API and a few other private projects.
PacketEvents now has a handfull of contributors improving the API.
Share the API, donate, contribute, fork.
Thanks.
+43 -13
View File
@@ -1,23 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.7</version>
<!-- You can build the project with this: "mvn clean compile assembly:single" -->
<version>1.8-PRE-1</version>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -40,6 +47,12 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<packaging>jar</packaging>
<name>packetevents</name>
@@ -70,10 +83,20 @@
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>sonotype</id>
<url>https://oss.sonatype.org/content/repositories/releases/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>20.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.16.2</artifactId>
@@ -95,6 +118,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.9</artifactId>
<version>1.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.8.8</artifactId>
@@ -119,14 +149,14 @@
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.1</version>
<version>3.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.ProtocolSupport</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>4fdd683</version>
<version>3d24efeda6</version>
<scope>provided</scope>
</dependency>
@@ -24,175 +24,208 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.bungee.BungeePluginMessageListener;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.packetmanager.PacketManager;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.event.impl.PostPlayerInjectEvent;
import io.github.retrooper.packetevents.event.manager.EventManager;
import io.github.retrooper.packetevents.event.manager.PEEventManager;
import io.github.retrooper.packetevents.exceptions.PacketEventsLoadFailureException;
import io.github.retrooper.packetevents.handler.PacketHandlerInternal;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import io.github.retrooper.packetevents.updatechecker.UpdateChecker;
import io.github.retrooper.packetevents.utils.entityfinder.EntityFinderUtils;
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil;
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil_7;
import io.github.retrooper.packetevents.utils.netty.bytebuf.ByteBufUtil_8;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.server.PEVersion;
import io.github.retrooper.packetevents.utils.player.PlayerUtils;
import io.github.retrooper.packetevents.utils.server.ServerUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.utils.version.PEVersion;
import io.github.retrooper.packetevents.utils.versionlookup.VersionLookupUtils;
import io.github.retrooper.packetevents.utils.versionlookup.protocollib.ProtocolLibVersionLookupUtils;
import io.github.retrooper.packetevents.utils.versionlookup.v_1_7_10.ProtocolVersionAccessor_v_1_7;
import io.github.retrooper.packetevents.utils.versionlookup.viaversion.ViaVersionLookupUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.ServicePriority;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Future;
public final class PacketEvents implements Listener {
private static final String nettyHandlerIdentifier = generateRandomNettyIdentifier();
private static final PacketEventsAPI packetEventsAPI = new PacketEventsAPI();
private static final PacketEvents instance = new PacketEvents();
private static final ArrayList<Plugin> plugins = new ArrayList<Plugin>(1);
private static boolean loaded, initialized;
private static final PEVersion version = new PEVersion(1, 7);
private static PacketEventsSettings settings = new PacketEventsSettings();
import java.lang.ref.WeakReference;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public final class PacketEvents implements Listener, EventManager {
private static PacketEvents instance;
private final PEVersion version = new PEVersion(1, 7, 9, 1);
private final EventManager eventManager = new PEEventManager();
private final PlayerUtils playerUtils = new PlayerUtils();
private final ServerUtils serverUtils = new ServerUtils();
private static Plugin plugin;
public static String handlerName;
/**
* This loads the PacketEvents API.
* <p>
* ServerVersion:
* In this method we detect and cache the server version.
* <p>
* NMSUtils:
* We setup some NMS utilities.
* <p>
* Packet ID System:
* All the packet classes we will be needing are cached in a Map with an integer ID.
* <p>
* Version Lookup Utils:
* We setup the client protocol version system.
* We check if ViaVersion, ProtocolSupport or ProtocolLib is present.
* <p>
* Wrappers:
* All PacketEvents' wrappers are setup and do all loading they need to do.
* General executor service, basically for anything that the packet executor service doesn't do.
* For example update checking when you initialize PacketEvents.
*/
public static void load() {
if (!loaded) {
public ExecutorService generalExecutorService = Executors.newSingleThreadExecutor(r -> new Thread(r, "PacketEvents-general"));
//Executor used for player injecting/ejecting.
public ExecutorService injectAndEjectExecutorService;//Initiated in init method
public PacketHandlerInternal packetHandlerInternal;
private boolean loading, loaded, initialized, initializing, stopping;
private PacketEventsSettings settings = new PacketEventsSettings();
private final ByteBufUtil byteBufUtil = NMSUtils.legacyNettyImportMode ? new ByteBufUtil_7() : new ByteBufUtil_8();
public static PacketEvents create(final Plugin plugin) {
if (!Bukkit.getServicesManager().isProvidedFor(PacketEvents.class)) {
instance = new PacketEvents();
Bukkit.getServicesManager().register(PacketEvents.class, instance,
plugin, ServicePriority.Normal);
return instance;
}
return instance = Bukkit.getServicesManager().load(PacketEvents.class);
}
public static PacketEvents get() {
return instance;
}
@Deprecated
public static PacketEvents getAPI() {
return get();
}
public void load() {
if (!loaded && !loading) {
loading = true;
ServerVersion version = ServerVersion.getVersion();
WrappedPacket.version = version;
PacketEvent.version = version;
NMSUtils.version = version;
EntityFinderUtils.version = version;
try {
NMSUtils.load();
PacketTypeClasses.Client.load();
PacketTypeClasses.Server.load();
PacketTypeClasses.Login.load();
PacketTypeClasses.Status.load();
//Load all classes
PacketTypeClasses.load();
EntityFinderUtils.load();
WrappedPacket.loadAllWrappers();
} catch (Exception ex) {
throw new IllegalStateException("PacketEvents failed to successfully load...", ex);
loading = false;
throw new PacketEventsLoadFailureException(ex);
}
loaded = true;
loading = false;
}
}
public static void loadSettings(PacketEventsSettings settings) {
PacketEvents.settings = settings;
public void loadSettings(PacketEventsSettings settings) {
this.settings = settings;
}
public static void init(final Plugin plugin) {
public void init(final Plugin plugin) {
init(plugin, settings);
}
/**
* Initiates PacketEvents
* <p>
* Loading:
* Loads PacketEvents if you haven't already.
* <p>
* Registering:
* Registers this class as a Bukkit listener to inject/eject players.
*
* @param pl JavaPlugin instance
*/
public static void init(final Plugin pl, PacketEventsSettings packetEventsSettings) {
public void init(final Plugin pl, PacketEventsSettings packetEventsSettings) {
load();
if (!initialized) {
if (!initialized && !initializing) {
initializing = true;
settings = packetEventsSettings;
plugins.add(pl);
if (settings.getInjectAndEjectThreadCount() < 1) {
settings.injectAndEjectThreadCount(1);
}
settings.lock();
int injectAndEjectThreadCount = settings.getInjectAndEjectThreadCount();
injectAndEjectExecutorService = Executors.newFixedThreadPool(injectAndEjectThreadCount, new ThreadFactory() {
private final AtomicInteger id = new AtomicInteger();
@Override
public Thread newThread(@NotNull Runnable r) {
return new Thread(r, "PacketEvents-inject-eject #" + id.getAndIncrement());
}
});
//Register Bukkit listener
Bukkit.getPluginManager().registerEvents(instance, plugins.get(0));
PacketEvents.getAPI().packetManager = new PacketManager(plugins.get(0), settings.shouldInjectEarly());
plugin = pl;
Bukkit.getPluginManager().registerEvents(this, plugin);
handlerName = "pe-" + plugin.getName();
packetHandlerInternal = new PacketHandlerInternal(plugin);
for (final Player p : Bukkit.getOnlinePlayers()) {
getAPI().getPlayerUtils().injectPlayer(p);
try {
getPlayerUtils().injectPlayer(p);
} catch (Exception ex) {
p.kickPlayer(getSettings().getInjectionFailureMessage());
}
}
if (settings.shouldCheckForUpdates()) {
Future<?> future = NettyPacketManager.executorService.submit(new Runnable() {
@Override
public void run() {
new UpdateChecker().handleUpdate();
}
});
}
generalExecutorService.execute(() -> new UpdateChecker().handleUpdate());
if (getAPI().getServerUtils().isBungeeCordEnabled()) {
Bukkit.getMessenger().registerOutgoingPluginChannel(plugins.get(0), "BungeeCord");
Bukkit.getServer().getMessenger().registerIncomingPluginChannel(plugins.get(0), BungeePluginMessageListener.tagName, new BungeePluginMessageListener());
}
initialized = true;
initializing = false;
}
}
/**
*
*/
public static void stop() {
if (initialized) {
for (final Player p : Bukkit.getOnlinePlayers()) {
getAPI().getPlayerUtils().ejectPlayer(p);
public void terminate() {
if (initialized && !stopping) {
for (Player player : Bukkit.getOnlinePlayers()) {
packetHandlerInternal.ejectPlayer(player);
}
packetHandlerInternal.cleanup();
getAPI().getEventManager().unregisterAllListeners();
getEventManager().unregisterAllListeners();
generalExecutorService.shutdownNow();
injectAndEjectExecutorService.shutdownNow();
initialized = false;
NettyPacketManager.executorService.shutdownNow();
stopping = false;
}
}
public static boolean hasLoaded() {
@Deprecated
public void stop() {
terminate();
}
public boolean hasLoaded() {
return loaded;
}
public static boolean isInitialized() {
public boolean isLoading() {
return loading;
}
public boolean isInitializing() {
return initializing;
}
public boolean isStopping() {
return stopping;
}
public boolean isInitialized() {
return initialized;
}
public static PacketEventsAPI getAPI() {
return packetEventsAPI;
}
public static ArrayList<Plugin> getPlugins() {
return plugins;
}
public static String getHandlerName(final String name) {
return "pe-" + nettyHandlerIdentifier + "-" + name;
public Plugin getPlugin() {
return plugin;
}
/**
@@ -200,59 +233,91 @@ public final class PacketEvents implements Listener {
*
* @return Configure some settings for the API
*/
public static PacketEventsSettings getSettings() {
public PacketEventsSettings getSettings() {
return settings;
}
public static PEVersion getVersion() {
public PEVersion getVersion() {
return version;
}
@EventHandler
public void onLogin(PlayerLoginEvent e) {
if (PacketEvents.getSettings().shouldInjectEarly()) {
assert getAPI().packetManager.tinyProtocol != null;
if (getAPI().packetManager.tinyProtocol.canInject(e.getPlayer())) {
getAPI().packetManager.injectPlayer(e.getPlayer());
public EventManager getEventManager() {
return eventManager;
}
public PlayerUtils getPlayerUtils() {
return playerUtils;
}
public ServerUtils getServerUtils() {
return serverUtils;
}
public ByteBufUtil getByteBufUtil() {
return byteBufUtil;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onLogin(final PlayerLoginEvent e) {
if (getSettings().shouldInjectEarly()) {
try {
packetHandlerInternal.injectPlayer(e.getPlayer());
} catch (Exception ex) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, PacketEvents.get().getSettings().getInjectionFailureMessage());
}
}
}
@EventHandler
@EventHandler(priority = EventPriority.HIGH)
public void onJoin(final PlayerJoinEvent e) {
if (!VersionLookupUtils.hasHandledLoadedDependencies()) {
VersionLookupUtils.handleLoadedDependencies();
final InetSocketAddress address = e.getPlayer().getAddress();
boolean viaAvailable = ViaVersionLookupUtils.isAvailable();
if (viaAvailable) {
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(e.getPlayer().getAddress(), ClientVersion.TEMP_UNRESOLVED);
Bukkit.getScheduler().runTaskLaterAsynchronously(getPlugin(), new Runnable() {
@Override
public void run() {
int protocolVersion = VersionLookupUtils.getProtocolVersion(e.getPlayer());
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(address, version);
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), true));
}
}, 1L);
} else if (getServerUtils().getVersion() == ServerVersion.v_1_7_10) {
ClientVersion version = ClientVersion.getClientVersion(ProtocolVersionAccessor_v_1_7.getProtocolVersion(e.getPlayer()));
if (version == ClientVersion.UNRESOLVED) {
version = getPlayerUtils().tempClientVersionMap.get(address);
if (version == null) {
version = ClientVersion.UNRESOLVED;
}
}
getPlayerUtils().clientVersionsMap.put(address, version);
}
Object channel = NMSUtils.getChannel(e.getPlayer());
//Waiting for the BungeeCord server to send their plugin message with your version,
//So we leave bungee alone
if (!PacketEvents.getAPI().getServerUtils().isBungeeCordEnabled()) {
if (VersionLookupUtils.isDependencyAvailable()) {
ClientVersion version = ClientVersion.getClientVersion(VersionLookupUtils.getProtocolVersion(e.getPlayer()));
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
if (!getSettings().shouldInjectEarly()) {
try {
packetHandlerInternal.injectPlayer(e.getPlayer());
//Injection was successful as no exception was thrown...
if (!viaAvailable) {
if (ProtocolLibVersionLookupUtils.isAvailable()) {
ClientVersion version = ClientVersion.getClientVersion(ProtocolLibVersionLookupUtils.getProtocolVersion(e.getPlayer()));
PacketEvents.get().getPlayerUtils().clientVersionsMap.put(address, version);
}
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), false));
}
} catch (Exception ex) {
e.getPlayer().kickPlayer(getSettings().getInjectionFailureMessage());
}
} else {
if (!viaAvailable) {
PacketEvents.get().getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer(), false));
}
}
if (!PacketEvents.getSettings().shouldInjectEarly()) {
PacketEvents.getAPI().packetManager.injectPlayer(e.getPlayer());
}
}
@EventHandler
@EventHandler(priority = EventPriority.HIGHEST)
public void onQuit(final PlayerQuitEvent e) {
PacketEvents.getAPI().getPlayerUtils().ejectPlayer(e.getPlayer());
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.remove(e.getPlayer().getUniqueId());
packetHandlerInternal.ejectPlayer(e.getPlayer());
}
private static String generateRandomNettyIdentifier() {
String alphabet = "abcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder();
Random random = new Random();
while (sb.length() < 13) {
int index = (int) (random.nextFloat() * alphabet.length());
sb.append(alphabet.charAt(index));
}
return sb.toString();
}
}
@@ -1,67 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.event.manager.EventManager;
import io.github.retrooper.packetevents.packetmanager.PacketManager;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import io.github.retrooper.packetevents.utils.player.PlayerUtils;
import io.github.retrooper.packetevents.utils.server.ServerUtils;
public final class PacketEventsAPI {
private final EventManager eventManager = new EventManager();
private final PlayerUtils playerUtils = new PlayerUtils();
private final ServerUtils serverUtils = new ServerUtils();
public PacketManager packetManager = null;
/**
* Get all utilities to do with the player
*
* @return Player Utilities
*/
public PlayerUtils getPlayerUtils() {
return playerUtils;
}
/**
* Get all utilities to do with the server
*
* @return Server Utilities
*/
public ServerUtils getServerUtils() {
return serverUtils;
}
/**
* Get the event manager
* Used to call events, register and unregister listeners
*
* @return PacketEvents' event manager
*/
public EventManager getEventManager() {
return eventManager;
}
}
@@ -0,0 +1,51 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents;
import org.bukkit.plugin.java.JavaPlugin;
public class PacketEventsPlugin extends JavaPlugin {
@Override
public void onLoad() {
}
@Override
public void onEnable() {
if (PacketEvents.get() == null) {
PacketEvents.create(this);
PacketEvents.get().load();
PacketEvents.get().init(this);
}
}
@Override
public void onDisable() {
if (PacketEvents.get() != null) {
PacketEvents.get().terminate();
}
}
}
@@ -1,55 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.bungee;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import java.util.UUID;
public class BungeePluginMessageListener implements PluginMessageListener {
public static String tagName = "packetevents";
@Override
public void onPluginMessageReceived(String tag, Player player, byte[] bytes) {
if (tag.equals(tagName)) {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
if (in.readUTF().equals("version")) {
String uuidString = in.readUTF();
Object channel = NMSUtils.getChannel(player);
short protocolVersion = in.readShort();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(channel, version);
}
}
}
}
@@ -25,25 +25,37 @@
package io.github.retrooper.packetevents.event;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.event.eventtypes.CallableEvent;
/**
* An event in the PacketEvents EventManager system.
* An event in both of PacketEvents' event systems.
*
* @author retrooper
* @since 1.2.6
*/
public abstract class PacketEvent {
public static ServerVersion version;
public abstract class PacketEvent implements CallableEvent {
private long timestamp = System.currentTimeMillis();
/**
* Timestamp of the packet
* Timestamp of when the PacketEvent was created.
* Basically timestamp of the packet.
*
* @return timestamp in milliseconds
* @return Packet timestamp in milliseconds.
*/
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
/**
* Setter for the timestamp.
*
* @param timestamp Packet timestamp in milliseconds.
*/
public void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
public void callPacketEvent(final PacketListenerDynamic listener) {
listener.onPacketEvent(this);
}
}
@@ -25,8 +25,14 @@
package io.github.retrooper.packetevents.event;
/**
* A Packet listener.
* Implement this interface in your listeners.
* The legacy Packet listener.
* Implement this interface in your listener if you are using the legacy event system.
*
* @author retrooper
* @see PacketListenerDynamic
* @since 1.2.6
* @deprecated There is a new and better listener for the new event system.
*/
@Deprecated
public interface PacketListener {
}
@@ -0,0 +1,91 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
/**
* Dynamic packet event listener.
* Implement whatever event method you need.
* Nothing will happen if you don't implement an event method.
*
* @author retrooper
* @since 1.7.7
*/
public abstract class PacketListenerDynamic {
private final PacketEventPriority priority;
public PacketListenerDynamic(final PacketEventPriority priority) {
this.priority = priority;
}
public PacketListenerDynamic() {
this(PacketEventPriority.NORMAL);
}
public PacketEventPriority getPriority() {
return priority;
}
public void onPacketStatusReceive(PacketStatusReceiveEvent event) {
}
public void onPacketStatusSend(PacketStatusSendEvent event) {
}
public void onPacketLoginReceive(PacketLoginReceiveEvent event) {
}
public void onPacketLoginSend(PacketLoginSendEvent event) {
}
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
}
public void onPacketPlaySend(PacketPlaySendEvent event) {
}
public void onPostPacketPlayReceive(PostPacketPlayReceiveEvent event) {
}
public void onPostPacketPlaySend(PostPacketPlaySendEvent event) {
}
public void onPostPlayerInject(PostPlayerInjectEvent event) {
}
public void onPlayerInject(PlayerInjectEvent event) {
}
public void onPlayerEject(PlayerEjectEvent event) {
}
public void onPacketEvent(PacketEvent event) {
}
}
@@ -24,16 +24,22 @@
package io.github.retrooper.packetevents.event.annotation;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
/**
* This is what you override your event listener with on the old event system.
* You can specify the event priority of the listener method.
*
* @author retrooper
* @since 1.0
* @deprecated Was used for the old event system, the new one doesn't need this anymore.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface PacketHandler {
byte priority() default PacketEventPriority.NORMAL;
byte priority() default 2; //NORMAL priority value
}
@@ -22,18 +22,23 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.enums;
package io.github.retrooper.packetevents.event.eventtypes;
public enum Direction {
DOWN, UP, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
NORTH_WEST, SOUTH_EAST,
SOUTH_WEST, WEST_NORTH_WEST,
NORTH_NORTH_WEST, NORTH_NORTH_EAST,
EAST_NORTH_EAST, EAST_SOUTH_EAST,
SOUTH_SOUTH_EAST, SOUTH_SOUTH_WEST,
WEST_SOUTH_WEST, SELF, NULL;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
public static Direction get(final int i) {
return values()[i];
}
/**
* The {@link PacketEvent} implements this interface.
* Every inbuilt event should implement the {@link #call(PacketListenerDynamic)} method.
* If you are making a custom event, don't implement this.
* The {@link PacketListenerDynamic#onPacketEvent(PacketEvent)} method is called for every event,
* including custom events.
*
* @author retrooper
* @see PacketPlayReceiveEvent
* @since 1.8
*/
public interface CallableEvent {
void call(PacketListenerDynamic listener);
}
@@ -24,21 +24,34 @@
package io.github.retrooper.packetevents.event.eventtypes;
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
/**
* This indicates that it is possible to cancel an event,
* which should result in cancelling the planned action.
* Every event that supports cancellation should implement this interface.
* PacketEvents' event system lets the highest priority listener be have the highest priority
* in deciding whether the event will cancel.
* This means an event with a lower priority than the higher priority one would not be able to decide.
* Cancelling the event means the action assosiated with the event will be cancelled.
* For example, cancelling the {@link PacketPlayReceiveEvent}
* will prevent minecraft from processing the incoming packet.
*
* @author retrooper
* @see PacketPlayReceiveEvent
* @since 1.7
*/
public interface CancellableEvent {
/**
* Has the event been cancelled?
* @return is event cancelled
* This method returns if the event will be cancelled.
*
* @return Will the event be cancelled.
*/
boolean isCancelled();
/**
* Cancel or proceed with the event.
* @param val
*
* @param val Is the event cancelled
*/
void setCancelled(boolean val);
@@ -46,11 +59,13 @@ public interface CancellableEvent {
* Cancel the event.
* You can achieve the same result by just using {@link #setCancelled(boolean)}
*/
@Deprecated
void cancel();
/**
* Uncancel the event.
* You can achieve the same result by just using {@link #setCancelled(boolean)}
*/
@Deprecated
void uncancel();
}
@@ -0,0 +1,37 @@
package io.github.retrooper.packetevents.event.eventtypes;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import java.net.InetSocketAddress;
public abstract class CancellableNMSPacketEvent extends NMSPacketEvent implements CancellableEvent {
private boolean cancelled;
public CancellableNMSPacketEvent(Object channel, NMSPacket packet) {
super(channel, packet);
}
public CancellableNMSPacketEvent(InetSocketAddress address, NMSPacket packet) {
super(address, packet);
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public void uncancel() {
cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
}
}
@@ -0,0 +1,108 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.eventtypes;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.utils.netty.channel.ChannelUtils;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import java.net.InetSocketAddress;
/**
* The {@code NMSPacketEvent} abstract class represents an event that has to do with an actual packet.
* Don't mix this up with {@link io.github.retrooper.packetevents.event.PacketEvent}.
* The PacketEvent class represents an event that belongs to PacketEvent's packet system.
*
* @author retrooper
* @since 1.8
*/
public abstract class NMSPacketEvent extends PacketEvent implements CallableEvent {
private final InetSocketAddress socketAddress;
protected NMSPacket packet;
protected boolean cancelled;
public NMSPacketEvent(Object channel, NMSPacket packet) {
this.socketAddress = ChannelUtils.getSocketAddress(channel);
this.packet = packet;
}
public NMSPacketEvent(InetSocketAddress address, NMSPacket packet) {
this.socketAddress = address;
this.packet = packet;
}
/**
* Get the associated player's socket address.
*
* @return Socket address of the associated player.
*/
public final InetSocketAddress getSocketAddress() {
return socketAddress;
}
/**
* This method returns the name of the packet.
* To get the name of the packet we get the class of the packet and then the name of the class.
* See also: {@link Class#getSimpleName()}
* We cache the name after the first call to improve performance.
* Java 8 does not cache the name.
* It is not recommended to call this method unless you NEED it.
* If you are comparing packet types, use the {@link PacketType} byte system.
* You would only need the packet name if packet type system doesn't contain your desired packet yet.
*
* @return Name of the packet.
*/
@Deprecated
public final String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getRawNMSPacket().getClass());
}
/**
* Get the NMS packet.
*
* @return Get NMS packet.
*/
public final NMSPacket getNMSPacket() {
return packet;
}
/**
* Update the NMS Packet.
*
* @param packet NMS Object
*/
public final void setNMSPacket(NMSPacket packet) {
this.packet = packet;
}
/**
* Get the Packet ID.
*
* @return Packet ID.
*/
public abstract byte getPacketId();
}
@@ -24,14 +24,21 @@
package io.github.retrooper.packetevents.event.eventtypes;
import io.github.retrooper.packetevents.event.impl.PacketPlayReceiveEvent;
import org.bukkit.entity.Player;
/**
* Event having to do with a player.
* Every event that has an associated player is recommended to implement this interface.
*
* @author retrooper
* @see PacketPlayReceiveEvent
* @since 1.6.9
*/
public interface PlayerEvent {
/**
* Associated player.
*
* @return Player.
*/
Player getPlayer();
}
@@ -24,70 +24,48 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
public class PacketStatusEvent extends PacketEvent implements CancellableEvent {
private final Object channel;
private final Object packet;
private boolean cancelled;
import java.net.InetSocketAddress;
public PacketStatusEvent(final Object channel, final Object packet) {
this.channel = channel;
this.packet = packet;
/**
* The {@code PacketLoginReceiveEvent} event is fired whenever the a LOGIN packet is received from a client.
* The {@code PacketLoginReceiveEvent} does not have to do with a bukkit player object due to
* the player object being null in this state.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Login">https://wiki.vg/Protocol#Login</a>
* @since 1.8
*/
public class PacketLoginReceiveEvent extends CancellableNMSPacketEvent {
public PacketLoginReceiveEvent(final Object channel, final NMSPacket packet) {
super(channel, packet);
}
public Object getChannel() {
return channel;
public PacketLoginReceiveEvent(final InetSocketAddress socketAddress, final NMSPacket packet) {
super(socketAddress, packet);
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Login.Client.HANDSHAKE) }
* </p>
*
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
return packet;
}
/**
* Get the ID of the packet
*
* @return packet id
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Status.packetIds.getOrDefault(packet.getClass(), (byte) -1);
return PacketType.Login.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public void uncancel() {
cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
public void call(PacketListenerDynamic listener) {
listener.onPacketLoginReceive(this);
}
}
@@ -24,52 +24,39 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import org.bukkit.entity.Player;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
public class PostPacketSendEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
import java.net.InetSocketAddress;
public PostPacketSendEvent(final Player player, final Object packet) {
this.player = player;
this.packet = packet;
/**
* The {@code PacketLoginSendEvent} event is fired whenever the a LOGIN packet is being planned to be sent to the client.
* The {@code PacketLoginSendEvent} does not have to do with a bukkit player object due to
* the player object being null in this state.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Login">https://wiki.vg/Protocol#Login</a>
* @since 1.8
*/
public class PacketLoginSendEvent extends CancellableNMSPacketEvent {
public PacketLoginSendEvent(Object channel, NMSPacket packet) {
super(channel, packet);
}
public PacketLoginSendEvent(InetSocketAddress address, NMSPacket packet) {
super(address, packet);
}
/**
* Get the packet sender
* @return player
*/
@Override
public Player getPlayer() {
return player;
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the raw packet object
* @return packet object
*/
public Object getNMSPacket() {
return packet;
}
/**
* Get the ID of the packet
* @return packet id
*/
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
return PacketType.Login.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPacketLoginSend(this);
}
}
@@ -0,0 +1,92 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* The {@code PacketPlayReceiveEvent} event is fired whenever the a PLAY packet is
* received from any connected client.
* Cancelling this event will result in preventing minecraft from processing the incoming packet.
* It would be as if the player never sent the packet from the server's view.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Play">https://wiki.vg/Protocol#Play</a>
* @since 1.2.6
*/
public final class PacketPlayReceiveEvent extends CancellableNMSPacketEvent implements PlayerEvent {
private final Player player;
public PacketPlayReceiveEvent(final Player player, final Object channel, final NMSPacket packet) {
super(channel, packet);
this.player = player;
}
/**
* This method returns the bukkit player object of the packet sender.
* The player object might be null during early packets.
*
* @return Packet sender.
*/
@NotNull
@Override
public Player getPlayer() {
return player;
}
/**
* This method returns the socket address of the packet sender.
* This address if guaranteed to never be null.
* You could use this to identify who is sending packets
* whenever the player object is null.
*
* @return Packet sender's socket address.
*/
/**
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Play.Client.USE_ENTITY) }
* </p>
*
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Play.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPacketPlayReceive(this);
}
}
@@ -24,77 +24,60 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* This event is called each time the server sends a packet to the client.
* The {@code PacketPlaySendEvent} event is fired whenever the a PLAY packet is about to be sent.
* Cancelling this event will result in preventing minecraft from sending the packet.
* The player won't receive the packet if you cancel it.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Play">https://wiki.vg/Protocol#Play</a>
* @since 1.2.6
*/
public final class PacketSendEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
public final class PacketPlaySendEvent extends CancellableNMSPacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
private boolean cancelled;
public PacketSendEvent(final Player player, final Object packet) {
public PacketPlaySendEvent(final Player player, final Object channel, final NMSPacket packet) {
super(channel, packet);
this.player = player;
this.packet = packet;
this.cancelled = false;
}
/**
* This method returns the bukkit player object of the packet receiver.
* The player object might be null during early packets.
*
* @return Packet receiver.
*/
@NotNull
@Override
public Player getPlayer() {
return player;
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the ID of the packet
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Play.Server.KEEP_ALIVE) }
* </p>
*
* @return packet id
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Server.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
/**
* Get the NMS packet object
*
* @return packet object
*/
public Object getNMSPacket() {
return packet;
return PacketType.Play.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public void uncancel() {
cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
public void call(PacketListenerDynamic listener) {
listener.onPacketPlaySend(this);
}
}
@@ -1,101 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import org.bukkit.entity.Player;
/**
* This event is called each time a packet is received from a client.
*/
public final class PacketReceiveEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
private final Player player;
private final Object packet;
private boolean cancelled;
public PacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
this.packet = packet;
}
/**
* Get the packet sender
* @return player
*/
@Override
public Player getPlayer() {
return player;
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the raw packet object
* @return packet object
*/
public Object getNMSPacket() {
return packet;
}
/**
* Get the ID of the packet
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public void uncancel() {
cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
}
}
@@ -24,73 +24,48 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import java.net.InetSocketAddress;
/**
* This event is called when we receive a login packet.
* The {@code PacketStatusReceiveEvent} event is fired whenever the server receives a STATUS packet from a client.
* The {@code PacketStatusSendEvent} does not have to do with a bukkit player object due to
* the player object being null in this state.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Status">https://wiki.vg/Protocol#Status</a>
* @since 1.8
*/
public class PacketLoginEvent extends PacketEvent implements CancellableEvent {
private final Object channel;
private final Object packet;
private boolean cancelled;
public PacketLoginEvent(final Object channel, final Object packet) {
this.channel = channel;
this.packet = packet;
public class PacketStatusReceiveEvent extends CancellableNMSPacketEvent {
public PacketStatusReceiveEvent(final Object channel, final NMSPacket packet) {
super(channel, packet);
}
public Object getChannel() {
return channel;
public PacketStatusReceiveEvent(final InetSocketAddress socketAddress, final NMSPacket packet) {
super(socketAddress, packet);
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Status.Client.PING) }
* </p>
*
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the raw packet object
*
* @return packet object
*/
public Object getNMSPacket() {
return packet;
}
/**
* Get the ID of the packet
*
* @return packet id
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Login.packetIds.getOrDefault(packet.getClass(), (byte) -1);
return PacketType.Status.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public void uncancel() {
cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
public void call(PacketListenerDynamic listener) {
listener.onPacketStatusReceive(this);
}
}
@@ -0,0 +1,73 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.eventtypes.CancellableNMSPacketEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import java.net.InetSocketAddress;
/**
* The {@code PacketStatusSendEvent} event is fired whenever the server wants to send a STATUS packet to the client.
* This class implements {@link CancellableEvent}.
* The {@code PacketStatusSendEvent} does not have to do with a bukkit player object due to
* the player object being null in this state.
* Use the {@link #getSocketAddress()} to identify who sends the packet.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Status">https://wiki.vg/Protocol#Status</a>
* @since 1.8
*/
public class PacketStatusSendEvent extends CancellableNMSPacketEvent {
public PacketStatusSendEvent(Object channel, NMSPacket packet) {
super(channel, packet);
}
public PacketStatusSendEvent(InetSocketAddress address, NMSPacket packet) {
super(address, packet);
}
/**
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Status.Server.PONG) }
* </p>
*
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Status.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPacketStatusSend(this);
}
}
@@ -24,13 +24,23 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* This event is called each time you eject a player.
* The {@code PlayerEjectEvent} event is fired whenever a player is ejected.
* A player is ejected by PacketEvents whenever they quit the server.
* This class implements {@link CancellableEvent} and {@link PlayerEvent}.
*
* @author retrooper
* @see <a href="https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java">https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java</a>
* @since 1.6.9
*/
public final class PlayerEjectEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
private final Player player;
@@ -42,11 +52,6 @@ public final class PlayerEjectEvent extends PacketEvent implements CancellableEv
this.async = isAsync;
}
public PlayerEjectEvent(final Player player) {
this.player = player;
this.async = true; //default value
}
@Override
public void cancel() {
cancelled = true;
@@ -67,12 +72,33 @@ public final class PlayerEjectEvent extends PacketEvent implements CancellableEv
cancelled = value;
}
/**
* This method returns the bukkit player object of the player being ejected.
* The player object is guaranteed to NOT be null.
*
* @return Ejected player.
*/
@NotNull
@Override
public Player getPlayer() {
return player;
}
/**
* This method returns if the event has been called asynchronously.
* If the {@link PacketEventsSettings#shouldEjectAsync()} is enabled, the event will be called asynchronously
* and the player will be ejected asynchronously.
* The {@link PacketEventsSettings} can be accessed here:
*
* @return Is the ejection asynchronous.
* @see PacketEvents#getSettings()
*/
public boolean isAsync() {
return async;
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPlayerEject(this);
}
}
@@ -24,25 +24,37 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import io.github.retrooper.packetevents.utils.netty.channel.ChannelUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.InetSocketAddress;
/**
* This event is called each time you inject a player.
* The {@code PlayerInjectEvent} event is fired whenever a player is injected.
* A player is injected by PacketEvents whenever they join the server.
* This class implements {@link CancellableEvent} and {@link PlayerEvent}.
*
* @author retrooper
* @see <a href="https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java">https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java</a>
* @since 1.6.9
*/
public final class PlayerInjectEvent extends PacketEvent implements CancellableEvent, PlayerEvent {
private final Player player;
private final InetSocketAddress address;
private final boolean async;
private boolean cancelled;
public PlayerInjectEvent(final Player player) {
this(player, false);
}
public PlayerInjectEvent(final Player player, boolean isAsync) {
this.player= player;
public PlayerInjectEvent(final Player player, final boolean isAsync) {
this.player = player;
this.address = ChannelUtils.getSocketAddress(PacketEvents.get().packetHandlerInternal.getChannel(player));
this.async = isAsync;
}
@@ -66,12 +78,43 @@ public final class PlayerInjectEvent extends PacketEvent implements CancellableE
cancelled = value;
}
/**
* This method returns the bukkit player object of the player being injected.
* This player might not be fully initialized.
*
* @return Injected Player.
*/
@Nullable
@Override
public Player getPlayer() {
return player;
}
/**
* This method returns the socket address injecting player.
*
* @return Socket address of the injecting player.
*/
@NotNull
public InetSocketAddress getSocketAddress() {
return address;
}
/**
* This method returns if the event has been called asynchronously.
* If the {@link PacketEventsSettings#shouldInjectAsync()} is enabled, the event will be called asynchronously
* and the player will be injected asynchronously.
* The {@link PacketEventsSettings} can be accessed here:
*
* @return Is the injection asynchronous.
* @see PacketEvents#getSettings()
*/
public boolean isAsync() {
return async;
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPlayerInject(this);
}
}
@@ -0,0 +1,85 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.NMSPacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
/**
* The {@code PostPacketPlayReceiveEvent} event is fired after minecraft processes
* a PLAY server-bound packet.
* You cannot cancel this event since minecraft already processed/is processing this packet.
* If the incoming packet was cancelled, resulting in it not being processed by minecraft,
* this event won't be called.
* This event assures you that the {@link PacketPlayReceiveEvent} event wasn't cancelled.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Serverbound_4">https://wiki.vg/Protocol#Serverbound_4</a>
* @since 1.7
*/
public class PostPacketPlayReceiveEvent extends NMSPacketEvent implements PlayerEvent {
private final Player player;
public PostPacketPlayReceiveEvent(final Player player, final Object channel, final NMSPacket packet) {
super(channel, packet);
this.player = player;
}
/**
* This method returns the bukkit player object of the packet sender.
* The player object might be null during early packets.
*
* @return Packet sender.
*/
@Nullable
@Override
public Player getPlayer() {
return player;
}
/**
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Play.Client.ARM_ANIMATION) }
* </p>
*
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Play.Client.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPostPacketPlayReceive(this);
}
}
@@ -0,0 +1,85 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.NMSPacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
/**
* The {@code PostPacketPlaySendEvent} event is fired after minecraft processes
* a PLAY client-bound packet.
* You cannot cancel this event since minecraft already processed this packet.
* If the incoming packet was cancelled, resulting in it not being processed by minecraft,
* this event won't be called.
* This event assures you that the {@link PacketPlaySendEvent} event wasn't cancelled.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Clientbound_4">https://wiki.vg/Protocol#Clientbound_4</a>
* @since 1.7
*/
public class PostPacketPlaySendEvent extends NMSPacketEvent implements PlayerEvent {
private final Player player;
public PostPacketPlaySendEvent(final Player player, final Object channel, final NMSPacket packet) {
super(channel, packet);
this.player = player;
}
/**
* This method returns the bukkit player object of the packet sender.
* The player object is might be null during early packets.
*
* @return Packet receiver.
*/
@Nullable
@Override
public Player getPlayer() {
return player;
}
/**
* Each binding in each packet state has their own constants.
* Example Usage:
* <p>
* {@code if (getPacketId() == PacketType.Play.Server.KEEP_ALIVE) }
* </p>
*
* @return Packet ID.
*/
@Override
public byte getPacketId() {
return PacketType.Play.Server.packetIds.getOrDefault(packet.getRawNMSPacket().getClass(), PacketType.INVALID);
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPostPacketPlaySend(this);
}
}
@@ -1,75 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import org.bukkit.entity.Player;
public class PostPacketReceiveEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final Object packet;
public PostPacketReceiveEvent(final Player player, final Object packet) {
this.player = player;
this.packet = packet;
}
/**
* Get the packet sender
* @return player
*/
@Override
public Player getPlayer() {
return player;
}
/**
* Get the packet's name (NMS packet class simple name).
* The class simple name is cached.
* @return Name of the packet
*/
public String getPacketName() {
return ClassUtil.getClassSimpleName(packet.getClass());
}
/**
* Get the raw packet object
* @return packet object
*/
public Object getNMSPacket() {
return packet;
}
/**
* Get the ID of the packet
* @return packet id
*/
public byte getPacketId() {
return PacketType.Client.packetIds.getOrDefault(packet.getClass(), (byte) -1);
}
}
@@ -0,0 +1,111 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.PlayerEvent;
import io.github.retrooper.packetevents.utils.netty.channel.ChannelUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.InetSocketAddress;
/**
* The {@code PostPlayerInjectEvent} event is fired after a successful injection.
* If you are on an older version of PacketEvents DON'T use this to register player data.
* This event might be called asynchronously and sometimes synchronously.
* Use the {@link #isAsync()} method to figure out if is being called sync or async.
* Make sure you do null checks in your packet listeners as this might be called a bit later.
* A player is injected by PacketEvents whenever they join the server.
*
* @author retrooper
* @see <a href="https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java">https://github.com/retrooper/packetevents/blob/dev/src/main/java/io/github/retrooper/packetevents/handler/PacketHandlerInternal.java</a>
* @since 1.3
*/
public class PostPlayerInjectEvent extends PacketEvent implements PlayerEvent {
private final Player player;
private final boolean async;
public PostPlayerInjectEvent(Player player, boolean async) {
this.player = player;
this.async = async;
}
/**
* This method returns the bukkit player object of the player that has been injected.
* The player is guaranteed to not be null.
*
* @return Injected Player.
*/
@NotNull
@Override
public Player getPlayer() {
return player;
}
/**
* This method returns the cached netty channel of the player.
*
* @return Netty channel of the injected player.
*/
@NotNull
public Object getChannel() {
return PacketEvents.get().packetHandlerInternal.getChannel(player);
}
@NotNull
public InetSocketAddress getSocketAddress() {
return ChannelUtils.getSocketAddress(getChannel());
}
/**
* This method returns the ClientVersion of the injected player.
*
* @return ClientVersion of injected player.
* @see ClientVersion
*/
@Nullable
public ClientVersion getClientVersion() {
return PacketEvents.get().getPlayerUtils().getClientVersion(player);
}
/**
* Has the event been called async or sync?
*
* @return Was the event call in an async context?
*/
public boolean isAsync() {
return async;
}
@Override
public void call(PacketListenerDynamic listener) {
listener.onPostPlayerInject(this);
}
}
@@ -25,97 +25,149 @@
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import io.github.retrooper.packetevents.utils.protocollib.ProtocolLibListener;
import io.github.retrooper.packetevents.utils.protocollib.ProtocolLibUtils;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* This is the event manager interface.
* Every method is already implemented, we just use this
* to have less code duplications.
* You can either call event manager methods in the
* {@link io.github.retrooper.packetevents.PacketEvents} instance or with an instance of the
* {@link PEEventManager} stored in {@link PacketEvents}.
*
* @author retrooper
* @see PacketEvents#getEventManager()
* @since 1.0
*/
public interface EventManager {
public final class EventManager {
private final ConcurrentHashMap<PacketListener, ConcurrentLinkedQueue<Method>> registeredMethods = new ConcurrentHashMap<>();
/**
* Call a packet event.
* This will let all listeners(new and deprecated listeners) process the event.
* It isn't recommended to use a mix of both listeners(new and deprecated),
* but it will work and they are compatible.
*
* @param event {@link PacketEvent}
* @return Same event manager instance.
*/
default EventManager callEvent(PacketEvent event) {
//The dynamic event manager calls the legacy event manager.
PEEventManager.EVENT_MANAGER_DYNAMIC.callEvent(event);
return this;
}
public void callEvent(final PacketEvent e) {
for (final PacketListener listener : registeredMethods.keySet()) {
ConcurrentLinkedQueue<Method> methods = registeredMethods.get(listener);
final boolean[] isCancelled = {false};
final byte[] eventPriority = {PacketEventPriority.LOWEST};
for (Method method : methods) {
Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(e)) {
PacketHandler annotation = method.getAnnotation(PacketHandler.class);
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
if (e instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) e;
if (annotation.priority() >= eventPriority[0]) {
eventPriority[0] = annotation.priority();
isCancelled[0] = ce.isCancelled();
}
}
if (e instanceof CancellableEvent) {
CancellableEvent cancellableEvent = (CancellableEvent) e;
cancellableEvent.setCancelled(isCancelled[0]);
}
}
}
/**
* Register a deprecated event listener.
* Not recommended to use the deprecated event listener.
*
* @param listener {@link PacketListener}
* @return Same event manager instance.
*/
@Deprecated
default EventManager registerListener(PacketListener listener) {
if (listener != null) {
PEEventManager.EVENT_MANAGER_LEGACY.registerListener(listener);
}
return this;
}
public void registerListener(final PacketListener listener) {
final ConcurrentLinkedQueue<Method> methods = new ConcurrentLinkedQueue<>();
for (final Method m : listener.getClass().getDeclaredMethods()) {
if(!m.isAccessible()) {
m.setAccessible(true);
}
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
if (!methods.isEmpty()) {
if (ProtocolLibUtils.isAvailable()
&& PacketEvents.getSettings().shouldUseProtocolLibIfAvailable()) {
ProtocolLibListener.registerProtocolLibListener(listener, methods);
} else {
registeredMethods.put(listener, methods);
}
/**
* Register multiple deprecated event listeners with one method.
* Not recommended to use the deprecated event listener.
*
* @param listeners {@link PacketListener}
* @return Same event manager instance.
*/
@Deprecated
default EventManager registerListeners(PacketListener... listeners) {
PEEventManager.EVENT_MANAGER_LEGACY.registerListeners(listeners);
return this;
}
/**
* Unregister a deprecated event listener.
* Not recommended to use the deprecated event listener.
*
* @param listener {@link PacketListener}
* @return Same event manager instance.
*/
@Deprecated
default EventManager unregisterListener(PacketListener listener) {
PEEventManager.EVENT_MANAGER_LEGACY.unregisterListener(listener);
return this;
}
/**
* Unregister multiple deprecated event listeners with one method.
* Not recommended to use the deprecated event listener.
*
* @param listeners {@link PacketListener}
* @return Same event manager instance.
*/
@Deprecated
default EventManager unregisterListeners(PacketListener... listeners) {
PEEventManager.EVENT_MANAGER_LEGACY.unregisterListeners(listeners);
return this;
}
/**
* Register the dynamic event listener.
*
* @param listener {@link PacketListenerDynamic}
* @return Same event manager instance.
*/
default EventManager registerListener(PacketListenerDynamic listener) {
if (listener != null) {
PEEventManager.EVENT_MANAGER_DYNAMIC.registerListener(listener);
}
return this;
}
public void registerListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
registerListener(listener);
}
/**
* Register multiple dynamic event listeners with one method.
*
* @param listeners {@link PacketListenerDynamic}
* @return Same event manager instance.
*/
default EventManager registerListeners(PacketListenerDynamic... listeners) {
PEEventManager.EVENT_MANAGER_DYNAMIC.registerListeners(listeners);
return this;
}
public void unregisterListener(final PacketListener e) {
registeredMethods.remove(e);
/**
* Unregister the dynamic event listener.
*
* @param listener {@link PacketListenerDynamic}
* @return Same event manager instance.
*/
default EventManager unregisterListener(PacketListenerDynamic listener) {
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterListener(listener);
return this;
}
public void unregisterListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
unregisterListener(listener);
}
/**
* Unregister multiple dynamic event listeners with one method.
* Recommended to use the dynamic event listener.
*
* @param listeners {@link PacketListenerDynamic}
* @return Same event manager instance.
*/
default EventManager unregisterListeners(PacketListenerDynamic... listeners) {
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterListeners(listeners);
return this;
}
public void unregisterAllListeners() {
registeredMethods.clear();
}
public boolean isRegistered(final PacketListener listener) {
return registeredMethods.containsKey(listener);
/**
* Unregister all registered event listeners.
* All the deprecated and the dynamic listeners will be unregistered.
*
* @return Same event manager instance.
*/
default EventManager unregisterAllListeners() {
PEEventManager.EVENT_MANAGER_DYNAMIC.unregisterAllListeners();
PEEventManager.EVENT_MANAGER_LEGACY.unregisterAllListeners();
return this;
}
}
@@ -0,0 +1,145 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListenerDynamic;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import io.github.retrooper.packetevents.event.priority.PacketEventPriority;
import java.util.ArrayList;
import java.util.List;
class EventManagerDynamic {
/**
* All listeners ordered by their priority.
* The most low priority ones are at the begging of the list and the most high priority ones are at the end.
*/
private final List<PacketListenerDynamic> listeners = new ArrayList<>();
/**
* Call the PacketEvent.
* This method processes the event on all the registered dynamic packet event listeners.
* The {@link PacketEventPriority#LOWEST} prioritized listeners will be processing first,
* the {@link PacketEventPriority#MONITOR} will be processing last and can
* be the final decider whether the event has been cancelled or not.
* This call event also calls the legacy event manager call event.
*
* @param event {@link PacketEvent}
* @see EventManagerLegacy#callEvent(PacketEvent, byte)
*/
public void callEvent(final PacketEvent event) {
boolean cancel = false;
if (event instanceof CancellableEvent) {
cancel = ((CancellableEvent) event).isCancelled();
}
byte highestReachedPriority = PacketEventPriority.LOWEST.getPriorityValue();
for (PacketListenerDynamic listener : listeners) {
highestReachedPriority = listener.getPriority().getPriorityValue();
try {
event.callPacketEvent(listener);
event.call(listener);
}
catch (Exception ex) {
throw new IllegalStateException("PacketEvents found an exception while calling a packet listener.", ex);
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
cancel = ce.isCancelled();
}
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
ce.setCancelled(cancel);
}
PEEventManager.EVENT_MANAGER_LEGACY.callEvent(event, highestReachedPriority);
}
/**
* Register the dynamic packet event listener.
*
* @param listener {@link PacketListenerDynamic}
*/
public void registerListener(final PacketListenerDynamic listener) {
final byte priorityValue = listener.getPriority().getPriorityValue();
if (listeners.isEmpty()) {
listeners.add(listener);
return;
}
for (int i = 0; i < listeners.size(); i++) {
PacketListenerDynamic other = listeners.get(i);
byte otherPriorityValue = other.getPriority().getPriorityValue();
if (i + 1 == listeners.size()) {
listeners.add(listener);
break;
} else if (otherPriorityValue == priorityValue) {
listeners.add(i + 1, listener);
break;
} else if (otherPriorityValue > priorityValue) {
listeners.add(i, listener);
break;
}
}
}
/**
* Register multiple dynamic packet event listeners with one method.
*
* @param listeners {@link PacketListenerDynamic}
*/
public void registerListeners(PacketListenerDynamic... listeners) {
for (PacketListenerDynamic listener : listeners) {
registerListener(listener);
}
}
/**
* Unregister the dynamic packet event listener.
*
* @param listener {@link PacketListenerDynamic}
*/
public void unregisterListener(PacketListenerDynamic listener) {
listeners.remove(listener);
}
/**
* Unregister multiple dynamic packet event listeners with one method.
*
* @param listeners {@link PacketListenerDynamic}
*/
public void unregisterListeners(PacketListenerDynamic... listeners) {
for (PacketListenerDynamic listener : listeners) {
unregisterListener(listener);
}
}
/**
* Unregister all dynamic packet event listeners.
*/
public void unregisterAllListeners() {
listeners.clear();
}
}
@@ -0,0 +1,166 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.eventtypes.CancellableEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@Deprecated
class EventManagerLegacy {
/**
* Map storing all all legacy packet event listeners.
* The key is an individual listener, the values are the key's event methods.
*/
private final Map<PacketListener, HashSet<Method>> staticRegisteredMethods = new HashMap<>();
/**
* Call a PacketEvent with the legacy event manager.
* This method processes the event on all legacy packet event listeners.
* This method is actually called by {@link EventManagerDynamic#callEvent(PacketEvent)} as the
* if you mix the two event systems, the dynamic listeners are always processed first and pass
* their highest reached event priority that this legacy one has to beat/reach to be able to cancel
* the event.
* This downside of this system is the event listeners aren't executed in any particular order, just
* in the order they were registered.
* This system is also slower than the other event system.
*
* @param event {@link PacketEvent}
* @param eventPriority Priority the legacy listeners should beat to decide cancellation of the event.
*/
@Deprecated
public void callEvent(final PacketEvent event, byte eventPriority) {
boolean isCancelled = false;
if (event instanceof CancellableEvent) {
isCancelled = ((CancellableEvent) event).isCancelled();
}
//STATIC LISTENERS
for (final PacketListener listener : staticRegisteredMethods.keySet()) {
HashSet<Method> methods = staticRegisteredMethods.get(listener);
for (Method method : methods) {
Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(event)) {
PacketHandler annotation = method.getAnnotation(PacketHandler.class);
try {
method.invoke(listener, event);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
if (annotation.priority() >= eventPriority) {
eventPriority = annotation.priority();
isCancelled = ce.isCancelled();
}
}
}
}
}
if (event instanceof CancellableEvent) {
CancellableEvent ce = (CancellableEvent) event;
ce.setCancelled(isCancelled);
}
}
/**
* Register a legacy packet event listener.
* Not recommended to use the deprecated event listener.
*
* @param listener {@link PacketListener}
*/
@Deprecated
public void registerListener(final PacketListener listener) {
final HashSet<Method> methods = new HashSet<>();
for (final Method m : listener.getClass().getDeclaredMethods()) {
if (!m.isAccessible()) {
m.setAccessible(true);
}
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
if (!methods.isEmpty()) {
staticRegisteredMethods.put(listener, methods);
}
}
/**
* Register multiple legacy packet event listeners with one method.
* Not recommended to use the deprecated event listener.
*
* @param listeners {@link PacketListener}
*/
@Deprecated
public void registerListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
registerListener(listener);
}
}
/**
* Unregister a legacy packet event listener.
* Not recommended to use the deprecated event listener.
*
* @param listener {@link PacketListener}
*/
@Deprecated
public void unregisterListener(final PacketListener listener) {
staticRegisteredMethods.remove(listener);
}
/**
* Unregister multiple legacy packet event listeners with one method.
* Not recommended to use the deprecated event listener.
*
* @param listeners {@link PacketListener}
*/
@Deprecated
public void unregisterListeners(final PacketListener... listeners) {
for (final PacketListener listener : listeners) {
unregisterListener(listener);
}
}
/**
* Unregister all legacy packet event listeners.
*/
@Deprecated
public void unregisterAllListeners() {
staticRegisteredMethods.clear();
}
}
@@ -22,19 +22,17 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
package io.github.retrooper.packetevents.event.manager;
/**
* Guaranteed to not be null.
* Class storing a static instance of the dynamic and the legacy event manager.
*
* @author retrooper
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
public class PEEventManager implements EventManager {
public static final EventManagerLegacy EVENT_MANAGER_LEGACY = new EventManagerLegacy();
public static final EventManagerDynamic EVENT_MANAGER_DYNAMIC = new EventManagerDynamic();
}
@@ -24,11 +24,84 @@
package io.github.retrooper.packetevents.event.priority;
public interface PacketEventPriority {
byte LOWEST = 0;
byte LOW = 1;
byte NORMAL = 2;
byte HIGH = 3;
byte HIGHEST = 4;
byte MONITOR = 5;
/**
* Event priority enum for the new event system.
* The event priority counts for the whole {@link io.github.retrooper.packetevents.event.PacketListenerDynamic}
* and not for just one event.
* The priority can be specified in the PacketListenerDynamic constructor.
* If you don't specify a priority in the constructor, it will use the {@link #NORMAL} priority.
*
* @author retrooper
* @since 1.6.9
*/
public enum PacketEventPriority {
/**
* The weakest event priority.
* The first to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you need to be the first processing the event and
* need no power in cancelling an event or preventing an event cancellation.
*/
LOWEST((byte) 0),
/**
* A weak event priority.
* Second to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you would prefer to be one of the first to process the event,
* but don't mind if some other listener processes before you.
*/
LOW((byte) 1),
/**
* Default event priority.
* Third to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you don't really care/know when you process or just want to
* be in the middle.
*/
NORMAL((byte) 2),
/**
* Higher than the {@link PacketEventPriority#NORMAL} event priority.
* Fourth to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you want to process before the default event prioritized listeners.
*/
HIGH((byte) 3),
/**
* Second most powerful event priority.
* Fifth to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you prefer to be one of the last to process,
* but don't mind if some other listener really needs to process after you.
* Also use this if you prefer deciding if the event cancelled or not, but don't
* mind if some other listener urgently needs to decide over you.
* {@link PacketEventPriority#MONITOR} is rarely ever recommended to use.
*/
HIGHEST((byte) 4),
/**
* Most powerful event priority.
* Last(Sixth) to be processed(IN THE DYNAMIC EVENT SYSTEM ONLY).
* Use this if you urgently need to be the last to process
* or urgently need to be the final decider whether the event has cancelled or not.
* This is rarely recommended.
*/
MONITOR((byte) 5);
final byte priorityValue;
PacketEventPriority(byte priorityValue) {
this.priorityValue = priorityValue;
}
public byte getPriorityValue() {
return priorityValue;
}
public static PacketEventPriority getPacketEventPriority(byte bytePriority) {
for (PacketEventPriority priority : values()) {
if (priority.priorityValue == bytePriority) {
return priority;
}
}
return NORMAL;
}
}
@@ -1,60 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.annotation.PacketHandler;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.out.animation.WrappedPacketOutAnimation;
import io.github.retrooper.packetevents.packetwrappers.out.explosion.WrappedPacketOutExplosion;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin implements PacketListener {
@Override
public void onLoad() {
PacketEvents.load();
}
@Override
public void onEnable() {
PacketEvents.getSettings().injectAsync(true).ejectAsync(true)
.backupServerVersion(ServerVersion.v_1_7_10).
useProtocolLibIfAvailable(true).checkForUpdates(true).injectEarly(true);
PacketEvents.getAPI().getEventManager().registerListener(this);
PacketEvents.init(this);
}
@Override
public void onDisable() {
PacketEvents.stop();
}
}
@@ -22,24 +22,30 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
package io.github.retrooper.packetevents.exceptions;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.BlockIteratorUtils;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
public WrappedPacketInBlockPlace_1_9(final Player player, final Object packet) {
super(player, packet);
/**
* An exception thrown by PacketEvents when the {@link io.github.retrooper.packetevents.PacketEvents#load}
* method fails to execute without any exceptions.
* Resulting in PacketEvents failing to load.
*
* @author retrooper
* @since 1.7.6
*/
public class PacketEventsLoadFailureException extends RuntimeException {
public PacketEventsLoadFailureException(String message) {
super(message);
}
public Player getPlayer() {
return this.player;
public PacketEventsLoadFailureException(String message, Throwable cause) {
super(message, cause);
}
public Block getBlock() {
return BlockIteratorUtils.getBlockLookingAt(getPlayer(),3);
public PacketEventsLoadFailureException() {
this("PacketEvents failed to load...");
}
public PacketEventsLoadFailureException(Throwable cause) {
this("PacketEvents failed to load...", cause);
}
}
@@ -26,7 +26,16 @@ package io.github.retrooper.packetevents.exceptions;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
public class WrapperFieldNotFoundException extends RuntimeException{
/**
* An exception thrown by PacketEvents when a wrapper fails
* to find a field.
*
* @author retrooper
* @see io.github.retrooper.packetevents.packetwrappers.WrappedPacket#read(int, Class)
* @see io.github.retrooper.packetevents.packetwrappers.WrappedPacket#write(Class, int, Object)
* @since 1.6.9
*/
public class WrapperFieldNotFoundException extends RuntimeException {
public WrapperFieldNotFoundException(String message) {
super(message);
}
@@ -0,0 +1,446 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.injector.GlobalChannelInjector;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.login.in.handshake.WrappedPacketLoginInHandshake;
import io.github.retrooper.packetevents.packetwrappers.login.in.start.WrappedPacketLoginInStart;
import io.github.retrooper.packetevents.settings.PacketEventsSettings;
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* Internal manager of everything related to packets.
* For example injecting, channel caching, internal processing, packet sending....
* This class is only meant to be used internally.
* This could end up being refactored or renamed without a deprecation as it is only meant to be used internally.
*
* @author retrooper
* @see <a href="http://netty.io">http://netty.io</a>
* @since 1.7.9
*/
public class PacketHandlerInternal {
public final GlobalChannelInjector injector;
public final HashMap<UUID, Long> keepAliveMap = new HashMap<>();
public final Map<String, Object> channelMap = new WeakHashMap<>();
public PacketHandlerInternal(Plugin plugin) {
injector = new GlobalChannelInjector();
injector.prepare();
}
/**
* Get a player's netty channel object with their name.
* This netty channel object is cached in a {@link ConcurrentHashMap} as the value and
* the name is the key.
* We cache the name and the channel quite early infact,
* once we receive the {@link PacketType.Login.Client#START} packet(which contains the game profile)
* and the game profile contains the player name.
* The wrapper for that packet is {@link WrappedPacketLoginInStart}.
* If PacketEvents couldn't cache(when you have {@link PacketEventsSettings#shouldInjectEarly()} set to false),
* PacketEvents will use some reflection to see if CraftBukkit has the netty channel.
* If you access this before the START login packet was sent, you will for sure experience issues.
*
* @param player Target player.
* @return Netty channel of a player by their name.
* @see <a href="https://wiki.vg/Protocol#Login_Start">https://wiki.vg/Protocol#Login_Start</a>
* @see Player#getName()
*/
public Object getChannel(Player player) {
String name = player.getName();
Object channel = channelMap.get(name);
if (channel == null) {
channel = NMSUtils.getChannel(player);
channelMap.put(name, channel);
}
return channel;
}
/**
* Inject a player.
* Executed synchronously or asynchronously depending on what you have the associated setting set to.
* Injecting a player is basically pairing the cached netty channel
* {@link #getChannel(Player)} to a bukkit player object.
* Bukkit initializes the {@link Player} object some time after
* we inject the netty channel, so we need to pair the two.
* PacketEvents already injects a player when the bukkit
* {@link org.bukkit.event.player.PlayerJoinEvent} or {@link org.bukkit.event.player.PlayerLoginEvent}
* is called, depending on your {@link PacketEventsSettings#shouldInjectEarly()} setting is set to.
*
* @param player Target bukkit player.
*/
public void injectPlayer(Player player) {
if (PacketEvents.get().getSettings().shouldInjectAsync()) {
injectPlayerAsync(player);
} else {
injectPlayerSync(player);
}
}
/**
* Eject a player.
* Executed synchronously or asynchronously depending on what you have the associated setting set to.
* Ejecting a player is basically unpairing the cached netty channel
* {@link #getChannel(Player)} from the bukkit player.
* Do this if you want to stop listening to a user's packets.
* PacketEvents already ejects a player when the bukkit
* {@link org.bukkit.event.player.PlayerQuitEvent} is called.
*
* @param player Target player.
*/
public void ejectPlayer(Player player) {
if (PacketEvents.get().getSettings().shouldEjectAsync()) {
ejectPlayerAsync(player);
} else {
ejectPlayerSync(player);
}
}
/**
* Synchronously inject a player.
*
* @param player Target player.
* @see #injectPlayer(Player)
*/
public void injectPlayerSync(Player player) {
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, false);
PacketEvents.get().getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
injector.injectPlayerSync(player);
}
}
/**
* Asynchronously inject a player.
*
* @param player Target player.
* @see #injectPlayer(Player)
*/
public void injectPlayerAsync(Player player) {
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, true);
PacketEvents.get().getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
injector.injectPlayerAsync(player);
}
}
/**
* Synchronously eject a player.
*
* @param player Target player.
* @see #ejectPlayer(Player)
*/
public void ejectPlayerSync(Player player) {
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, false);
PacketEvents.get().getEventManager().callEvent(ejectEvent);
if (!ejectEvent.isCancelled()) {
injector.ejectPlayerSync(player);
keepAliveMap.remove(player.getUniqueId());
channelMap.remove(player.getName());
}
}
/**
* Asynchronously eject a player.
*
* @param player Target player.
* @see #ejectPlayer(Player)
*/
public void ejectPlayerAsync(Player player) {
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, true);
PacketEvents.get().getEventManager().callEvent(ejectEvent);
if (!ejectEvent.isCancelled()) {
injector.ejectPlayerAsync(player);
}
}
/**
* Write and flush a packet to a netty channel.
* This netty channel is an object as 1.7.10 and 1.8 and above
* have different netty package locations.
*
* @param channel Netty channel.
* @param packet NMS Packet.
*/
public void sendPacket(Object channel, Object packet) {
injector.sendPacket(channel, packet);
}
/**
* Make PacketEvents process an incoming packet.
*
* @param player Packet sender.
* @param channel Packet sender's netty channel.
* @param packet NMS Packet.
* @return NMS Packet, null if the event was cancelled.
*/
public Object read(Player player, Object channel, Object packet) {
if (PacketTypeClasses.Login.Client.START.equals(packet.getClass())) {
WrappedPacketLoginInStart startWrapper = new WrappedPacketLoginInStart(new NMSPacket(packet));
WrappedGameProfile gameProfile = startWrapper.getGameProfile();
channelMap.put(gameProfile.name, channel);
}
if (player == null) {
String simpleClassName = ClassUtil.getClassSimpleName(packet.getClass());
//Status packet
if (simpleClassName.startsWith("PacketS")) {
final PacketStatusReceiveEvent event = new PacketStatusReceiveEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptStatusReceive(event);
if (event.isCancelled()) {
packet = null;
}
} else {
//Login packet
final PacketLoginReceiveEvent event = new PacketLoginReceiveEvent(channel, new NMSPacket(packet));//Cache the channel
//f (event.getPacketId() == PacketType.Login.Client.START) {
// WrappedPacketLoginInStart startWrapper = new WrappedPacketLoginInStart(event.getNMSPacket());
//WrappedGameProfile gameProfile = startWrapper.getGameProfile();
//channelMap.put(gameProfile.name, channel);
//}
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptLoginReceive(event);
if (event.isCancelled()) {
packet = null;
}
}
} else {
final PacketPlayReceiveEvent event = new PacketPlayReceiveEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptRead(event);
if (event.isCancelled()) {
packet = null;
}
}
return packet;
}
/**
* Make PacketEvents process an outgoing packet.
* The NMS Packet will be null when netty should cancel a packet.
*
* @param player Packet receiver.
* @param channel Packet receiver's netty channel.
* @param packet NMS Packet.
* @return NMS Packet, null if the event was cancelled.
*/
public Object write(Player player, Object channel, Object packet) {
if (player == null) {
String simpleClassName = ClassUtil.getClassSimpleName(packet.getClass());
//Status packet
if (simpleClassName.startsWith("PacketS")) {
final PacketStatusSendEvent event = new PacketStatusSendEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptStatusSend(event);
if (event.isCancelled()) {
packet = null;
}
}
//Login packet
else {
final PacketLoginSendEvent event = new PacketLoginSendEvent(channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptLoginSend(event);
if (event.isCancelled()) {
packet = null;
}
}
} else {
final PacketPlaySendEvent event = new PacketPlaySendEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
packet = event.getNMSPacket().getRawNMSPacket();
interceptWrite(event);
if (event.isCancelled()) {
packet = null;
}
}
return packet;
}
/**
* Make PacketEvents process an incoming PLAY packet after minecraft has processed it.
* As minecraft has already processed the packet, we cannot cancel the action, nor the event.
*
* @param player Packet sender.
* @param channel Netty channel of the packet sender.
* @param packet NMS Packet.
*/
public void postRead(Player player, Object channel, Object packet) {
if (player != null) {
//Since player != null check is done, status and login packets won't come passed this point.
PostPacketPlayReceiveEvent event = new PostPacketPlayReceiveEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
interceptPostPlayReceive(event);
}
}
/**
* Make PacketEvents process an outgoing PLAY packet after minecraft has already sent the packet.
* This doesn't necessarily mean the client already received the packet,
* but the server has sent it for sure by this time.
* As minecraft has already processed the packet, we cannot cancel the action, nor the event.
*
* @param player Packet receiver.
* @param channel Netty channel of the packet receiver.
* @param packet NMS Packet.
*/
public void postWrite(Player player, Object channel, Object packet) {
if (player != null) {
//Since player != null check is done, status and login packets won't come passed this point.
PostPacketPlaySendEvent event = new PostPacketPlaySendEvent(player, channel, new NMSPacket(packet));
PacketEvents.get().getEventManager().callEvent(event);
interceptPostPlaySend(event);
}
}
/**
* Internal processing of an incoming PLAY packet.
*
* @param event PLAY server-bound packet event.
*/
private void interceptRead(PacketPlayReceiveEvent event) {
if (event.getPacketId() == PacketType.Play.Client.KEEP_ALIVE) {
UUID uuid = event.getPlayer().getUniqueId();
long timestamp = keepAliveMap.getOrDefault(uuid, event.getTimestamp());
long currentTime = event.getTimestamp();
long ping = currentTime - timestamp;
long smoothedPing = (PacketEvents.get().getPlayerUtils().getSmoothedPing(event.getPlayer()) * 3 + ping) / 4;
PacketEvents.get().getPlayerUtils().playerPingMap.put(uuid, (short) ping);
PacketEvents.get().getPlayerUtils().playerSmoothedPingMap.put(uuid, (short) smoothedPing);
}
}
/**
* Internal processing of an outgoing PLAY packet.
*
* @param event PLAY client-bound packet event.
*/
private void interceptWrite(PacketPlaySendEvent event) {
}
/**
* Internal processing of an incoming LOGIN packet.
*
* @param event LOGIN server-bound packet event.
*/
private void interceptLoginReceive(PacketLoginReceiveEvent event) {
if (event.getPacketId() == PacketType.Login.Client.HANDSHAKE) {
WrappedPacketLoginInHandshake handshake = new WrappedPacketLoginInHandshake(event.getNMSPacket());
int protocolVersion = handshake.getProtocolVersion();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.get().getPlayerUtils().tempClientVersionMap.put(event.getSocketAddress(), version);
}
}
/**
* Internal processing of an outgoing LOGIN packet.
*
* @param event client-bound LOGIN packet event.
*/
private void interceptLoginSend(PacketLoginSendEvent event) {
}
/**
* Internal processing of an incoming STATUS packet.
*
* @param event server-bound STATUS packet event.
*/
private void interceptStatusReceive(PacketStatusReceiveEvent event) {
}
/**
* Internal processing of an outgoing STATUS packet.
*
* @param event client-bound STATUS packet event.
*/
private void interceptStatusSend(PacketStatusSendEvent event) {
}
/**
* Internal processing of a packet that has already been processed by minecraft.
*
* @param event post server-bound play packet event.
*/
private void interceptPostPlayReceive(PostPacketPlayReceiveEvent event) {
}
/**
* Internal processing of a packet that has already been sent to a client.
* Doesn't necessarily mean the client has received it yet.
*
* @param event post client-bound play packet event.
*/
private void interceptPostPlaySend(PostPacketPlaySendEvent event) {
if (event.getPacketId() == PacketType.Play.Server.KEEP_ALIVE) {
if (event.getPlayer() != null) {
keepAliveMap.put(event.getPlayer().getUniqueId(), event.getTimestamp());
}
}
}
/**
* If you are using the EarlyInjector,
* calling this close method will unregister the channel handlers it registered when the plugin enabled.
* PacketEvents already unregisters them in the {@link PacketEvents#terminate()} method.
*/
public void cleanup() {
injector.cleanup();
}
/**
* If you are using the EarlyInjector,
* calling this close method will unregister the channel handlers it registered when the plugin enabled
* ASYNCHRONOUSLY.
* PacketEvents already unregisters them in the {@link PacketEvents#terminate()} method.
*/
public void cleanupAsync() {
injector.cleanupAsync();
}
}
@@ -0,0 +1,33 @@
package io.github.retrooper.packetevents.injector;
import io.github.retrooper.packetevents.PacketEvents;
import org.bukkit.entity.Player;
public interface ChannelInjector {
default void prepare() {
}
default void cleanup() {
}
default void cleanupAsync() {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
cleanup();
}
});
}
void injectPlayerSync(Player player);
void ejectPlayerSync(Player player);
void injectPlayerAsync(Player player);
void ejectPlayerAsync(Player player);
void sendPacket(Object channel, Object rawNMSPacket);
}
@@ -0,0 +1,65 @@
package io.github.retrooper.packetevents.injector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyChannelInjector7;
import io.github.retrooper.packetevents.injector.earlyinjector.EarlyChannelInjector8;
import io.github.retrooper.packetevents.injector.lateinjector.LateChannelInjector7;
import io.github.retrooper.packetevents.injector.lateinjector.LateChannelInjector8;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import org.bukkit.entity.Player;
public class GlobalChannelInjector implements ChannelInjector {
private final ChannelInjector injector;
public GlobalChannelInjector() {
boolean legacy = NMSUtils.legacyNettyImportMode;
//Early injector
if (PacketEvents.get().getSettings().shouldInjectEarly()) {
injector = legacy ? new EarlyChannelInjector7() : new EarlyChannelInjector8();
}
//Late injector
else {
injector = legacy ? new LateChannelInjector7() : new LateChannelInjector8();
}
}
@Override
public void prepare() {
injector.prepare();
}
@Override
public void cleanup() {
injector.cleanup();
}
@Override
public void cleanupAsync() {
injector.cleanupAsync();
}
@Override
public void injectPlayerSync(Player player) {
injector.injectPlayerSync(player);
}
@Override
public void ejectPlayerSync(Player player) {
injector.ejectPlayerSync(player);
}
@Override
public void injectPlayerAsync(Player player) {
injector.injectPlayerAsync(player);
}
@Override
public void ejectPlayerAsync(Player player) {
injector.ejectPlayerAsync(player);
}
@Override
public void sendPacket(Object channel, Object rawNMSPacket) {
injector.sendPacket(channel, rawNMSPacket);
}
}
@@ -0,0 +1,337 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.injector.earlyinjector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import net.minecraft.util.io.netty.channel.*;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 1.7.10 Spigot Early channel injector.
* This is an early injector for 1.7.10 spigot servers.
* The netty import on spigot changed since 1.8.
* So we needed to make a new class using the older import location to support 1.7.10.
* This is why we also commonly use a java {@link Object} class when it comes to netty channels
* in some classes to maintain support for both netty imports.
*
* @author retrooper
* @since 1.8
*/
public class EarlyChannelInjector7 implements EarlyInjector {
/**
* Netty minecraft server channels.
*/
private final List<Channel> serverChannels = new ArrayList<>();
/**
* First channel initializer.
* Used to inject incoming channels.
*/
private ChannelInitializer<Channel> firstChannelInitializer;
/**
* Second channel initializer.
*/
private ChannelInitializer<Channel> secondChannelInitializer;
/**
* Channel handler.
*/
private ChannelInboundHandlerAdapter channelHandler;
/**
* Network managers.
*/
private List<Object> networkMarkers;
/**
* Access minecraft's network managers to synchronize against as they interfere with our channel injection.
* Initiate the channel initializers and the channel handler.
* Access minecraft's server channels and add our own.
*/
@Override
public void prepare() {
networkMarkers = NMSUtils.getNetworkMarkers();
firstChannelInitializer = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(final Channel channel) {
if (networkMarkers != null) {
synchronized (networkMarkers) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
if (PacketEvents.get().getServerUtils().getVersion().isHigherThan(ServerVersion.v_1_11_2)) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
injectChannel(channel);
}
});
} else {
injectChannel(channel);
}
}
});
}
} else {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
if (PacketEvents.get().getServerUtils().getVersion().isHigherThan(ServerVersion.v_1_11_2)) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
injectChannel(channel);
}
});
} else {
injectChannel(channel);
}
}
});
}
}
};
secondChannelInitializer = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
channel.pipeline().addLast(firstChannelInitializer);
}
};
channelHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Channel channel = (Channel) msg;
channel.pipeline().addFirst(secondChannelInitializer);
ctx.fireChannelRead(msg);
}
};
//Wrapper for the minecraft server connection.
WrappedPacket serverConnectionWrapper = new WrappedPacket(new NMSPacket(NMSUtils.getMinecraftServerConnection()));
boolean searching = true;
for (int i = 0; searching; i++) {
try {
//Get the list.
List<Object> serverChannelList = (List<Object>) serverConnectionWrapper.readObject(i, List.class);
for (Object serverChannel : serverChannelList) {
//Is this the server channel list?
if (serverChannel instanceof ChannelFuture) {
//Yes it is...
Channel channel = ((ChannelFuture) serverChannel).channel();
serverChannels.add(channel);
//Add our channel handler to all the server channel pipelines.
channel.pipeline().addFirst(channelHandler);
searching = false;
}
}
} catch (Exception ex) {
break;
}
}
}
/**
* Remove our channel handler from all server channel pipelines from the current thread.
*/
@Override
public void cleanup() {
for (Channel channel : serverChannels) {
try {
channel.pipeline().remove(channelHandler);
} catch (NoSuchElementException ignored) {
}
}
}
/**
* Inject a netty channel to listen to packets.
* If already injected, get the channel interceptor.
*
* @param ch Netty channel.
* @return {@link PlayerChannelInterceptor}
*/
@Override
public PlayerChannelInterceptor injectChannel(Object ch) {
Channel channel = (Channel) ch;
String handlerName = PacketEvents.handlerName;
PlayerChannelInterceptor interceptor = (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
if (interceptor == null) {
interceptor = new PlayerChannelInterceptor();
if (channel.pipeline().get("packet_handler") != null) {
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
} else {
throw new IllegalStateException("Failed to inject an incoming channel due to \"packet_handler\" not being added to the pipeline! Let them rejoin!");
}
}
return interceptor;
}
/**
* Eject a netty channel.
*
* @param ch Netty channel.
*/
@Override
public void ejectChannel(Object ch) {
Channel channel = (Channel) ch;
String handlerName = PacketEvents.handlerName;
if (channel.pipeline().get(handlerName) != null) {
channel.pipeline().remove(handlerName);
}
}
/**
* Inject a player on the current thread.
*
* @param player Target player.
*/
@Override
public void injectPlayerSync(Player player) {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
injectChannel(channel).player = player;
}
/**
* Eject a player on the current thread.
*
* @param player Target player.
*/
@Override
public void ejectPlayerSync(Player player) {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
ejectChannel(channel);
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
/**
* Inject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
*
* @param player Target player.
*/
@Override
public void injectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
injectChannel(channel).player = player;
}
});
}
/**
* Eject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
*
* @param player Target player.
*/
@Override
public void ejectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
ejectChannel(channel);
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
});
}
/**
* Send a raw NMS packet to a netty channel.
*
* @param ch Netty channel.
* @param packet Raw NMS Packet.
*/
@Override
public void sendPacket(Object ch, Object packet) {
Channel channel = (Channel) ch;
channel.writeAndFlush(packet);
}
/**
* Player channel interceptor.
*
* @author retrooper
* @since 1.8
*/
public static class PlayerChannelInterceptor extends ChannelDuplexHandler {
/**
* Associated player.
* This is null until you inject the player.
* (We inject the PLAYER by PlayerLoginEvent or PlayerJoinEvent depending on your settings)
*/
public volatile Player player;
/**
* Incoming packet interception.
*
* @param ctx Netty channel handler context.
* @param packet Raw NMS Packet.
* @throws Exception Possible exception.
*/
@Override
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
if (packet != null) {
super.channelRead(ctx, packet);
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
}
}
/**
* Outgoing packet interception.
*
* @param ctx Netty channel handler context.
* @param packet Raw NMS Packet
* @param promise Netty channel promise.
* @throws Exception Possible exception.
*/
@Override
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
if (packet != null) {
super.write(ctx, packet, promise);
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
}
}
}
}
@@ -0,0 +1,332 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.injector.earlyinjector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.netty.channel.*;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 1.8 (and above) Spigot Early channel injector.
* This is an early injector for 1.8 (and above) spigot servers.
* The netty import on spigot changed since 1.8.
* So we needed to make separate classes for the 1.7.10 and the 1.8+ injector.
* This is why we also commonly use a java {@link Object} class when it comes to netty channels
* in some classes to maintain support for both netty imports.
*
* @author retrooper
* @since 1.8
*/
public class EarlyChannelInjector8 implements EarlyInjector {
/**
* Netty minecraft server channels.
*/
private final List<Channel> serverChannels = new ArrayList<>();
/**
* First channel initializer.
* Used to inject incoming channels.
*/
private ChannelInitializer<Channel> firstChannelInitializer;
/**
* Second channel initializer.
*/
private ChannelInitializer<Channel> secondChannelInitializer;
/**
* Channel handler.
*/
private ChannelInboundHandlerAdapter channelHandler;
/**
* Network managers.
*/
private List<Object> networkMarkers;
/**
* Access minecraft's network managers to synchronize against as they interfere with our channel injection.
* Initiate the channel initializers and the channel handler.
* Access minecraft's server channels and add our own.
*/
@Override
public void prepare() {
networkMarkers = NMSUtils.getNetworkMarkers();
firstChannelInitializer = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(final Channel channel) {
if (networkMarkers != null) {
synchronized (networkMarkers) {
if (PacketEvents.get().getServerUtils().getVersion().isHigherThan(ServerVersion.v_1_11_2)) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
injectChannel(channel);
}
});
} else {
injectChannel(channel);
}
}
} else {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
if (PacketEvents.get().getServerUtils().getVersion().isHigherThan(ServerVersion.v_1_11_2)) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
injectChannel(channel);
}
});
} else {
injectChannel(channel);
}
}
});
}
}
};
secondChannelInitializer = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
channel.pipeline().addLast(firstChannelInitializer);
}
};
channelHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Channel channel = (Channel) msg;
channel.pipeline().addFirst(secondChannelInitializer);
ctx.fireChannelRead(msg);
}
};
//Wrapper for the minecraft server connection.
WrappedPacket serverConnectionWrapper = new WrappedPacket(new NMSPacket(NMSUtils.getMinecraftServerConnection()));
boolean searching = true;
for (int i = 0; searching; i++) {
try {
//Get the list.
List<Object> serverChannelList = (List<Object>) serverConnectionWrapper.readObject(i, List.class);
for (Object serverChannel : serverChannelList) {
//Is this the server channel list?
if (serverChannel instanceof ChannelFuture) {
//Yes it is...
Channel channel = ((ChannelFuture) serverChannel).channel();
serverChannels.add(channel);
//Add our channel handler to all server channel pipelines.
channel.pipeline().addFirst(channelHandler);
searching = false;
}
}
} catch (Exception ex) {
break;
}
}
}
/**
* Remove our channel handler from all server channel pipelines from the current thread.
*/
@Override
public void cleanup() {
for (Channel channel : serverChannels) {
try {
channel.pipeline().remove(channelHandler);
} catch (NoSuchElementException ignored) {
}
}
}
/**
* Inject a netty channel to listen to packets.
* If already injected, get the channel interceptor.
*
* @param ch Netty channel.
* @return {@link PlayerChannelInterceptor}
*/
@Override
public PlayerChannelInterceptor injectChannel(Object ch) {
Channel channel = (Channel) ch;
final String handlerName = PacketEvents.handlerName;
try {
PlayerChannelInterceptor interceptor = (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
if (interceptor == null) {
interceptor = new PlayerChannelInterceptor();
if (channel.pipeline().get("packet_handler") != null) {
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
}
}
return interceptor;
} catch (IllegalArgumentException ex) {
//Let us try again
return (PlayerChannelInterceptor) channel.pipeline().get(handlerName);
}
}
/**
* Eject a netty channel.
*
* @param ch Netty channel.
*/
@Override
public void ejectChannel(Object ch) {
Channel channel = (Channel) ch;
String handlerName = PacketEvents.handlerName;
if (channel.pipeline().get(handlerName) != null) {
channel.pipeline().remove(handlerName);
}
}
/**
* Inject a player on the current thread.
*
* @param player Target player.
*/
@Override
public void injectPlayerSync(Player player) {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
injectChannel(channel).player = player;
}
/**
* Eject a player on the current thread.
*
* @param player Target player.
*/
@Override
public void ejectPlayerSync(Player player) {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
ejectChannel(channel);
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
/**
* Inject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
*
* @param player Target player.
*/
@Override
public void injectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
injectChannel(channel).player = player;
}
});
}
/**
* Eject a player on our custom inject and eject (fixed) thread pool (=asynchronously).
*
* @param player Target player.
*/
@Override
public void ejectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
ejectChannel(channel);
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
});
}
/**
* Send a raw NMS packet to a netty channel.
*
* @param ch Netty channel.
* @param packet Raw NMS Packet.
*/
@Override
public void sendPacket(Object ch, Object packet) {
Channel channel = (Channel) ch;
channel.writeAndFlush(packet);
}
/**
* Player channel interceptor.
*
* @author retrooper
* @since 1.8
*/
public static class PlayerChannelInterceptor extends ChannelDuplexHandler {
/**
* Associated player.
* This is null until you inject the player.
* (We inject the PLAYER by PlayerLoginEvent or PlayerJoinEvent depending on your settings)
*/
public volatile Player player;
/**
* Incoming packet interception.
*
* @param ctx Netty channel handler context.
* @param packet Raw NMS Packet.
* @throws Exception Possible exception.
*/
@Override
public void channelRead(final ChannelHandlerContext ctx, Object packet) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
if (packet != null) {
super.channelRead(ctx, packet);
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
}
}
/**
* Outgoing packet interception.
*
* @param ctx Netty channel handler context.
* @param packet Raw NMS Packet
* @param promise Netty channel promise.
* @throws Exception Possible exception.
*/
@Override
public void write(final ChannelHandlerContext ctx, Object packet, final ChannelPromise promise) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
if (packet != null) {
super.write(ctx, packet, promise);
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
}
}
}
}
@@ -0,0 +1,13 @@
package io.github.retrooper.packetevents.injector.earlyinjector;
import io.github.retrooper.packetevents.injector.ChannelInjector;
public interface EarlyInjector extends ChannelInjector {
void prepare();
void cleanup();
Object injectChannel(Object channel);
void ejectChannel(Object channel);
}
@@ -0,0 +1,102 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.injector.lateinjector;
import io.github.retrooper.packetevents.PacketEvents;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;
public class LateChannelInjector7 implements LateInjector {
@Override
public void injectPlayerSync(Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
if (packet != null) {
super.channelRead(ctx, packet);
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
if (packet != null) {
super.write(ctx, packet, promise);
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
}
}
};
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelDuplexHandler);
}
@Override
public void ejectPlayerSync(Player player) {
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
channel.pipeline().remove(PacketEvents.handlerName);
}
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
@Override
public void injectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
injectPlayerSync(player);
}
});
}
@Override
public void ejectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
channel.pipeline().remove(PacketEvents.handlerName);
}
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
});
}
@Override
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel) rawChannel;
channel.pipeline().writeAndFlush(packet);
}
}
@@ -0,0 +1,112 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.injector.lateinjector;
import io.github.retrooper.packetevents.PacketEvents;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;
import java.util.NoSuchElementException;
public class LateChannelInjector8 implements LateInjector {
@Override
public void injectPlayerSync(Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.read(player, ctx.channel(), packet);
if (packet != null) {
super.channelRead(ctx, packet);
PacketEvents.get().packetHandlerInternal.postRead(player, ctx.channel(), packet);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
packet = PacketEvents.get().packetHandlerInternal.write(player, ctx.channel(), packet);
if (packet != null) {
super.write(ctx, packet, promise);
PacketEvents.get().packetHandlerInternal.postWrite(player, ctx.channel(), packet);
}
}
};
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
channel.pipeline().addBefore("packet_handler", PacketEvents.handlerName, channelDuplexHandler);
}
@Override
public void ejectPlayerSync(Player player) {
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
try {
channel.pipeline().remove(PacketEvents.handlerName);
} catch (NoSuchElementException ignored) {
}
}
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
@Override
public void injectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
injectPlayerSync(player);
}
});
}
@Override
public void ejectPlayerAsync(Player player) {
PacketEvents.get().injectAndEjectExecutorService.execute(new Runnable() {
@Override
public void run() {
final Channel channel = (Channel) PacketEvents.get().packetHandlerInternal.getChannel(player);
if (channel.pipeline().get(PacketEvents.handlerName) != null) {
try {
channel.pipeline().remove(PacketEvents.handlerName);
} catch (NoSuchElementException ignored) {
}
}
PacketEvents.get().packetHandlerInternal.keepAliveMap.remove(player.getUniqueId());
PacketEvents.get().packetHandlerInternal.channelMap.remove(player.getName());
PacketEvents.get().getPlayerUtils().clientVersionsMap.remove(player.getAddress());
PacketEvents.get().getPlayerUtils().tempClientVersionMap.remove(player.getAddress());
}
});
}
@Override
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel) rawChannel;
channel.pipeline().writeAndFlush(packet);
}
}
@@ -0,0 +1,7 @@
package io.github.retrooper.packetevents.injector.lateinjector;
import io.github.retrooper.packetevents.injector.ChannelInjector;
public interface LateInjector extends ChannelInjector {
}
@@ -1,266 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetmanager;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.TinyProtocol;
import io.github.retrooper.packetevents.packettype.PacketType;
import io.github.retrooper.packetevents.packetwrappers.login.in.WrappedPacketLoginHandshake;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.ClientVersion;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.versionlookup.VersionLookupUtils;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.UUID;
public class PacketManager {
private final Plugin plugin;
private final boolean tinyProtocolMode;
public final TinyProtocol tinyProtocol;
public final NettyPacketManager nettyProtocol;
private final HashMap<UUID, Long> keepAliveMap = new HashMap<>();
public PacketManager(Plugin plugin, boolean tinyProtocolMode) {
this.plugin = plugin;
this.tinyProtocolMode = tinyProtocolMode;
if (tinyProtocolMode) {
tinyProtocol = new TinyProtocol(plugin);
nettyProtocol = null;
} else {
tinyProtocol = null;
nettyProtocol = new NettyPacketManager(plugin);
}
}
public void injectPlayer(Player player) {
if (PacketEvents.getSettings().shouldInjectAsync()) {
injectPlayerAsync(player);
} else {
injectPlayerSync(player);
}
}
public void ejectPlayer(Player player) {
if (PacketEvents.getSettings().shouldEjectAsync()) {
ejectPlayerAsync(player);
} else {
ejectPlayerSync(player);
}
}
public void injectPlayerSync(Player player) {
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, false);
PacketEvents.getAPI().getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
if (tinyProtocolMode) {
tinyProtocol.injectPlayer(player);
} else {
nettyProtocol.injectPlayer(player);
}
}
}
public void injectPlayerAsync(Player player) {
PlayerInjectEvent injectEvent = new PlayerInjectEvent(player, true);
PacketEvents.getAPI().getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
if (tinyProtocolMode) {
tinyProtocol.injectPlayerAsync(player);
} else {
nettyProtocol.injectPlayerAsync(player);
}
}
}
public void ejectPlayerSync(Player player) {
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, false);
PacketEvents.getAPI().getEventManager().callEvent(ejectEvent);
if (!ejectEvent.isCancelled()) {
keepAliveMap.remove(player.getUniqueId());
NMSUtils.channelCache.remove(player.getUniqueId());
if (tinyProtocolMode) {
tinyProtocol.ejectPlayer(player);
} else {
nettyProtocol.ejectPlayer(player);
}
}
}
public void ejectPlayerAsync(Player player) {
PlayerEjectEvent ejectEvent = new PlayerEjectEvent(player, true);
PacketEvents.getAPI().getEventManager().callEvent(ejectEvent);
if (!ejectEvent.isCancelled()) {
keepAliveMap.remove(player.getUniqueId());
NMSUtils.channelCache.remove(player.getUniqueId());
if (tinyProtocolMode) {
tinyProtocol.ejectPlayerAsync(player);
} else {
nettyProtocol.ejectPlayerAsync(player);
}
}
}
public void sendPacket(Object channel, Object packet) {
if (tinyProtocolMode) {
tinyProtocol.sendPacket(channel, packet);
} else {
nettyProtocol.sendPacket(channel, packet);
}
}
public Object read(Player player, Object channel, Object packet) {
switch (ClassUtil.getClassSimpleName(packet.getClass())) {
case "PacketHandshakingInSetProtocol":
case "PacketLoginInCustomPayload":
case "PacketLoginInStart":
case "PacketLoginInEncryptionBegin":
final PacketLoginEvent packetLoginEvent = new PacketLoginEvent(channel, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetLoginEvent);
interceptLogin(packetLoginEvent);
if (packetLoginEvent.isCancelled()) {
packet = null;
}
break;
case "PacketStatusInPing":
final PacketStatusEvent packetStatusEvent = new PacketStatusEvent(channel, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetStatusEvent);
interceptStatus(packetStatusEvent);
if (packetStatusEvent.isCancelled()) {
packet = null;
}
break;
default:
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(player, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetReceiveEvent);
interceptRead(packetReceiveEvent);
if (packetReceiveEvent.isCancelled()) {
packet = null;
}
break;
}
return packet;
}
public Object write(Player player, Object channel, Object packet) {
switch (ClassUtil.getClassSimpleName(packet.getClass())) {
case "PacketLoginOutDisconnect":
case "PacketLoginOutEncryptionBegin":
case "PacketLoginOutSetCompression":
case "PacketLoginOutSuccess":
final PacketLoginEvent packetLoginEvent = new PacketLoginEvent(channel, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetLoginEvent);
interceptLogin(packetLoginEvent);
if (packetLoginEvent.isCancelled()) {
packet = null;
}
break;
case "PacketStatusOutPong":
final PacketStatusEvent packetStatusEvent = new PacketStatusEvent(channel, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetStatusEvent);
interceptStatus(packetStatusEvent);
if (packetStatusEvent.isCancelled()) {
packet = null;
}
break;
default:
final PacketSendEvent packetSendEvent = new PacketSendEvent(player, packet);
PacketEvents.getAPI().getEventManager().callEvent(packetSendEvent);
interceptWrite(packetSendEvent);
if (packetSendEvent.isCancelled()) {
packet = null;
}
break;
}
return packet;
}
public void postRead(Player player, Object packet) {
switch (ClassUtil.getClassSimpleName(packet.getClass())) {
case "PacketHandshakingInSetProtocol":
case "PacketLoginInCustomPayload":
case "PacketLoginInStart":
case "PacketLoginInEncryptionBegin":
case "PacketStatusInPing":
break;
default:
PacketEvents.getAPI().getEventManager().callEvent(new PostPacketReceiveEvent(player, packet));
break;
}
}
public void postWrite(Player player, Object packet) {
switch (ClassUtil.getClassSimpleName(packet.getClass())) {
case "PacketLoginOutDisconnect":
case "PacketLoginOutEncryptionBegin":
case "PacketLoginOutSetCompression":
case "PacketLoginOutSuccess":
case "PacketStatusOutPong":
break;
default:
PacketEvents.getAPI().getEventManager().callEvent(new PostPacketSendEvent(player, packet));
break;
}
}
private void interceptRead(PacketReceiveEvent event) {
if (event.getPacketId() == PacketType.Client.KEEP_ALIVE) {
UUID uuid = event.getPlayer().getUniqueId();
long timestamp = keepAliveMap.getOrDefault(uuid, event.getTimestamp());
long currentTime = event.getTimestamp();
long ping = currentTime - timestamp;
long smoothedPing = ((PacketEvents.getAPI().getPlayerUtils().getSmoothedPing(event.getPlayer()) * 3) + ping) / 4;
PacketEvents.getAPI().getPlayerUtils().playerPingMap.put(uuid, (short) ping);
PacketEvents.getAPI().getPlayerUtils().playerSmoothedPingMap.put(uuid, (short) smoothedPing);
}
}
private void interceptWrite(PacketSendEvent event) {
if (event.getPacketId() == PacketType.Server.KEEP_ALIVE) {
keepAliveMap.put(event.getPlayer().getUniqueId(), event.getTimestamp());
}
}
private void interceptLogin(PacketLoginEvent event) {
if (event.getPacketId() == PacketType.Login.HANDSHAKE) {
if (!VersionLookupUtils.isDependencyAvailable()) {
WrappedPacketLoginHandshake handshake = new WrappedPacketLoginHandshake(event.getNMSPacket());
int protocolVersion = handshake.getProtocolVersion();
ClientVersion version = ClientVersion.getClientVersion(protocolVersion);
PacketEvents.getAPI().getPlayerUtils().clientVersionsMap.put(event.getChannel(), version);
}
}
}
private void interceptStatus(PacketStatusEvent event) {
}
}
@@ -1,136 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetmanager.netty;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NettyPacketManager {
public static boolean v1_7_nettyMode = false;
public static final ExecutorService
executorService =
Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors(), 64));
static {
try {
Class.forName("io.netty.channel.Channel");
} catch (ClassNotFoundException e) {
v1_7_nettyMode = true;
}
}
private Plugin plugin;
private Object npm;
public NettyPacketManager(Plugin plugin) {
this.plugin = plugin;
if (v1_7_nettyMode) {
npm = new NettyPacketManager_7();
} else {
npm = new NettyPacketManager_8();
}
}
/**
* Synchronously inject a player
*
* @param player Target player to inject
*/
public void injectPlayer(final Player player) {
if (v1_7_nettyMode) {
NettyPacketManager_7 npm_7 = (NettyPacketManager_7)npm;
npm_7.injectPlayer(player);
} else {
NettyPacketManager_8 npm_8 = (NettyPacketManager_8)npm;
npm_8.injectPlayer(player);
}
}
/**
* Asynchronously inject a player
*
* @param player
*/
public void injectPlayerAsync(final Player player) {
//Redundant channel variable created just so we can cache it synchronously.
Object channel = NMSUtils.getChannel(player);
executorService.execute(() -> {
if (v1_7_nettyMode) {
NettyPacketManager_7 npm_7 = (NettyPacketManager_7)npm;
npm_7.injectPlayer(player);
} else {
NettyPacketManager_8 npm_8 = (NettyPacketManager_8)npm;
npm_8.injectPlayer(player);
}
});
}
/**
* Synchronously eject a player.
*
* @param player
*/
public void ejectPlayer(final Player player) {
if (v1_7_nettyMode) {
NettyPacketManager_7 npm_7 = (NettyPacketManager_7)npm;
npm_7.ejectPlayer(player);
} else {
NettyPacketManager_8 npm_8 = (NettyPacketManager_8)npm;
npm_8.ejectPlayer(player);
}
}
/**
* Asynchronously eject a player
*
* @param player
*/
public void ejectPlayerAsync(final Player player) {
executorService.execute(() -> {
if (v1_7_nettyMode) {
NettyPacketManager_7 npm_7 = (NettyPacketManager_7)npm;
npm_7.ejectPlayer(player);
} else {
NettyPacketManager_8 npm_8 = (NettyPacketManager_8)npm;
npm_8.ejectPlayer(player);
}
});
}
public void sendPacket(Object channel, Object packet) {
if (v1_7_nettyMode) {
NettyPacketManager_7 npm_7 = (NettyPacketManager_7)npm;
npm_7.sendPacket(channel, packet);
} else {
NettyPacketManager_8 npm_8 = (NettyPacketManager_8)npm;
npm_8.sendPacket(channel, packet);
}
}
}
@@ -1,84 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetmanager.netty;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelPipeline;
import net.minecraft.util.io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;
final class NettyPacketManager_7 {
NettyPacketManager_7() {
}
/**
* Inject a player using 1.7.10's netty import location
* @param player
*/
public void injectPlayer(final Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Object packet = PacketEvents.getAPI().packetManager.read(player, ctx.channel(), msg);
if (packet == null) {
return;
}
super.channelRead(ctx, msg);
PacketEvents.getAPI().packetManager.postRead(player, packet);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
Object packet = PacketEvents.getAPI().packetManager.write(player, ctx.channel(),msg);
if (packet == null) {
return;
}
super.write(ctx, msg, promise);
PacketEvents.getAPI().packetManager.postWrite(player, packet);
}
};
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
pipeline.addBefore("packet_handler", PacketEvents.getHandlerName(player.getName()), channelDuplexHandler);
}
/**
* Eject a player using 1.7.10 netty import location.
* @param player Target Player
*/
public void ejectPlayer(final Player player) {
Channel channel = (Channel) NMSUtils.getChannelNoCache(player);
assert channel != null;
channel.pipeline().remove(PacketEvents.getHandlerName(player.getName()));
}
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel)rawChannel;
channel.pipeline().writeAndFlush(packet);
}
}
@@ -1,84 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetmanager.netty;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;
final class NettyPacketManager_8 {
NettyPacketManager_8() {
}
/**
* Inject a player with 1.8+ netty import location.
* @param player
*/
public void injectPlayer(final Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Object packet = PacketEvents.getAPI().packetManager.read(player, ctx.channel(),msg);
if (packet == null) {
return;
}
super.channelRead(ctx, msg);
PacketEvents.getAPI().packetManager.postRead(player, packet);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
Object packet = PacketEvents.getAPI().packetManager.write(player, ctx.channel(),msg);
if (packet == null) {
return;
}
super.write(ctx, msg, promise);
PacketEvents.getAPI().packetManager.postWrite(player, packet);
}
};
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
pipeline.addBefore("packet_handler", PacketEvents.getHandlerName(player.getName()), channelDuplexHandler);
}
/**
* Eject a player with 1.8+ netty import location.
* @param player
*/
public void ejectPlayer(final Player player) {
final Channel channel = (Channel) NMSUtils.getChannelNoCache(player);
assert channel != null;
channel.pipeline().remove(PacketEvents.getHandlerName(player.getName()));
}
public void sendPacket(Object rawChannel, Object packet) {
Channel channel = (Channel)rawChannel;
channel.pipeline().writeAndFlush(packet);
}
}
@@ -1,376 +0,0 @@
package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
/**
* An utility class that simplifies reflection in Bukkit plugins.
*
* @author Kristian
*/
public final class Reflection {
/**
* An interface for invoking a specific constructor.
*/
public interface ConstructorInvoker {
/**
* Invoke a constructor for a specific class.
*
* @param arguments - the arguments to pass to the constructor.
* @return The constructed object.
*/
Object invoke(Object... arguments);
}
/**
* An interface for invoking a specific method.
*/
public interface MethodInvoker {
/**
* Invoke a method on a specific target object.
*
* @param target - the target object, or NULL for a static method.
* @param arguments - the arguments to pass to the method.
* @return The return value, or NULL if is void.
*/
Object invoke(Object target, Object... arguments);
}
/**
* An interface for retrieving the field content.
*
* @param <T> - field type.
*/
public interface FieldAccessor<T> {
/**
* Retrieve the content of a field.
*
* @param target - the target object, or NULL for a static field.
* @return The value of the field.
*/
T get(Object target);
/**
* Set the content of a field.
*
* @param target - the target object, or NULL for a static field.
* @param value - the new value of the field.
*/
void set(Object target, Object value);
/**
* Determine if the given object has this field.
*
* @param target - the object to test.
* @return TRUE if it does, FALSE otherwise.
*/
boolean hasField(Object target);
}
// Deduce the net.minecraft.server.v* package
private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server");
private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", "");
// Variable replacement
private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");
private Reflection() {
// Seal class
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param target - the target type.
* @param name - the name of the field, or NULL to ignore.
* @param fieldType - a compatible field type.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType) {
return getField(target, name, fieldType, 0);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param name - the name of the field, or NULL to ignore.
* @param fieldType - a compatible field type.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(String className, String name, Class<T> fieldType) {
return getField(getClass(className), name, fieldType, 0);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param target - the target type.
* @param fieldType - a compatible field type.
* @param index - the number of compatible fields to skip.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(Class<?> target, Class<T> fieldType, int index) {
return getField(target, null, fieldType, index);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param fieldType - a compatible field type.
* @param index - the number of compatible fields to skip.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(String className, Class<T> fieldType, int index) {
return getField(getClass(className), fieldType, index);
}
// Common method
private static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType, int index) {
for (final Field field : target.getDeclaredFields()) {
if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) {
field.setAccessible(true);
// A function for retrieving a specific field value
return new FieldAccessor<T>() {
@Override
@SuppressWarnings("unchecked")
public T get(Object target) {
try {
return (T) field.get(target);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access reflection.", e);
}
}
@Override
public void set(Object target, Object value) {
try {
field.set(target, value);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access reflection.", e);
}
}
@Override
public boolean hasField(Object target) {
// target instanceof DeclaringClass
return field.getDeclaringClass().isAssignableFrom(target.getClass());
}
};
}
}
// Search in parent classes
if (target.getSuperclass() != null)
return getField(target.getSuperclass(), name, fieldType, index);
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getMethod(String className, String methodName, Class<?>... params) {
return getTypedMethod(getClass(className), methodName, null, params);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getMethod(Class<?> clazz, String methodName, Class<?>... params) {
return getTypedMethod(clazz, methodName, null, params);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param returnType - the expected return type, or NULL to ignore.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getTypedMethod(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... params) {
for (final Method method : clazz.getDeclaredMethods()) {
if ((methodName == null || method.getName().equals(methodName))
&& (returnType == null || method.getReturnType().equals(returnType))
&& Arrays.equals(method.getParameterTypes(), params)) {
method.setAccessible(true);
return new MethodInvoker() {
@Override
public Object invoke(Object target, Object... arguments) {
try {
return method.invoke(target, arguments);
} catch (Exception e) {
throw new RuntimeException("Cannot invoke method " + method, e);
}
}
};
}
}
// Search in every superclass
if (clazz.getSuperclass() != null)
return getMethod(clazz.getSuperclass(), methodName, params);
throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params)));
}
/**
* Search for the first publically and privately defined constructor of the given name and parameter count.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param params - the expected parameters.
* @return An object that invokes this constructor.
* @throws IllegalStateException If we cannot find this method.
*/
public static ConstructorInvoker getConstructor(String className, Class<?>... params) {
return getConstructor(getClass(className), params);
}
/**
* Search for the first publically and privately defined constructor of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param params - the expected parameters.
* @return An object that invokes this constructor.
* @throws IllegalStateException If we cannot find this method.
*/
public static ConstructorInvoker getConstructor(Class<?> clazz, Class<?>... params) {
for (final Constructor<?> constructor : clazz.getDeclaredConstructors()) {
if (Arrays.equals(constructor.getParameterTypes(), params)) {
constructor.setAccessible(true);
return new ConstructorInvoker() {
@Override
public Object invoke(Object... arguments) {
try {
return constructor.newInstance(arguments);
} catch (Exception e) {
throw new RuntimeException("Cannot invoke constructor " + constructor, e);
}
}
};
}
}
throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params)));
}
/**
* Retrieve a class from its full name, without knowing its type on compile time.
* <p>
* This is useful when looking up fields by a NMS or OBC type.
* <p>
*
* See {@link #getClass()} for more information.
* @param lookupName - the class name with variables.
* @return The class.
*/
public static Class<Object> getUntypedClass(String lookupName) {
@SuppressWarnings({ "rawtypes", "unchecked" })
Class<Object> clazz = (Class) getClass(lookupName);
return clazz;
}
public static Class<?> getClass(String lookupName) {
return getCanonicalClass(expandVariables(lookupName));
}
/**
* Retrieve a class in the net.minecraft.server.VERSION.* package.
*
* @param name - the name of the class, excluding the package.
* @throws IllegalArgumentException If the class doesn't exist.
*/
public static Class<?> getMinecraftClass(String name) {
return getCanonicalClass(NMS_PREFIX + "." + name);
}
/**
* Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package.
*
* @param name - the name of the class, excluding the package.
* @throws IllegalArgumentException If the class doesn't exist.
*/
public static Class<?> getCraftBukkitClass(String name) {
return getCanonicalClass(OBC_PREFIX + "." + name);
}
/**
* Retrieve a class by its canonical name.
*
* @param canonicalName - the canonical name.
* @return The class.
*/
private static Class<?> getCanonicalClass(String canonicalName) {
try {
return Class.forName(canonicalName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Cannot find " + canonicalName, e);
}
}
/**
* Expand variables such as "{nms}" and "{obc}" to their corresponding packages.
*
* @param name - the full name of the class.
* @return The expanded string.
*/
private static String expandVariables(String name) {
StringBuffer output = new StringBuffer();
Matcher matcher = MATCH_VARIABLE.matcher(name);
while (matcher.find()) {
String variable = matcher.group(1);
String replacement = "";
// Expand all detected variables
if ("nms".equalsIgnoreCase(variable))
replacement = NMS_PREFIX;
else if ("obc".equalsIgnoreCase(variable))
replacement = OBC_PREFIX;
else if ("version".equalsIgnoreCase(variable))
replacement = VERSION;
else
throw new IllegalArgumentException("Unknown variable: " + variable);
// Assume the expanded variables are all packages, and append a dot
if (replacement.length() > 0 && matcher.end() < name.length() && name.charAt(matcher.end()) != '.')
replacement += ".";
matcher.appendReplacement(output, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(output);
return output.toString();
}
}
@@ -1,120 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class TinyProtocol {
private final Object tinyProt;
public TinyProtocol(Plugin plugin) {
if (NettyPacketManager.v1_7_nettyMode) {
tinyProt = new TinyProtocol7(plugin);
} else {
tinyProt = new TinyProtocol8(plugin);
}
}
public void injectPlayer(Player player) {
if (!NettyPacketManager.v1_7_nettyMode) {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.injectPlayer(player);
} else {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.injectPlayer(player);
}
}
public void injectPlayerAsync(Player player) {
if (!NettyPacketManager.v1_7_nettyMode) {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.injectPlayerAsync(player);
} else {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.injectPlayerAsync(player);
}
}
public void ejectPlayer(Player player) {
if (!NettyPacketManager.v1_7_nettyMode) {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.uninjectPlayer(player);
} else {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.uninjectPlayer(player);
}
}
public void ejectPlayerAsync(Player player) {
if (!NettyPacketManager.v1_7_nettyMode) {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.uninjectPlayerAsync(player);
} else {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.uninjectPlayerAsync(player);
}
}
public void sendPacket(Object channel, Object packet) {
if (!NettyPacketManager.v1_7_nettyMode) {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
tp8.sendPacket(channel, packet);
} else {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
tp7.sendPacket(channel, packet);
}
}
public Object read(Player player, Object channel, Object packet) {
return PacketEvents.getAPI().packetManager.read(player, channel, packet);
}
public Object write(Player player, Object channel, Object packet) {
return PacketEvents.getAPI().packetManager.write(player, channel, packet);
}
public Object getChannel(Player player) {
if (NettyPacketManager.v1_7_nettyMode) {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
return tp7.getChannel(player);
} else {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
return tp8.getChannel(player);
}
}
public boolean canInject(Player player) {
if (NettyPacketManager.v1_7_nettyMode) {
TinyProtocol7 tp7 = (TinyProtocol7) tinyProt;
return !tp7.uninjectedChannels.contains(getChannel(player));
} else {
TinyProtocol8 tp8 = (TinyProtocol8) tinyProt;
return !tp8.uninjectedChannels.contains(getChannel(player));
}
}
}
@@ -1,551 +0,0 @@
/*
* This file is part of Hawk Anticheat.
* Copyright (C) 2018 Hawk Development Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import net.minecraft.util.com.google.common.collect.Lists;
import net.minecraft.util.com.google.common.collect.MapMaker;
import net.minecraft.util.com.mojang.authlib.GameProfile;
import net.minecraft.util.io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
/**
* Represents a very tiny alternative to ProtocolLib.
* <p>
* It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)!
*
* @author Kristian
*/
//BROKEN: NPEs when player joins while server is starting, and using PlayerJoinEvent instead will cause NPE for protocol version lookup.
//Protocol version number lookup method from DeprecatedLuke's version of TinyProtocol
public class TinyProtocol7 {
private static final AtomicInteger ID = new AtomicInteger();
// Used in order to lookup a channel
private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
private static final FieldAccessor<Object> getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
private static final FieldAccessor<Channel> getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
// Looking up ServerConnection
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
private static final MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
// Packets we have to intercept
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
private static final Class<?> PACKET_HANDSHAKING_IN_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol");
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
// Speedup channel/protocol lookup
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Listener listener;
// Channels that have already been removed
public Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
// List of network markers
private List<Object> networkManagers;
// Injected channel handlers
private List<Channel> serverChannels = Lists.newArrayList();
private ChannelInboundHandlerAdapter serverChannelHandler;
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
// Current handler name
private String handlerName;
protected volatile boolean closed;
protected Plugin plugin;
/**
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
* <p>
* You can construct multiple instances per plugin.
*
* @param plugin - the plugin.
*/
public TinyProtocol7(final Plugin plugin) {
this.plugin = plugin;
// Compute handler name
this.handlerName = getHandlerName();
try {
registerChannelHandler();
registerPlayers(plugin);
} catch (IllegalArgumentException ex) {
// Damn you, late bind
plugin.getLogger().info("Delaying server channel injection due to late bind.");
new BukkitRunnable() {
@Override
public void run() {
registerChannelHandler();
registerPlayers(plugin);
plugin.getLogger().info("Late bind injection successful.");
}
}.runTask(plugin);
}
}
private void createServerChannelHandler() {
// Handle connected channels
endInitProtocol = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
try {
// This can take a while, so we need to stop the main thread from interfering
synchronized (networkManagers) {
// Stop injecting channels
if (!closed) {
channel.eventLoop().submit(() -> injectChannelInternal(channel));
}
}
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
}
}
};
// This is executed before Minecraft's channel handler
beginInitProtocol = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(endInitProtocol);
}
};
serverChannelHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel channel = (Channel) msg;
// Prepare to initialize ths channel
channel.pipeline().addFirst(beginInitProtocol);
ctx.fireChannelRead(msg);
}
};
}
@SuppressWarnings("unchecked")
private void registerChannelHandler() {
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
Object serverConnection = getServerConnection.get(mcServer);
boolean looking = true;
// We need to synchronize against this list
networkManagers = (List<Object>) getNetworkMarkers.invoke(null, serverConnection);
createServerChannelHandler();
// Find the correct list, or implicitly throw an exception
for (int i = 0; looking; i++) {
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
for (Object item : list) {
if (!(item instanceof ChannelFuture))
break;
// Channel future that contains the server connection
Channel serverChannel = ((ChannelFuture) item).channel();
serverChannels.add(serverChannel);
serverChannel.pipeline().addFirst(serverChannelHandler);
looking = false;
}
}
}
private void unregisterChannelHandler() {
if (serverChannelHandler == null)
return;
for (Channel serverChannel : serverChannels) {
final ChannelPipeline pipeline = serverChannel.pipeline();
// Remove channel handler
serverChannel.eventLoop().execute(new Runnable() {
@Override
public void run() {
try {
pipeline.remove(serverChannelHandler);
} catch (NoSuchElementException e) {
// That's fine
}
}
});
}
}
private void registerPlayers(Plugin plugin) {
for (Player player : plugin.getServer().getOnlinePlayers()) {
injectPlayer(player);
}
}
/**
* Invoked when the server is starting to send a packet to a player.
* <p>
* Note that this is not executed on the main thread.
*
* @param receiver - the receiving player, NULL for early login/status packets.
* @param channel - the channel that received the packet. Never NULL.
* @param packet - the packet being sent.
* @return The packet to send instead, or NULL to cancel the transmission.
*/
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
return PacketEvents.getAPI().packetManager.write(receiver, channel, packet);
}
/**
* Invoked when the server has received a packet from a given player.
* <p>
* Use {@link Channel#remoteAddress()} to get the remote address of the client.
*
* @param sender - the player that sent the packet, NULL for early login/status packets.
* @param channel - channel that received the packet. Never NULL.
* @param packet - the packet being received.
* @return The packet to recieve instead, or NULL to cancel.
*/
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
return PacketEvents.getAPI().packetManager.read(sender, channel,packet);
}
/**
* Send a packet to a particular player.
* <p>
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param player - the destination player.
* @param packet - the packet to send.
*/
public void sendPacket(Player player, Object packet) {
sendPacket(getChannel(player), packet);
}
/**
* Send a packet to a particular client.
* <p>
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param channel - client identified by a channel.
* @param packet - the packet to send.
*/
public void sendPacket(Channel channel, Object packet) {
channel.pipeline().writeAndFlush(packet);
}
public void sendPacket(Object channel, Object packet) {
sendPacket((Channel) channel, packet);
}
/**
* Pretend that a given packet has been received from a player.
* <p>
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param player - the player that sent the packet.
* @param packet - the packet that will be received by the server.
*/
public void receivePacket(Player player, Object packet) {
receivePacket(getChannel(player), packet);
}
/**
* Pretend that a given packet has been received from a given client.
* <p>
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param channel - client identified by a channel.
* @param packet - the packet that will be received by the server.
*/
public void receivePacket(Channel channel, Object packet) {
channel.pipeline().context("encoder").fireChannelRead(packet);
}
/**
* Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID.
* <p>
* Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances.
*
* @return A unique channel handler name.
*/
protected String getHandlerName() {
return "PacketEvents-" + ID.incrementAndGet();
}
/**
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
* <p>
* This will automatically be called when a player has logged in.
*
* @param player - the player to inject.
*/
public void injectPlayer(Player player) {
injectChannelInternal(getChannel(player)).player = player;
}
public void injectPlayerAsync(Player player) {
Channel channel = getChannel(player);
injectChannelInternalAsync(channel).player = player;
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
*/
public void injectChannel(Channel channel) {
injectChannelInternal(channel);
}
public void injectChannelAsync(Channel channel) {
injectChannelInternalAsync(channel);
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
* @return The packet interceptor.
*/
private PacketInterceptor injectChannelInternal(Channel channel) {
try {
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new PacketInterceptor();
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
uninjectedChannels.remove(channel);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return (PacketInterceptor) channel.pipeline().get(handlerName);
}
}
private PacketInterceptor injectChannelInternalAsync(Channel channel) {
try {
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new PacketInterceptor();
final PacketInterceptor pi = interceptor;
NettyPacketManager.executorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
}
});
uninjectedChannels.remove(channel);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return (PacketInterceptor) channel.pipeline().get(handlerName);
}
}
/**
* Retrieve the Netty channel associated with a player. This is cached.
*
* @param player - the player.
* @return The Netty channel.
*/
public Channel getChannel(Player player) {
Channel channel = channelLookup.get(player.getName());
// Lookup channel again
if (channel == null) {
Object connection = getConnection.get(getPlayerHandle.invoke(player));
Object manager = getManager.get(connection);
channelLookup.put(player.getName(), channel = getChannel.get(manager));
}
return channel;
}
/**
* Uninject a specific player.
*
* @param player - the injected player.
*/
public void uninjectPlayer(Player player) {
uninjectChannel(getChannel(player));
}
public void uninjectPlayerAsync(Player player) {
Channel channel = getChannel(player);
uninjectChannelAsync(channel);
}
/**
* Uninject a specific channel.
* <p>
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
*
* @param channel - the injected channel.
*/
public void uninjectChannel(final Channel channel) {
// No need to guard against this if we're closing
if (!closed) {
uninjectedChannels.add(channel);
}
// See ChannelInjector in ProtocolLib, line 590
channel.pipeline().remove(handlerName);
}
public void uninjectChannelAsync(Channel channel) {
// No need to guard against this if we're closing
if (!closed) {
uninjectedChannels.add(channel);
}
// See ChannelInjector in ProtocolLib, line 590
NettyPacketManager.executorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().remove(handlerName);
}
});
}
/**
* Determine if the given player has been injected by TinyProtocol.
*
* @param player - the player.
* @return TRUE if it is, FALSE otherwise.
*/
public boolean hasInjected(Player player) {
return hasInjected(getChannel(player));
}
/**
* Determine if the given channel has been injected by TinyProtocol.
*
* @param channel - the channel.
* @return TRUE if it is, FALSE otherwise.
*/
public boolean hasInjected(Channel channel) {
return channel.pipeline().get(handlerName) != null;
}
/**
* Cease listening for packets. This is called automatically when your plugin is disabled.
*/
public final void close() {
if (!closed) {
closed = true;
// Remove our handlers
for (Player player : plugin.getServer().getOnlinePlayers()) {
uninjectPlayer(player);
}
// Clean up Bukkit
HandlerList.unregisterAll(listener);
unregisterChannelHandler();
}
}
/**
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
*
* @author Kristian
*/
private final class PacketInterceptor extends ChannelDuplexHandler {
// Updated by the login event
public volatile Player player;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// Intercept channel
final Channel channel = ctx.channel();
handleLoginStart(channel, msg);
try {
msg = onPacketInAsync(player, channel, msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
}
if (msg != null) {
super.channelRead(ctx, msg);
PacketEvents.getAPI().packetManager.postRead(player, msg);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
try {
msg = onPacketOutAsync(player, ctx.channel(), msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
}
if (msg != null) {
super.write(ctx, msg, promise);
PacketEvents.getAPI().packetManager.postWrite(player, msg);
}
}
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
GameProfile profile = getGameProfile.get(packet);
channelLookup.put(profile.getName(), channel);
}
}
}
}
@@ -1,558 +0,0 @@
/*
* This file is part of Hawk Anticheat.
* Copyright (C) 2018 Hawk Development Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.packetmanager.tinyprotocol;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.mojang.authlib.GameProfile;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetmanager.netty.NettyPacketManager;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.packetmanager.tinyprotocol.Reflection.MethodInvoker;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
/**
* Represents a very tiny alternative to ProtocolLib.
* <p>
* It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)!
*
* @author Kristian
*/
//BROKEN: NPEs when player joins while server is starting, and using PlayerJoinEvent instead will cause NPE for protocol version lookup.
//Protocol version number lookup method from DeprecatedLuke's version of TinyProtocol
public class TinyProtocol8 {
private static final AtomicInteger ID = new AtomicInteger();
// Used in order to lookup a channel
private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
private static final FieldAccessor<Object> getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
private static final FieldAccessor<Channel> getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
// Looking up ServerConnection
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
private static final MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
// Packets we have to intercept
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
private static final Class<?> PACKET_HANDSHAKING_IN_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol");
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
private static final FieldAccessor<Integer> protocolId = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, int.class, 0);
private static final FieldAccessor<Enum> protocolType = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, Enum.class, 0);
// Speedup channel/protocol lookup
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Listener listener;
// Channels that have already been removed
public Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
// List of network markers
private List<Object> networkManagers;
// Injected channel handlers
private List<Channel> serverChannels = Lists.newArrayList();
private ChannelInboundHandlerAdapter serverChannelHandler;
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
// Current handler name
private String handlerName;
protected volatile boolean closed;
protected Plugin plugin;
/**
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
* <p>
* You can construct multiple instances per plugin.
*
* @param plugin - the plugin.
*/
public TinyProtocol8(final Plugin plugin) {
this.plugin = plugin;
// Compute handler name
this.handlerName = getHandlerName();
try {
registerChannelHandler();
registerPlayers(plugin);
} catch (IllegalArgumentException ex) {
// Damn you, late bind
plugin.getLogger().info("Delaying server channel injection due to late bind.");
new BukkitRunnable() {
@Override
public void run() {
registerChannelHandler();
registerPlayers(plugin);
plugin.getLogger().info("Late bind injection successful.");
}
}.runTask(plugin);
}
}
private void createServerChannelHandler() {
// Handle connected channels
endInitProtocol = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
try {
// This can take a while, so we need to stop the main thread from interfering
synchronized (networkManagers) {
// Stop injecting channels
if (!closed) {
channel.eventLoop().submit(() -> injectChannelInternal(channel));
}
}
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
}
}
};
// This is executed before Minecraft's channel handler
beginInitProtocol = new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(endInitProtocol);
}
};
serverChannelHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel channel = (Channel) msg;
// Prepare to initialize ths channel
channel.pipeline().addFirst(beginInitProtocol);
ctx.fireChannelRead(msg);
}
};
}
/**
* Register bukkit events.
*/
@SuppressWarnings("unchecked")
private void registerChannelHandler() {
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
Object serverConnection = getServerConnection.get(mcServer);
boolean looking = true;
// We need to synchronize against this list
networkManagers = (List<Object>) getNetworkMarkers.invoke(null, serverConnection);
createServerChannelHandler();
// Find the correct list, or implicitly throw an exception
for (int i = 0; looking; i++) {
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
for (Object item : list) {
if (!(item instanceof ChannelFuture))
break;
// Channel future that contains the server connection
Channel serverChannel = ((ChannelFuture) item).channel();
serverChannels.add(serverChannel);
serverChannel.pipeline().addFirst(serverChannelHandler);
looking = false;
}
}
}
private void unregisterChannelHandler() {
if (serverChannelHandler == null)
return;
for (Channel serverChannel : serverChannels) {
final ChannelPipeline pipeline = serverChannel.pipeline();
// Remove channel handler
serverChannel.eventLoop().execute(new Runnable() {
@Override
public void run() {
try {
pipeline.remove(serverChannelHandler);
} catch (NoSuchElementException e) {
// That's fine
}
}
});
}
}
private void registerPlayers(Plugin plugin) {
for (Player player : plugin.getServer().getOnlinePlayers()) {
injectPlayer(player);
}
}
/**
* Invoked when the server is starting to send a packet to a player.
* <p>
* Note that this is not executed on the main thread.
*
* @param receiver - the receiving player, NULL for early login/status packets.
* @param channel - the channel that received the packet. Never NULL.
* @param packet - the packet being sent.
* @return The packet to send instead, or NULL to cancel the transmission.
*/
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
return PacketEvents.getAPI().packetManager.write(receiver, channel, packet);
}
/**
* Invoked when the server has received a packet from a given player.
* <p>
* Use {@link Channel#remoteAddress()} to get the remote address of the client.
*
* @param sender - the player that sent the packet, NULL for early login/status packets.
* @param channel - channel that received the packet. Never NULL.
* @param packet - the packet being received.
* @return The packet to recieve instead, or NULL to cancel.
*/
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
return PacketEvents.getAPI().packetManager.read(sender, channel, packet);
}
/**
* Send a packet to a particular player.
* <p>
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param player - the destination player.
* @param packet - the packet to send.
*/
public void sendPacket(Player player, Object packet) {
sendPacket(getChannel(player), packet);
}
/**
* Send a packet to a particular client.
* <p>
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param channel - client identified by a channel.
* @param packet - the packet to send.
*/
public void sendPacket(Channel channel, Object packet) {
channel.pipeline().writeAndFlush(packet);
}
public void sendPacket(Object channel, Object packet) {
sendPacket((Channel) channel, packet);
}
/**
* Pretend that a given packet has been received from a player.
* <p>
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param player - the player that sent the packet.
* @param packet - the packet that will be received by the server.
*/
public void receivePacket(Player player, Object packet) {
receivePacket(getChannel(player), packet);
}
/**
* Pretend that a given packet has been received from a given client.
* <p>
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
*
* @param channel - client identified by a channel.
* @param packet - the packet that will be received by the server.
*/
public void receivePacket(Channel channel, Object packet) {
channel.pipeline().context("encoder").fireChannelRead(packet);
}
/**
* Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID.
* <p>
* Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances.
*
* @return A unique channel handler name.
*/
protected String getHandlerName() {
return "PacketEvents-" + ID.incrementAndGet();
}
/**
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
* <p>
* This will automatically be called when a player has logged in.
*
* @param player - the player to inject.
*/
public void injectPlayer(Player player) {
injectChannelInternal(getChannel(player)).player = player;
}
public void injectPlayerAsync(Player player) {
Channel channel = getChannel(player);
injectChannelInternalAsync(channel).player = player;
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
*/
public void injectChannel(Channel channel) {
injectChannelInternal(channel);
}
public void injectChannelAsync(Channel channel) {
injectChannelInternalAsync(channel);
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
* @return The packet interceptor.
*/
private PacketInterceptor injectChannelInternal(Channel channel) {
try {
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new PacketInterceptor();
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
uninjectedChannels.remove(channel);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return (PacketInterceptor) channel.pipeline().get(handlerName);
}
}
private PacketInterceptor injectChannelInternalAsync(Channel channel) {
try {
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new PacketInterceptor();
final PacketInterceptor pi = interceptor;
NettyPacketManager.executorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().addBefore("packet_handler", handlerName, pi);
}
});
uninjectedChannels.remove(channel);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return (PacketInterceptor) channel.pipeline().get(handlerName);
}
}
/**
* Retrieve the Netty channel associated with a player. This is cached.
*
* @param player - the player.
* @return The Netty channel.
*/
public Channel getChannel(Player player) {
Channel channel = channelLookup.get(player.getName());
// Lookup channel again
if (channel == null) {
Object connection = getConnection.get(getPlayerHandle.invoke(player));
Object manager = getManager.get(connection);
channelLookup.put(player.getName(), channel = getChannel.get(manager));
}
return channel;
}
/**
* Uninject a specific player.
*
* @param player - the injected player.
*/
public void uninjectPlayer(Player player) {
uninjectChannel(getChannel(player));
}
public void uninjectPlayerAsync(Player player) {
Channel channel = getChannel(player);
uninjectChannelAsync(channel);
}
/**
* Uninject a specific channel.
* <p>
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
*
* @param channel - the injected channel.
*/
public void uninjectChannel(final Channel channel) {
// No need to guard against this if we're closing
if (!closed) {
uninjectedChannels.add(channel);
}
// See ChannelInjector in ProtocolLib, line 590
channel.pipeline().remove(handlerName);
}
public void uninjectChannelAsync(Channel channel) {
// No need to guard against this if we're closing
if (!closed) {
uninjectedChannels.add(channel);
}
// See ChannelInjector in ProtocolLib, line 590
NettyPacketManager.executorService.execute(new Runnable() {
@Override
public void run() {
channel.pipeline().remove(handlerName);
}
});
}
/**
* Determine if the given player has been injected by TinyProtocol.
*
* @param player - the player.
* @return TRUE if it is, FALSE otherwise.
*/
public boolean hasInjected(Player player) {
return hasInjected(getChannel(player));
}
/**
* Determine if the given channel has been injected by TinyProtocol.
*
* @param channel - the channel.
* @return TRUE if it is, FALSE otherwise.
*/
public boolean hasInjected(Channel channel) {
return channel.pipeline().get(handlerName) != null;
}
/**
* Cease listening for packets. This is called automatically when your plugin is disabled.
*/
public final void close() {
if (!closed) {
closed = true;
// Remove our handlers
for (Player player : plugin.getServer().getOnlinePlayers()) {
uninjectPlayer(player);
}
// Clean up Bukkit
HandlerList.unregisterAll(listener);
unregisterChannelHandler();
}
}
/**
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
*
* @author Kristian
*/
private final class PacketInterceptor extends ChannelDuplexHandler {
// Updated by the login event
public volatile Player player;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// Intercept channel
final Channel channel = ctx.channel();
handleLoginStart(channel, msg);
try {
msg = onPacketInAsync(player, channel, msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
}
if (msg != null) {
super.channelRead(ctx, msg);
PacketEvents.getAPI().packetManager.postRead(player, msg);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
try {
msg = onPacketOutAsync(player, ctx.channel(), msg);
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
}
if (msg != null) {
super.write(ctx, msg, promise);
PacketEvents.getAPI().packetManager.postWrite(player, msg);
}
}
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
GameProfile profile = getGameProfile.get(packet);
channelLookup.put(profile.getName(), channel);
}
}
}
}
@@ -24,257 +24,414 @@
package io.github.retrooper.packetevents.packettype;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import java.util.HashMap;
import java.util.Map;
/**
* Packet Type IDs.
* This is the Packet ID system, it is recommended to use this over packet comparisons by packet name.
* This is also faster than comparing packet names.
*
* @author retrooper
* @since 1.6.8
*/
public class PacketType {
/**
* If a Packet Type could not be resolved, it will be set to the current value of this constant.
* This value may change over the versions so it is important to use the variable and not hard code its value.
*/
public static final byte INVALID = -1;
/**
* Status Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Status">https://wiki.vg/Protocol#Status</a>
* @since 1.7
*/
public static class Status {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte PING = 0, PONG = 1;
/**
* Server-bound (client-sided) Status Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Serverbound_2">https://wiki.vg/Protocol#Serverbound_2</a>
* @since 1.8
*/
public static class Client {
public static final byte START = 0, PING = 1;
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static void init() {
packetIds.put(PacketTypeClasses.Status.PING, PING);
packetIds.put(PacketTypeClasses.Status.PONG, PONG);
/**
* Load the server-bound status Packet IDs.
*/
public static void init() {
packetIds.put(PacketTypeClasses.Status.Client.START, Client.START);
packetIds.put(PacketTypeClasses.Status.Client.PING, Client.PING);
}
}
/**
* Client-bound (server-sided) Status Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Clientbound_2">https://wiki.vg/Protocol#Clientbound_2</a>
* @since 1.8
*/
public static class Server {
public static final byte PONG = 0, SERVER_INFO = 1;
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
/**
* Load the client-bound Status Packet IDs.
*/
public static void init() {
packetIds.put(PacketTypeClasses.Status.Server.PONG, Server.PONG);
packetIds.put(PacketTypeClasses.Status.Server.SERVER_INFO, Server.SERVER_INFO);
}
}
}
/**
* Login Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Login">https://wiki.vg/Protocol#Login</a>
* @since 1.7
*/
public static class Login {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte HANDSHAKE = 0,
IN_CUSTOM_PAYLOAD = 1, OUT_CUSTOM_PAYLOAD = 2,IN_START = 3, IN_ENCRYPTION_BEGIN = 4,
DISCONNECT = 5, OUT_ENCRYPTION_BEGIN = 6, OUT_SUCCESS = 7;
/**
* Server-bound (client-sided) Login Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Serverbound_3">https://wiki.vg/Protocol#Serverbound_3</a>
* @since 1.8
*/
public static class Client {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte HANDSHAKE = 0, CUSTOM_PAYLOAD = 1, START = 2, ENCRYPTION_BEGIN = 3;
public static void init() {
packetIds.put(PacketTypeClasses.Login.HANDSHAKE, HANDSHAKE);
packetIds.put(PacketTypeClasses.Login.IN_CUSTOM_PAYLOAD, IN_CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Login.OUT_CUSTOM_PAYLOAD, OUT_CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Login.IN_START, IN_START);
packetIds.put(PacketTypeClasses.Login.IN_ENCRYPTION_BEGIN, IN_ENCRYPTION_BEGIN);
packetIds.put(PacketTypeClasses.Login.DISCONNECT, DISCONNECT);
packetIds.put(PacketTypeClasses.Login.OUT_ENCRYPTION_BEGIN, OUT_ENCRYPTION_BEGIN);
packetIds.put(PacketTypeClasses.Login.OUT_SUCCESS, OUT_SUCCESS);
}
}
public static class Client {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte TELEPORT_ACCEPT = 0,
TILE_NBT_QUERY = 1, DIFFICULTY_CHANGE = 2, CHAT = 3, CLIENT_COMMAND = 4,
SETTINGS = 5, TAB_COMPLETE = 6, TRANSACTION = 7, ENCHANT_ITEM = 8,
WINDOW_CLICK = 9, CLOSE_WINDOW = 10, CUSTOM_PAYLOAD = 11, B_EDIT = 12,
ENTITY_NBT_QUERY = 13, USE_ENTITY = 14, JIGSAW_GENERATE = 15, KEEP_ALIVE = 16,
DIFFICULTY_LOCK = 17, POSITION = 18, POSITION_LOOK = 19, LOOK = 20,
FLYING = 21, VEHICLE_MOVE = 22, BOAT_MOVE = 23, PICK_ITEM = 24,
AUTO_RECIPE = 25, ABILITIES = 26, BLOCK_DIG = 27, ENTITY_ACTION = 28,
STEER_VEHICLE = 29, RECIPE_DISPLAYED = 30, ITEM_NAME = 31, RESOURCE_PACK_STATUS = 32,
ADVANCEMENTS = 33, TR_SEL = 34, BEACON = 35, HELD_ITEM_SLOT = 36,
SET_COMMAND_BLOCK = 37, SET_COMMAND_MINECART = 38, SET_CREATIVE_SLOT = 39, SET_JIGSAW = 40,
STRUCT = 41, UPDATE_SIGN = 42, ARM_ANIMATION = 43, SPECTATE = 44,
USE_ITEM = 45, BLOCK_PLACE = 46;
public static void init() {
packetIds.put(PacketTypeClasses.Client.TELEPORT_ACCEPT, TELEPORT_ACCEPT);
packetIds.put(PacketTypeClasses.Client.TILE_NBT_QUERY, TILE_NBT_QUERY);
packetIds.put(PacketTypeClasses.Client.DIFFICULTY_CHANGE, DIFFICULTY_CHANGE);
packetIds.put(PacketTypeClasses.Client.CHAT, CHAT);
packetIds.put(PacketTypeClasses.Client.CLIENT_COMMAND, CLIENT_COMMAND);
packetIds.put(PacketTypeClasses.Client.SETTINGS, SETTINGS);
packetIds.put(PacketTypeClasses.Client.TAB_COMPLETE, TAB_COMPLETE);
packetIds.put(PacketTypeClasses.Client.TRANSACTION, TRANSACTION);
packetIds.put(PacketTypeClasses.Client.ENCHANT_ITEM, ENCHANT_ITEM);
packetIds.put(PacketTypeClasses.Client.WINDOW_CLICK, WINDOW_CLICK);
packetIds.put(PacketTypeClasses.Client.CLOSE_WINDOW, CLOSE_WINDOW);
packetIds.put(PacketTypeClasses.Client.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Client.B_EDIT, B_EDIT);
packetIds.put(PacketTypeClasses.Client.ENTITY_NBT_QUERY, ENTITY_NBT_QUERY);
packetIds.put(PacketTypeClasses.Client.USE_ENTITY, USE_ENTITY);
packetIds.put(PacketTypeClasses.Client.JIGSAW_GENERATE, JIGSAW_GENERATE);
packetIds.put(PacketTypeClasses.Client.KEEP_ALIVE, KEEP_ALIVE);
packetIds.put(PacketTypeClasses.Client.DIFFICULTY_LOCK, DIFFICULTY_LOCK);
packetIds.put(PacketTypeClasses.Client.POSITION, POSITION);
packetIds.put(PacketTypeClasses.Client.POSITION_LOOK, POSITION_LOOK);
packetIds.put(PacketTypeClasses.Client.LOOK, LOOK);
packetIds.put(PacketTypeClasses.Client.FLYING, FLYING);
packetIds.put(PacketTypeClasses.Client.VEHICLE_MOVE, VEHICLE_MOVE);
packetIds.put(PacketTypeClasses.Client.BOAT_MOVE, BOAT_MOVE);
packetIds.put(PacketTypeClasses.Client.PICK_ITEM, PICK_ITEM);
packetIds.put(PacketTypeClasses.Client.AUTO_RECIPE, AUTO_RECIPE);
packetIds.put(PacketTypeClasses.Client.ABILITIES, ABILITIES);
packetIds.put(PacketTypeClasses.Client.BLOCK_DIG, BLOCK_DIG);
packetIds.put(PacketTypeClasses.Client.ENTITY_ACTION, ENTITY_ACTION);
packetIds.put(PacketTypeClasses.Client.STEER_VEHICLE, STEER_VEHICLE);
packetIds.put(PacketTypeClasses.Client.RECIPE_DISPLAYED, RECIPE_DISPLAYED);
packetIds.put(PacketTypeClasses.Client.ITEM_NAME, ITEM_NAME);
packetIds.put(PacketTypeClasses.Client.RESOURCE_PACK_STATUS, RESOURCE_PACK_STATUS);
packetIds.put(PacketTypeClasses.Client.ADVANCEMENTS, ADVANCEMENTS);
packetIds.put(PacketTypeClasses.Client.TR_SEL, TR_SEL);
packetIds.put(PacketTypeClasses.Client.BEACON, BEACON);
packetIds.put(PacketTypeClasses.Client.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
packetIds.put(PacketTypeClasses.Client.SET_COMMAND_BLOCK, SET_COMMAND_BLOCK);
packetIds.put(PacketTypeClasses.Client.SET_COMMAND_MINECART, SET_COMMAND_MINECART);
packetIds.put(PacketTypeClasses.Client.SET_CREATIVE_SLOT, SET_CREATIVE_SLOT);
packetIds.put(PacketTypeClasses.Client.SET_JIGSAW, SET_JIGSAW);
packetIds.put(PacketTypeClasses.Client.STRUCT, STRUCT);
packetIds.put(PacketTypeClasses.Client.UPDATE_SIGN, UPDATE_SIGN);
packetIds.put(PacketTypeClasses.Client.ARM_ANIMATION, ARM_ANIMATION);
packetIds.put(PacketTypeClasses.Client.SPECTATE, SPECTATE);
packetIds.put(PacketTypeClasses.Client.USE_ITEM, USE_ITEM);
packetIds.put(PacketTypeClasses.Client.BLOCK_PLACE, BLOCK_PLACE);
}
public static class Util {
/**
* Is the packet an instance of the PacketPlayInFlying packet?
*
* @param packetID
* @return packetID == FLYING or POSITION or POSITION_LOOK or LOOK
* Load the server-bound Login Packet IDs.
*/
public static boolean isInstanceOfFlying(final byte packetID) {
return packetID == FLYING
|| packetID == POSITION
|| packetID == POSITION_LOOK
|| packetID == LOOK;
public static void init() {
packetIds.put(PacketTypeClasses.Login.Client.HANDSHAKE, Client.HANDSHAKE);
packetIds.put(PacketTypeClasses.Login.Client.CUSTOM_PAYLOAD, Client.CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Login.Client.START, Client.START);
packetIds.put(PacketTypeClasses.Login.Client.ENCRYPTION_BEGIN, Client.ENCRYPTION_BEGIN);
}
}
/**
* Client-bound (server-sided) Login Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Clientbound_3">https://wiki.vg/Protocol#Clientbound_3</a>
* @since 1.8
*/
public static class Server {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte CUSTOM_PAYLOAD = 0, DISCONNECT = 1, ENCRYPTION_BEGIN = 2, SUCCESS = 3, SET_COMPRESSION = 4;
/**
* Load the client-bound Login Packet IDs.
*/
public static void init() {
packetIds.put(PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD, Server.CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Login.Server.DISCONNECT, Server.DISCONNECT);
packetIds.put(PacketTypeClasses.Login.Server.ENCRYPTION_BEGIN, Server.ENCRYPTION_BEGIN);
packetIds.put(PacketTypeClasses.Login.Server.SUCCESS, Server.SUCCESS);
packetIds.put(PacketTypeClasses.Login.Server.SET_COMPRESSION, Server.SET_COMPRESSION);
}
}
}
public static class Server {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte SPAWN_ENTITY = 0, SPAWN_ENTITY_EXPERIENCE_ORB = 1, SPAWN_ENTITY_WEATHER = 2, SPAWN_ENTITY_LIVING = 3,
SPAWN_ENTITY_PAINTING = 4, SPAWN_ENTITY_SPAWN = 5, ANIMATION = 6, STATISTIC = 7,
BLOCK_BREAK = 8, BLOCK_BREAK_ANIMATION = 9, TILE_ENTITY_DATA = 10, BLOCK_ACTION = 11,
BLOCK_CHANGE = 12, BOSS = 13, SERVER_DIFFICULTY = 14, CHAT = 15, MULTI_BLOCK_CHANGE = 16,
TAB_COMPLETE = 17, COMMANDS = 18, TRANSACTION = 19, CLOSE_WINDOW = 20,
WINDOW_ITEMS = 21, WINDOW_DATA = 22, SET_SLOT = 23, SET_COOLDOWN = 24,
CUSTOM_PAYLOAD = 25, CUSTOM_SOUND_EFFECT = 26, KICK_DISCONNECT = 27, ENTITY_STATUS = 28,
EXPLOSION = 29, UNLOAD_CHUNK = 30, GAME_STATE_CHANGE = 31, OPEN_WINDOW_HORSE = 32,
KEEP_ALIVE = 33, MAP_CHUNK = 34, WORLD_EVENT = 35, WORLD_PARTICLES = 36,
LIGHT_UPDATE = 37, LOGIN = 38, MAP = 39, OPEN_WINDOW_MERCHANT = 40,
REL_ENTITY_MOVE = 41, REL_ENTITY_MOVE_LOOK = 42, ENTITY_LOOK = 43, ENTITY = 44,
VEHICLE_MOVE = 45, OPEN_BOOK = 46, OPEN_WINDOW = 47, OPEN_SIGN_EDITOR = 48,
AUTO_RECIPE = 49, ABILITIES = 50, COMBAT_EVENT = 51, PLAYER_INFO = 52,
LOOK_AT = 53, POSITION = 54, RECIPES = 55, ENTITY_DESTROY = 56,
REMOVE_ENTITY_EFFECT = 57, RESOURCE_PACK_SEND = 58, RESPAWN = 59, ENTITY_HEAD_ROTATION = 60,
SELECT_ADVANCEMENT_TAB = 61, WORLD_BORDER = 62, CAMERA = 63, HELD_ITEM_SLOT = 64,
VIEW_CENTRE = 65, VIEW_DISTANCE = 66, SCOREBOARD_DISPLAY_OBJECTIVE = 67, ENTITY_METADATA = 68,
ATTACH_ENTITY = 69, ENTITY_VELOCITY = 70, ENTITY_EQUIPMENT = 71, EXPERIENCE = 72,
UPDATE_HEALTH = 73, SCOREBOARD_OBJECTIVE = 74, MOUNT = 75, SCOREBOARD_TEAM = 76,
SCOREBOARD_SCORE = 77, SPAWN_POSITION = 78, UPDATE_TIME = 79, TITLE = 80,
ENTITY_SOUND = 81, NAMED_SOUND_EFFECT = 82, STOP_SOUND = 83, PLAYER_LIST_HEADER_FOOTER = 84,
NBT_QUERY = 85, COLLECT = 86, ENTITY_TELEPORT = 87, ADVANCEMENTS = 88, UPDATE_ATTRIBUTES = 89,
ENTITY_EFFECT = 90, RECIPE_UPDATE = 91, TAGS = 92, MAP_CHUNK_BULK = 93;
/**
* Play Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Play">https://wiki.vg/Protocol#Play</a>
* @since 1.8
*/
public static class Play {
/**
* Server-bound (client-sided) Play Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Serverbound_4">https://wiki.vg/Protocol#Serverbound_4</a>
* @since 1.8
*/
public static class Client {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte TELEPORT_ACCEPT = 0,
TILE_NBT_QUERY = 1, DIFFICULTY_CHANGE = 2, CHAT = 3, CLIENT_COMMAND = 4,
SETTINGS = 5, TAB_COMPLETE = 6, TRANSACTION = 7, ENCHANT_ITEM = 8,
WINDOW_CLICK = 9, CLOSE_WINDOW = 10, CUSTOM_PAYLOAD = 11, B_EDIT = 12,
ENTITY_NBT_QUERY = 13, USE_ENTITY = 14, JIGSAW_GENERATE = 15, KEEP_ALIVE = 16,
DIFFICULTY_LOCK = 17, POSITION = 18, POSITION_LOOK = 19, LOOK = 20,
FLYING = 21, VEHICLE_MOVE = 22, BOAT_MOVE = 23, PICK_ITEM = 24,
AUTO_RECIPE = 25, ABILITIES = 26, BLOCK_DIG = 27, ENTITY_ACTION = 28,
STEER_VEHICLE = 29, RECIPE_DISPLAYED = 30, ITEM_NAME = 31, RESOURCE_PACK_STATUS = 32,
ADVANCEMENTS = 33, TR_SEL = 34, BEACON = 35, HELD_ITEM_SLOT = 36,
SET_COMMAND_BLOCK = 37, SET_COMMAND_MINECART = 38, SET_CREATIVE_SLOT = 39, SET_JIGSAW = 40,
STRUCT = 41, UPDATE_SIGN = 42, ARM_ANIMATION = 43, SPECTATE = 44,
USE_ITEM = 45, BLOCK_PLACE = 46;
public static void init() {
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_EXPERIENCE_ORB);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_WEATHER);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_LIVING, SPAWN_ENTITY_LIVING);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_PAINTING);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_SPAWN, SPAWN_ENTITY_SPAWN);
packetIds.put(PacketTypeClasses.Server.ANIMATION, ANIMATION);
packetIds.put(PacketTypeClasses.Server.STATISTIC, STATISTIC);
packetIds.put(PacketTypeClasses.Server.BLOCK_BREAK, BLOCK_BREAK);
packetIds.put(PacketTypeClasses.Server.BLOCK_BREAK_ANIMATION, BLOCK_BREAK_ANIMATION);
packetIds.put(PacketTypeClasses.Server.TILE_ENTITY_DATA, TILE_ENTITY_DATA);
packetIds.put(PacketTypeClasses.Server.BLOCK_ACTION, BLOCK_ACTION);
packetIds.put(PacketTypeClasses.Server.BLOCK_CHANGE, BLOCK_CHANGE);
packetIds.put(PacketTypeClasses.Server.BOSS, BOSS);
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Server.SERVER_DIFFICULTY, SERVER_DIFFICULTY);
packetIds.put(PacketTypeClasses.Server.CHAT, CHAT);
packetIds.put(PacketTypeClasses.Server.MULTI_BLOCK_CHANGE, MULTI_BLOCK_CHANGE);
packetIds.put(PacketTypeClasses.Server.TAB_COMPLETE, TAB_COMPLETE);
packetIds.put(PacketTypeClasses.Server.COMMANDS, COMMANDS);
packetIds.put(PacketTypeClasses.Server.TRANSACTION, TRANSACTION);
packetIds.put(PacketTypeClasses.Server.CLOSE_WINDOW, CLOSE_WINDOW);
packetIds.put(PacketTypeClasses.Server.WINDOW_ITEMS, WINDOW_ITEMS);
packetIds.put(PacketTypeClasses.Server.WINDOW_DATA, WINDOW_DATA);
packetIds.put(PacketTypeClasses.Server.SET_SLOT, SET_SLOT);
packetIds.put(PacketTypeClasses.Server.SET_COOLDOWN, SET_COOLDOWN);
packetIds.put(PacketTypeClasses.Server.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Server.CUSTOM_SOUND_EFFECT, CUSTOM_SOUND_EFFECT);
packetIds.put(PacketTypeClasses.Server.KICK_DISCONNECT, KICK_DISCONNECT);
packetIds.put(PacketTypeClasses.Server.ENTITY_STATUS, ENTITY_STATUS);
packetIds.put(PacketTypeClasses.Server.EXPLOSION, EXPLOSION);
packetIds.put(PacketTypeClasses.Server.UNLOAD_CHUNK, UNLOAD_CHUNK);
packetIds.put(PacketTypeClasses.Server.GAME_STATE_CHANGE, GAME_STATE_CHANGE);
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW_HORSE, OPEN_WINDOW_HORSE);
packetIds.put(PacketTypeClasses.Server.KEEP_ALIVE, KEEP_ALIVE);
packetIds.put(PacketTypeClasses.Server.MAP_CHUNK, MAP_CHUNK);
packetIds.put(PacketTypeClasses.Server.WORLD_EVENT, WORLD_EVENT);
packetIds.put(PacketTypeClasses.Server.WORLD_EVENT, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Server.WORLD_PARTICLES, WORLD_PARTICLES);
packetIds.put(PacketTypeClasses.Server.LIGHT_UPDATE, LIGHT_UPDATE);
packetIds.put(PacketTypeClasses.Server.LOGIN, LOGIN);
packetIds.put(PacketTypeClasses.Server.MAP, MAP);
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW_MERCHANT, OPEN_WINDOW_MERCHANT);
packetIds.put(PacketTypeClasses.Server.REL_ENTITY_MOVE, REL_ENTITY_MOVE);
packetIds.put(PacketTypeClasses.Server.REL_ENTITY_MOVE_LOOK, REL_ENTITY_MOVE_LOOK);
packetIds.put(PacketTypeClasses.Server.ENTITY_LOOK, ENTITY_LOOK);
packetIds.put(PacketTypeClasses.Server.ENTITY, ENTITY);
packetIds.put(PacketTypeClasses.Server.VEHICLE_MOVE, VEHICLE_MOVE);
packetIds.put(PacketTypeClasses.Server.OPEN_BOOK, OPEN_BOOK);
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW, OPEN_WINDOW);
packetIds.put(PacketTypeClasses.Server.OPEN_SIGN_EDITOR, OPEN_SIGN_EDITOR);
packetIds.put(PacketTypeClasses.Server.AUTO_RECIPE, AUTO_RECIPE);
packetIds.put(PacketTypeClasses.Server.ABILITIES, ABILITIES);
packetIds.put(PacketTypeClasses.Server.COMBAT_EVENT, COMBAT_EVENT);
packetIds.put(PacketTypeClasses.Server.PLAYER_INFO, PLAYER_INFO);
packetIds.put(PacketTypeClasses.Server.LOOK_AT, LOOK_AT);
packetIds.put(PacketTypeClasses.Server.POSITION, POSITION);
packetIds.put(PacketTypeClasses.Server.RECIPES, RECIPES);
packetIds.put(PacketTypeClasses.Server.ENTITY_DESTROY, ENTITY_DESTROY);
packetIds.put(PacketTypeClasses.Server.REMOVE_ENTITY_EFFECT, REMOVE_ENTITY_EFFECT);
packetIds.put(PacketTypeClasses.Server.RESOURCE_PACK_SEND, RESOURCE_PACK_SEND);
packetIds.put(PacketTypeClasses.Server.RESPAWN, RESPAWN);
packetIds.put(PacketTypeClasses.Server.ENTITY_HEAD_ROTATION, ENTITY_HEAD_ROTATION);
packetIds.put(PacketTypeClasses.Server.SELECT_ADVANCEMENT_TAB, SELECT_ADVANCEMENT_TAB);
packetIds.put(PacketTypeClasses.Server.WORLD_BORDER, WORLD_BORDER);
packetIds.put(PacketTypeClasses.Server.CAMERA, CAMERA);
packetIds.put(PacketTypeClasses.Server.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
packetIds.put(PacketTypeClasses.Server.VIEW_CENTRE, VIEW_CENTRE);
packetIds.put(PacketTypeClasses.Server.VIEW_DISTANCE, VIEW_DISTANCE);
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_DISPLAY_OBJECTIVE, SCOREBOARD_DISPLAY_OBJECTIVE);
packetIds.put(PacketTypeClasses.Server.ENTITY_METADATA, ENTITY_METADATA);
packetIds.put(PacketTypeClasses.Server.ATTACH_ENTITY, ATTACH_ENTITY);
packetIds.put(PacketTypeClasses.Server.ENTITY_VELOCITY, ENTITY_VELOCITY);
packetIds.put(PacketTypeClasses.Server.ENTITY_EQUIPMENT, ENTITY_EQUIPMENT);
packetIds.put(PacketTypeClasses.Server.EXPERIENCE, EXPERIENCE);
packetIds.put(PacketTypeClasses.Server.UPDATE_HEALTH, UPDATE_HEALTH);
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_OBJECTIVE, SCOREBOARD_OBJECTIVE);
packetIds.put(PacketTypeClasses.Server.MOUNT, MOUNT);
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_TEAM, SCOREBOARD_TEAM);
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_SCORE, SCOREBOARD_SCORE);
packetIds.put(PacketTypeClasses.Server.SPAWN_POSITION, SPAWN_POSITION);
packetIds.put(PacketTypeClasses.Server.UPDATE_TIME, UPDATE_TIME);
packetIds.put(PacketTypeClasses.Server.TITLE, TITLE);
packetIds.put(PacketTypeClasses.Server.ENTITY_SOUND, ENTITY_SOUND);
packetIds.put(PacketTypeClasses.Server.NAMED_SOUND_EFFECT, NAMED_SOUND_EFFECT);
packetIds.put(PacketTypeClasses.Server.STOP_SOUND, STOP_SOUND);
packetIds.put(PacketTypeClasses.Server.PLAYER_LIST_HEADER_FOOTER, PLAYER_LIST_HEADER_FOOTER);
packetIds.put(PacketTypeClasses.Server.NBT_QUERY, NBT_QUERY);
packetIds.put(PacketTypeClasses.Server.COLLECT, COLLECT);
packetIds.put(PacketTypeClasses.Server.ENTITY_TELEPORT, ENTITY_TELEPORT);
packetIds.put(PacketTypeClasses.Server.ADVANCEMENTS, ADVANCEMENTS);
packetIds.put(PacketTypeClasses.Server.UPDATE_ATTRIBUTES, UPDATE_ATTRIBUTES);
packetIds.put(PacketTypeClasses.Server.ENTITY_EFFECT, ENTITY_EFFECT);
packetIds.put(PacketTypeClasses.Server.RECIPE_UPDATE, RECIPE_UPDATE);
packetIds.put(PacketTypeClasses.Server.TAGS, TAGS);
packetIds.put(PacketTypeClasses.Server.MAP_CHUNK_BULK, MAP_CHUNK_BULK);
/**
* Load the server-bound Play Packet IDs.
*/
public static void init() {
packetIds.put(PacketTypeClasses.Play.Client.TELEPORT_ACCEPT, TELEPORT_ACCEPT);
packetIds.put(PacketTypeClasses.Play.Client.TILE_NBT_QUERY, TILE_NBT_QUERY);
packetIds.put(PacketTypeClasses.Play.Client.DIFFICULTY_CHANGE, DIFFICULTY_CHANGE);
packetIds.put(PacketTypeClasses.Play.Client.CHAT, CHAT);
packetIds.put(PacketTypeClasses.Play.Client.CLIENT_COMMAND, CLIENT_COMMAND);
packetIds.put(PacketTypeClasses.Play.Client.SETTINGS, SETTINGS);
packetIds.put(PacketTypeClasses.Play.Client.TAB_COMPLETE, TAB_COMPLETE);
packetIds.put(PacketTypeClasses.Play.Client.TRANSACTION, TRANSACTION);
packetIds.put(PacketTypeClasses.Play.Client.ENCHANT_ITEM, ENCHANT_ITEM);
packetIds.put(PacketTypeClasses.Play.Client.WINDOW_CLICK, WINDOW_CLICK);
packetIds.put(PacketTypeClasses.Play.Client.CLOSE_WINDOW, CLOSE_WINDOW);
packetIds.put(PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Play.Client.B_EDIT, B_EDIT);
packetIds.put(PacketTypeClasses.Play.Client.ENTITY_NBT_QUERY, ENTITY_NBT_QUERY);
packetIds.put(PacketTypeClasses.Play.Client.USE_ENTITY, USE_ENTITY);
packetIds.put(PacketTypeClasses.Play.Client.JIGSAW_GENERATE, JIGSAW_GENERATE);
packetIds.put(PacketTypeClasses.Play.Client.KEEP_ALIVE, KEEP_ALIVE);
packetIds.put(PacketTypeClasses.Play.Client.DIFFICULTY_LOCK, DIFFICULTY_LOCK);
packetIds.put(PacketTypeClasses.Play.Client.POSITION, POSITION);
packetIds.put(PacketTypeClasses.Play.Client.POSITION_LOOK, POSITION_LOOK);
packetIds.put(PacketTypeClasses.Play.Client.LOOK, LOOK);
packetIds.put(PacketTypeClasses.Play.Client.FLYING, FLYING);
packetIds.put(PacketTypeClasses.Play.Client.VEHICLE_MOVE, VEHICLE_MOVE);
packetIds.put(PacketTypeClasses.Play.Client.BOAT_MOVE, BOAT_MOVE);
packetIds.put(PacketTypeClasses.Play.Client.PICK_ITEM, PICK_ITEM);
packetIds.put(PacketTypeClasses.Play.Client.AUTO_RECIPE, AUTO_RECIPE);
packetIds.put(PacketTypeClasses.Play.Client.ABILITIES, ABILITIES);
packetIds.put(PacketTypeClasses.Play.Client.BLOCK_DIG, BLOCK_DIG);
packetIds.put(PacketTypeClasses.Play.Client.ENTITY_ACTION, ENTITY_ACTION);
packetIds.put(PacketTypeClasses.Play.Client.STEER_VEHICLE, STEER_VEHICLE);
packetIds.put(PacketTypeClasses.Play.Client.RECIPE_DISPLAYED, RECIPE_DISPLAYED);
packetIds.put(PacketTypeClasses.Play.Client.ITEM_NAME, ITEM_NAME);
packetIds.put(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, RESOURCE_PACK_STATUS);
packetIds.put(PacketTypeClasses.Play.Client.ADVANCEMENTS, ADVANCEMENTS);
packetIds.put(PacketTypeClasses.Play.Client.TR_SEL, TR_SEL);
packetIds.put(PacketTypeClasses.Play.Client.BEACON, BEACON);
packetIds.put(PacketTypeClasses.Play.Client.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
packetIds.put(PacketTypeClasses.Play.Client.SET_COMMAND_BLOCK, SET_COMMAND_BLOCK);
packetIds.put(PacketTypeClasses.Play.Client.SET_COMMAND_MINECART, SET_COMMAND_MINECART);
packetIds.put(PacketTypeClasses.Play.Client.SET_CREATIVE_SLOT, SET_CREATIVE_SLOT);
packetIds.put(PacketTypeClasses.Play.Client.SET_JIGSAW, SET_JIGSAW);
packetIds.put(PacketTypeClasses.Play.Client.STRUCT, STRUCT);
packetIds.put(PacketTypeClasses.Play.Client.UPDATE_SIGN, UPDATE_SIGN);
packetIds.put(PacketTypeClasses.Play.Client.ARM_ANIMATION, ARM_ANIMATION);
packetIds.put(PacketTypeClasses.Play.Client.SPECTATE, SPECTATE);
packetIds.put(PacketTypeClasses.Play.Client.USE_ITEM, USE_ITEM);
packetIds.put(PacketTypeClasses.Play.Client.BLOCK_PLACE, BLOCK_PLACE);
}
/**
* Server-bound Play Packet Type utility.
* Save a few lines of code by using this.
*
* @author retrooper
* @since 1.8
*/
public static class Util {
/**
* Is the play packet a PacketPlayInFlying, PacketPlayInPosition, PacketPlayInPositionLook
* or a PacketPlayInLook packet?
*
* @param packetID Play Packet ID.
* @return Is the Packet ID an instance of the PacketPlayInFlying packet?
*/
public static boolean isInstanceOfFlying(final byte packetID) {
return packetID == FLYING
|| packetID == POSITION
|| packetID == POSITION_LOOK
|| packetID == LOOK;
}
/**
* Is this the packet where the client places a block?
* On 1.7.10 - 1.8.8 the client sends a PacketPlayInBlockPlace packet when actually placing the block.
* On 1.9 - now the client sends a PacketPlayInUseItem packet when placing the block and the
* PacketPlayInBlockPlace has a different use.
* This method is a nice utility supporting all these versions letting you know
* if the client played a block.
* The {@link io.github.retrooper.packetevents.packetwrappers.play.in.blockplace.WrappedPacketInBlockPlace} wrapper
* only works on an actual block place.
* Use this method before using the wrapper to support all minecraft versions.
*
* @param packetID Play Packet ID.
* @return Has the client placed a block?
*/
public static boolean isBlockPlace(final byte packetID) {
final ServerVersion version = PacketEvents.get().getServerUtils().getVersion();
return version.isHigherThan(ServerVersion.v_1_8_8) ?
packetID == Client.USE_ITEM
: packetID == Client.BLOCK_PLACE;
}
}
}
public static class Util {
/**
* Client-bound (server-sided) Play Packet IDs.
*
* @author retrooper
* @see <a href="https://wiki.vg/Protocol#Clientbound_4">https://wiki.vg/Protocol#Clientbound_4</a>
* @since 1.8
*/
public static class Server {
public static final Map<Class<?>, Byte> packetIds = new HashMap<>();
public static final byte SPAWN_ENTITY = 0, SPAWN_ENTITY_EXPERIENCE_ORB = 1, SPAWN_ENTITY_WEATHER = 2, SPAWN_ENTITY_LIVING = 3,
SPAWN_ENTITY_PAINTING = 4, SPAWN_ENTITY_SPAWN = 5, ANIMATION = 6, STATISTIC = 7,
BLOCK_BREAK = 8, BLOCK_BREAK_ANIMATION = 9, TILE_ENTITY_DATA = 10, BLOCK_ACTION = 11,
BLOCK_CHANGE = 12, BOSS = 13, SERVER_DIFFICULTY = 14, CHAT = 15, MULTI_BLOCK_CHANGE = 16,
TAB_COMPLETE = 17, COMMANDS = 18, TRANSACTION = 19, CLOSE_WINDOW = 20,
WINDOW_ITEMS = 21, WINDOW_DATA = 22, SET_SLOT = 23, SET_COOLDOWN = 24,
CUSTOM_PAYLOAD = 25, CUSTOM_SOUND_EFFECT = 26, KICK_DISCONNECT = 27, ENTITY_STATUS = 28,
EXPLOSION = 29, UNLOAD_CHUNK = 30, GAME_STATE_CHANGE = 31, OPEN_WINDOW_HORSE = 32,
KEEP_ALIVE = 33, MAP_CHUNK = 34, WORLD_EVENT = 35, WORLD_PARTICLES = 36,
LIGHT_UPDATE = 37, LOGIN = 38, MAP = 39, OPEN_WINDOW_MERCHANT = 40,
REL_ENTITY_MOVE = 41, REL_ENTITY_MOVE_LOOK = 42, ENTITY_LOOK = 43, ENTITY = 44,
VEHICLE_MOVE = 45, OPEN_BOOK = 46, OPEN_WINDOW = 47, OPEN_SIGN_EDITOR = 48,
AUTO_RECIPE = 49, ABILITIES = 50, COMBAT_EVENT = 51, PLAYER_INFO = 52,
LOOK_AT = 53, POSITION = 54, RECIPES = 55, ENTITY_DESTROY = 56,
REMOVE_ENTITY_EFFECT = 57, RESOURCE_PACK_SEND = 58, RESPAWN = 59, ENTITY_HEAD_ROTATION = 60,
SELECT_ADVANCEMENT_TAB = 61, WORLD_BORDER = 62, CAMERA = 63, HELD_ITEM_SLOT = 64,
VIEW_CENTRE = 65, VIEW_DISTANCE = 66, SCOREBOARD_DISPLAY_OBJECTIVE = 67, ENTITY_METADATA = 68,
ATTACH_ENTITY = 69, ENTITY_VELOCITY = 70, ENTITY_EQUIPMENT = 71, EXPERIENCE = 72,
UPDATE_HEALTH = 73, SCOREBOARD_OBJECTIVE = 74, MOUNT = 75, SCOREBOARD_TEAM = 76,
SCOREBOARD_SCORE = 77, SPAWN_POSITION = 78, UPDATE_TIME = 79, TITLE = 80,
ENTITY_SOUND = 81, NAMED_SOUND_EFFECT = 82, STOP_SOUND = 83, PLAYER_LIST_HEADER_FOOTER = 84,
NBT_QUERY = 85, COLLECT = 86, ENTITY_TELEPORT = 87, ADVANCEMENTS = 88, UPDATE_ATTRIBUTES = 89,
ENTITY_EFFECT = 90, RECIPE_UPDATE = 91, TAGS = 92, MAP_CHUNK_BULK = 93, NAMED_ENTITY_SPAWN = 94;
/**
* Is the packet an instance of the PacketPlayOutEntity packet?
*
* @param packetID
* @return packetID == ENTITY or REL_ENTITY_MOVE or REL_ENTITY_MOVE_LOOK or ENTITY_LOOK
* Load the client-bound Play Packet IDs.
*/
public static boolean isInstanceOfEntity(final byte packetID) {
return packetID == ENTITY || packetID == REL_ENTITY_MOVE ||
packetID == REL_ENTITY_MOVE_LOOK || packetID == ENTITY_LOOK;
public static void init() {
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_EXPERIENCE_ORB);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_WEATHER);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_LIVING, SPAWN_ENTITY_LIVING);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_PAINTING);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY_SPAWN, SPAWN_ENTITY_SPAWN);
packetIds.put(PacketTypeClasses.Play.Server.ANIMATION, ANIMATION);
packetIds.put(PacketTypeClasses.Play.Server.STATISTIC, STATISTIC);
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_BREAK, BLOCK_BREAK);
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_BREAK_ANIMATION, BLOCK_BREAK_ANIMATION);
packetIds.put(PacketTypeClasses.Play.Server.TILE_ENTITY_DATA, TILE_ENTITY_DATA);
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_ACTION, BLOCK_ACTION);
packetIds.put(PacketTypeClasses.Play.Server.BLOCK_CHANGE, BLOCK_CHANGE);
packetIds.put(PacketTypeClasses.Play.Server.BOSS, BOSS);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_ENTITY, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Play.Server.SERVER_DIFFICULTY, SERVER_DIFFICULTY);
packetIds.put(PacketTypeClasses.Play.Server.CHAT, CHAT);
packetIds.put(PacketTypeClasses.Play.Server.MULTI_BLOCK_CHANGE, MULTI_BLOCK_CHANGE);
packetIds.put(PacketTypeClasses.Play.Server.TAB_COMPLETE, TAB_COMPLETE);
packetIds.put(PacketTypeClasses.Play.Server.COMMANDS, COMMANDS);
packetIds.put(PacketTypeClasses.Play.Server.TRANSACTION, TRANSACTION);
packetIds.put(PacketTypeClasses.Play.Server.CLOSE_WINDOW, CLOSE_WINDOW);
packetIds.put(PacketTypeClasses.Play.Server.WINDOW_ITEMS, WINDOW_ITEMS);
packetIds.put(PacketTypeClasses.Play.Server.WINDOW_DATA, WINDOW_DATA);
packetIds.put(PacketTypeClasses.Play.Server.SET_SLOT, SET_SLOT);
packetIds.put(PacketTypeClasses.Play.Server.SET_COOLDOWN, SET_COOLDOWN);
packetIds.put(PacketTypeClasses.Play.Server.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
packetIds.put(PacketTypeClasses.Play.Server.CUSTOM_SOUND_EFFECT, CUSTOM_SOUND_EFFECT);
packetIds.put(PacketTypeClasses.Play.Server.KICK_DISCONNECT, KICK_DISCONNECT);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_STATUS, ENTITY_STATUS);
packetIds.put(PacketTypeClasses.Play.Server.EXPLOSION, EXPLOSION);
packetIds.put(PacketTypeClasses.Play.Server.UNLOAD_CHUNK, UNLOAD_CHUNK);
packetIds.put(PacketTypeClasses.Play.Server.GAME_STATE_CHANGE, GAME_STATE_CHANGE);
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW_HORSE, OPEN_WINDOW_HORSE);
packetIds.put(PacketTypeClasses.Play.Server.KEEP_ALIVE, KEEP_ALIVE);
packetIds.put(PacketTypeClasses.Play.Server.MAP_CHUNK, MAP_CHUNK);
packetIds.put(PacketTypeClasses.Play.Server.WORLD_EVENT, WORLD_EVENT);
packetIds.put(PacketTypeClasses.Play.Server.WORLD_EVENT, SPAWN_ENTITY);
packetIds.put(PacketTypeClasses.Play.Server.WORLD_PARTICLES, WORLD_PARTICLES);
packetIds.put(PacketTypeClasses.Play.Server.LIGHT_UPDATE, LIGHT_UPDATE);
packetIds.put(PacketTypeClasses.Play.Server.LOGIN, LOGIN);
packetIds.put(PacketTypeClasses.Play.Server.MAP, MAP);
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW_MERCHANT, OPEN_WINDOW_MERCHANT);
packetIds.put(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE, REL_ENTITY_MOVE);
packetIds.put(PacketTypeClasses.Play.Server.REL_ENTITY_MOVE_LOOK, REL_ENTITY_MOVE_LOOK);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_LOOK, ENTITY_LOOK);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY, ENTITY);
packetIds.put(PacketTypeClasses.Play.Server.VEHICLE_MOVE, VEHICLE_MOVE);
packetIds.put(PacketTypeClasses.Play.Server.OPEN_BOOK, OPEN_BOOK);
packetIds.put(PacketTypeClasses.Play.Server.OPEN_WINDOW, OPEN_WINDOW);
packetIds.put(PacketTypeClasses.Play.Server.OPEN_SIGN_EDITOR, OPEN_SIGN_EDITOR);
packetIds.put(PacketTypeClasses.Play.Server.AUTO_RECIPE, AUTO_RECIPE);
packetIds.put(PacketTypeClasses.Play.Server.ABILITIES, ABILITIES);
packetIds.put(PacketTypeClasses.Play.Server.COMBAT_EVENT, COMBAT_EVENT);
packetIds.put(PacketTypeClasses.Play.Server.PLAYER_INFO, PLAYER_INFO);
packetIds.put(PacketTypeClasses.Play.Server.LOOK_AT, LOOK_AT);
packetIds.put(PacketTypeClasses.Play.Server.POSITION, POSITION);
packetIds.put(PacketTypeClasses.Play.Server.RECIPES, RECIPES);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_DESTROY, ENTITY_DESTROY);
packetIds.put(PacketTypeClasses.Play.Server.REMOVE_ENTITY_EFFECT, REMOVE_ENTITY_EFFECT);
packetIds.put(PacketTypeClasses.Play.Server.RESOURCE_PACK_SEND, RESOURCE_PACK_SEND);
packetIds.put(PacketTypeClasses.Play.Server.RESPAWN, RESPAWN);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_HEAD_ROTATION, ENTITY_HEAD_ROTATION);
packetIds.put(PacketTypeClasses.Play.Server.SELECT_ADVANCEMENT_TAB, SELECT_ADVANCEMENT_TAB);
packetIds.put(PacketTypeClasses.Play.Server.WORLD_BORDER, WORLD_BORDER);
packetIds.put(PacketTypeClasses.Play.Server.CAMERA, CAMERA);
packetIds.put(PacketTypeClasses.Play.Server.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
packetIds.put(PacketTypeClasses.Play.Server.VIEW_CENTRE, VIEW_CENTRE);
packetIds.put(PacketTypeClasses.Play.Server.VIEW_DISTANCE, VIEW_DISTANCE);
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_DISPLAY_OBJECTIVE, SCOREBOARD_DISPLAY_OBJECTIVE);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_METADATA, ENTITY_METADATA);
packetIds.put(PacketTypeClasses.Play.Server.ATTACH_ENTITY, ATTACH_ENTITY);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_VELOCITY, ENTITY_VELOCITY);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_EQUIPMENT, ENTITY_EQUIPMENT);
packetIds.put(PacketTypeClasses.Play.Server.EXPERIENCE, EXPERIENCE);
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_HEALTH, UPDATE_HEALTH);
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_OBJECTIVE, SCOREBOARD_OBJECTIVE);
packetIds.put(PacketTypeClasses.Play.Server.MOUNT, MOUNT);
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_TEAM, SCOREBOARD_TEAM);
packetIds.put(PacketTypeClasses.Play.Server.SCOREBOARD_SCORE, SCOREBOARD_SCORE);
packetIds.put(PacketTypeClasses.Play.Server.SPAWN_POSITION, SPAWN_POSITION);
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_TIME, UPDATE_TIME);
packetIds.put(PacketTypeClasses.Play.Server.TITLE, TITLE);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_SOUND, ENTITY_SOUND);
packetIds.put(PacketTypeClasses.Play.Server.NAMED_SOUND_EFFECT, NAMED_SOUND_EFFECT);
packetIds.put(PacketTypeClasses.Play.Server.STOP_SOUND, STOP_SOUND);
packetIds.put(PacketTypeClasses.Play.Server.PLAYER_LIST_HEADER_FOOTER, PLAYER_LIST_HEADER_FOOTER);
packetIds.put(PacketTypeClasses.Play.Server.NBT_QUERY, NBT_QUERY);
packetIds.put(PacketTypeClasses.Play.Server.COLLECT, COLLECT);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_TELEPORT, ENTITY_TELEPORT);
packetIds.put(PacketTypeClasses.Play.Server.ADVANCEMENTS, ADVANCEMENTS);
packetIds.put(PacketTypeClasses.Play.Server.UPDATE_ATTRIBUTES, UPDATE_ATTRIBUTES);
packetIds.put(PacketTypeClasses.Play.Server.ENTITY_EFFECT, ENTITY_EFFECT);
packetIds.put(PacketTypeClasses.Play.Server.RECIPE_UPDATE, RECIPE_UPDATE);
packetIds.put(PacketTypeClasses.Play.Server.TAGS, TAGS);
packetIds.put(PacketTypeClasses.Play.Server.MAP_CHUNK_BULK, MAP_CHUNK_BULK);
packetIds.put(PacketTypeClasses.Play.Server.NAMED_ENTITY_SPAWN, NAMED_ENTITY_SPAWN);
}
/**
* Client-bound Play Packet Type utility.
* Save a few lines of code by using this.
*
* @author retrooper
* @since 1.8
*/
public static class Util {
/**
* Is the play packet a PacketPlayOutEntity, PacketPlayOutRelEntityMove, PacketPlayOutRelEntityMoveLook
* or a PacketPlayOutEntityLook packet?
*
* @param packetID Play Packet ID.
* @return Is the Packet ID an instance of the PacketPlayOutEntity packet?
*/
public static boolean isInstanceOfEntity(final byte packetID) {
return packetID == ENTITY || packetID == REL_ENTITY_MOVE ||
packetID == REL_ENTITY_MOVE_LOOK || packetID == ENTITY_LOOK;
}
}
}
}
}
@@ -28,259 +28,291 @@ import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
public class PacketTypeClasses {
public static void load() {
//PLAY
PacketTypeClasses.Play.Client.load();
PacketTypeClasses.Play.Server.load();
//LOGIN
PacketTypeClasses.Login.Client.load();
PacketTypeClasses.Login.Server.load();
//STATUS
PacketTypeClasses.Status.Client.load();
PacketTypeClasses.Status.Server.load();
}
public static class Status {
public static Class<?> PING, PONG;
public static class Client {
public static Class<?> START, PING;
public static void load() {
PING = NMSUtils.getNMSClassWithoutException("PacketStatusInPing");
PONG = NMSUtils.getNMSClassWithoutException("PacketStatusOutPong");
PacketType.Status.init();
public static void load() {
Client.START = NMSUtils.getNMSClassWithoutException("PacketStatusInStart");
Client.PING = NMSUtils.getNMSClassWithoutException("PacketStatusInPing");
PacketType.Status.Client.init();
}
}
public static class Server {
public static Class<?> PONG, SERVER_INFO;
public static void load() {
Server.PONG = NMSUtils.getNMSClassWithoutException("PacketStatusOutPong");
Server.SERVER_INFO = NMSUtils.getNMSClassWithoutException("PacketStatusOutServerInfo");
PacketType.Status.Server.init();
}
}
}
public static class Login {
public static Class<?> HANDSHAKE,
IN_CUSTOM_PAYLOAD, OUT_CUSTOM_PAYLOAD,IN_START, IN_ENCRYPTION_BEGIN,
DISCONNECT, OUT_ENCRYPTION_BEGIN, OUT_SUCCESS;
public static class Client {
public static Class<?> HANDSHAKE, CUSTOM_PAYLOAD, START, ENCRYPTION_BEGIN;
public static void load() {
HANDSHAKE = NMSUtils.getNMSClassWithoutException("PacketHandshakingInSetProtocol");
//In and Out custom payload login packets have been here since AROUND 1.13.2?
IN_CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginInCustomPayload");
OUT_CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginOutCustomPayload");
IN_START = NMSUtils.getNMSClassWithoutException("PacketLoginInStart");
IN_ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginInEncryptionBegin");
DISCONNECT = NMSUtils.getNMSClassWithoutException("PacketLoginOutDisconnect");
OUT_ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginOutEncryptionBegin");
OUT_SUCCESS = NMSUtils.getNMSClassWithoutException("PacketLoginOutSuccess");
PacketType.Login.init();
public static void load() {
Client.HANDSHAKE = NMSUtils.getNMSClassWithoutException("PacketHandshakingInSetProtocol");
//In and Out custom payload login packets have been here since AROUND 1.13.2.
Client.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginInCustomPayload");
Client.START = NMSUtils.getNMSClassWithoutException("PacketLoginInStart");
Client.ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginInEncryptionBegin");
PacketType.Login.Client.init();
}
}
public static class Server {
public static Class<?> CUSTOM_PAYLOAD, DISCONNECT, ENCRYPTION_BEGIN, SUCCESS, SET_COMPRESSION;
public static void load() {
Server.CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException("PacketLoginOutCustomPayload");
Server.DISCONNECT = NMSUtils.getNMSClassWithoutException("PacketLoginOutDisconnect");
Server.ENCRYPTION_BEGIN = NMSUtils.getNMSClassWithoutException("PacketLoginOutEncryptionBegin");
Server.SUCCESS = NMSUtils.getNMSClassWithoutException("PacketLoginOutSuccess");
Server.SET_COMPRESSION = NMSUtils.getNMSClassWithoutException("PacketLoginOutSetCompression");
PacketType.Login.Server.init();
}
}
}
public static class Client {
private static final String c = "PacketPlayIn";
public static Class<?> FLYING, POSITION, POSITION_LOOK, LOOK, CLIENT_COMMAND,
TRANSACTION, BLOCK_DIG, ENTITY_ACTION, USE_ENTITY,
WINDOW_CLICK, STEER_VEHICLE, CUSTOM_PAYLOAD, ARM_ANIMATION,
BLOCK_PLACE, USE_ITEM, ABILITIES, HELD_ITEM_SLOT,
CLOSE_WINDOW, TAB_COMPLETE, CHAT, SET_CREATIVE_SLOT,
KEEP_ALIVE, SETTINGS, ENCHANT_ITEM, TELEPORT_ACCEPT,
TILE_NBT_QUERY, DIFFICULTY_CHANGE, B_EDIT, ENTITY_NBT_QUERY,
JIGSAW_GENERATE, DIFFICULTY_LOCK, VEHICLE_MOVE, BOAT_MOVE, PICK_ITEM,
AUTO_RECIPE, RECIPE_DISPLAYED, ITEM_NAME, RESOURCE_PACK_STATUS,
ADVANCEMENTS, TR_SEL, BEACON, SET_COMMAND_BLOCK,
SET_COMMAND_MINECART, SET_JIGSAW, STRUCT, UPDATE_SIGN, SPECTATE;
public static class Play {
public static class Client {
private static final String PREFIX = "PacketPlayIn";
public static Class<?> FLYING, POSITION, POSITION_LOOK, LOOK, CLIENT_COMMAND,
TRANSACTION, BLOCK_DIG, ENTITY_ACTION, USE_ENTITY,
WINDOW_CLICK, STEER_VEHICLE, CUSTOM_PAYLOAD, ARM_ANIMATION,
BLOCK_PLACE, USE_ITEM, ABILITIES, HELD_ITEM_SLOT,
CLOSE_WINDOW, TAB_COMPLETE, CHAT, SET_CREATIVE_SLOT,
KEEP_ALIVE, SETTINGS, ENCHANT_ITEM, TELEPORT_ACCEPT,
TILE_NBT_QUERY, DIFFICULTY_CHANGE, B_EDIT, ENTITY_NBT_QUERY,
JIGSAW_GENERATE, DIFFICULTY_LOCK, VEHICLE_MOVE, BOAT_MOVE, PICK_ITEM,
AUTO_RECIPE, RECIPE_DISPLAYED, ITEM_NAME, RESOURCE_PACK_STATUS,
ADVANCEMENTS, TR_SEL, BEACON, SET_COMMAND_BLOCK,
SET_COMMAND_MINECART, SET_JIGSAW, STRUCT, UPDATE_SIGN, SPECTATE;
/**
* Initiate all server-bound packet classes.
*/
public static void load() {
FLYING = NMSUtils.getNMSClassWithoutException(c + "Flying");
try {
POSITION = NMSUtils.getNMSClass(c + "Position");
POSITION_LOOK = NMSUtils.getNMSClass(c + "PositionLook");
LOOK = NMSUtils.getNMSClass(c + "Look");
} catch (ClassNotFoundException e) {
POSITION = SubclassUtil.getSubClass(FLYING, c + "Position");
POSITION_LOOK = SubclassUtil.getSubClass(FLYING, c + "PositionLook");
LOOK = SubclassUtil.getSubClass(FLYING, c + "Look");
/**
* Initiate all server-bound play packet classes.
*/
public static void load() {
FLYING = NMSUtils.getNMSClassWithoutException(PREFIX + "Flying");
try {
POSITION = NMSUtils.getNMSClass(PREFIX + "Position");
POSITION_LOOK = NMSUtils.getNMSClass(PREFIX + "PositionLook");
LOOK = NMSUtils.getNMSClass(PREFIX + "Look");
} catch (ClassNotFoundException e) {
POSITION = SubclassUtil.getSubClass(FLYING, PREFIX + "Position");
POSITION_LOOK = SubclassUtil.getSubClass(FLYING, PREFIX + "PositionLook");
LOOK = SubclassUtil.getSubClass(FLYING, PREFIX + "Look");
}
try {
SETTINGS = NMSUtils.getNMSClass(PREFIX + "Settings");
ENCHANT_ITEM = NMSUtils.getNMSClass(PREFIX + "EnchantItem");
CLIENT_COMMAND = NMSUtils.getNMSClass(PREFIX + "ClientCommand");
TRANSACTION = NMSUtils.getNMSClass(PREFIX + "Transaction");
BLOCK_DIG = NMSUtils.getNMSClass(PREFIX + "BlockDig");
ENTITY_ACTION = NMSUtils.getNMSClass(PREFIX + "EntityAction");
USE_ENTITY = NMSUtils.getNMSClass(PREFIX + "UseEntity");
WINDOW_CLICK = NMSUtils.getNMSClass(PREFIX + "WindowClick");
STEER_VEHICLE = NMSUtils.getNMSClass(PREFIX + "SteerVehicle");
CUSTOM_PAYLOAD = NMSUtils.getNMSClass(PREFIX + "CustomPayload");
ARM_ANIMATION = NMSUtils.getNMSClass(PREFIX + "ArmAnimation");
ABILITIES = NMSUtils.getNMSClass(PREFIX + "Abilities");
HELD_ITEM_SLOT = NMSUtils.getNMSClass(PREFIX + "HeldItemSlot");
CLOSE_WINDOW = NMSUtils.getNMSClass(PREFIX + "CloseWindow");
TAB_COMPLETE = NMSUtils.getNMSClass(PREFIX + "TabComplete");
CHAT = NMSUtils.getNMSClass(PREFIX + "Chat");
SET_CREATIVE_SLOT = NMSUtils.getNMSClass(PREFIX + "SetCreativeSlot");
KEEP_ALIVE = NMSUtils.getNMSClass(PREFIX + "KeepAlive");
UPDATE_SIGN = NMSUtils.getNMSClassWithoutException(PREFIX + "UpdateSign");
TELEPORT_ACCEPT = NMSUtils.getNMSClassWithoutException(PREFIX + "TeleportAccept");
TILE_NBT_QUERY = NMSUtils.getNMSClassWithoutException(PREFIX + "TileNBTQuery");
DIFFICULTY_CHANGE = NMSUtils.getNMSClassWithoutException(PREFIX + "DifficultyChange");
B_EDIT = NMSUtils.getNMSClassWithoutException(PREFIX + "BEdit");
ENTITY_NBT_QUERY = NMSUtils.getNMSClassWithoutException(PREFIX + "EntityNBTQuery");
JIGSAW_GENERATE = NMSUtils.getNMSClassWithoutException(PREFIX + "JigsawGenerate");
DIFFICULTY_LOCK = NMSUtils.getNMSClassWithoutException(PREFIX + "DifficultyLock");
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(PREFIX + "VehicleMove");
BOAT_MOVE = NMSUtils.getNMSClassWithoutException(PREFIX + "BoatMove");
PICK_ITEM = NMSUtils.getNMSClassWithoutException(PREFIX + "PickItem");
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(PREFIX + "AutoRecipe");
RECIPE_DISPLAYED = NMSUtils.getNMSClassWithoutException(PREFIX + "RecipeDisplayed");
ITEM_NAME = NMSUtils.getNMSClassWithoutException(PREFIX + "ItemName");
//1.8+
RESOURCE_PACK_STATUS = NMSUtils.getNMSClassWithoutException(PREFIX + "ResourcePackStatus");
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(PREFIX + "Advancements");
TR_SEL = NMSUtils.getNMSClassWithoutException(PREFIX + "TrSel");
BEACON = NMSUtils.getNMSClassWithoutException(PREFIX + "Beacon");
SET_COMMAND_BLOCK = NMSUtils.getNMSClassWithoutException(PREFIX + "SetCommandBlock");
SET_COMMAND_MINECART = NMSUtils.getNMSClassWithoutException(PREFIX + "SetCommandMinecart");
SET_JIGSAW = NMSUtils.getNMSClassWithoutException(PREFIX + "SetJigsaw");
STRUCT = NMSUtils.getNMSClassWithoutException(PREFIX + "Struct");
SPECTATE = NMSUtils.getNMSClassWithoutException(PREFIX + "Spectate");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
BLOCK_PLACE = NMSUtils.getNMSClass(PREFIX + "BlockPlace");
USE_ITEM = NMSUtils.getNMSClass(PREFIX + "UseItem");
} catch (ClassNotFoundException ignored) {
}
PacketType.Play.Client.init();
}
try {
SETTINGS = NMSUtils.getNMSClass(c + "Settings");
ENCHANT_ITEM = NMSUtils.getNMSClass(c + "EnchantItem");
CLIENT_COMMAND = NMSUtils.getNMSClass(c + "ClientCommand");
TRANSACTION = NMSUtils.getNMSClass(c + "Transaction");
BLOCK_DIG = NMSUtils.getNMSClass(c + "BlockDig");
ENTITY_ACTION = NMSUtils.getNMSClass(c + "EntityAction");
USE_ENTITY = NMSUtils.getNMSClass(c + "UseEntity");
WINDOW_CLICK = NMSUtils.getNMSClass(c + "WindowClick");
STEER_VEHICLE = NMSUtils.getNMSClass(c + "SteerVehicle");
CUSTOM_PAYLOAD = NMSUtils.getNMSClass(c + "CustomPayload");
ARM_ANIMATION = NMSUtils.getNMSClass(c + "ArmAnimation");
ABILITIES = NMSUtils.getNMSClass(c + "Abilities");
HELD_ITEM_SLOT = NMSUtils.getNMSClass(c + "HeldItemSlot");
CLOSE_WINDOW = NMSUtils.getNMSClass(c + "CloseWindow");
TAB_COMPLETE = NMSUtils.getNMSClass(c + "TabComplete");
CHAT = NMSUtils.getNMSClass(c + "Chat");
SET_CREATIVE_SLOT = NMSUtils.getNMSClass(c + "SetCreativeSlot");
KEEP_ALIVE = NMSUtils.getNMSClass(c + "KeepAlive");
UPDATE_SIGN = NMSUtils.getNMSClassWithoutException(c + "UpdateSign");
TELEPORT_ACCEPT = NMSUtils.getNMSClassWithoutException(c + "TeleportAccept");
TILE_NBT_QUERY = NMSUtils.getNMSClassWithoutException(c + "TileNBTQuery");
DIFFICULTY_CHANGE = NMSUtils.getNMSClassWithoutException(c + "DifficultyChange");
B_EDIT = NMSUtils.getNMSClassWithoutException(c + "BEdit");
ENTITY_NBT_QUERY = NMSUtils.getNMSClassWithoutException(c + "EntityNBTQuery");
JIGSAW_GENERATE = NMSUtils.getNMSClassWithoutException(c + "JigsawGenerate");
DIFFICULTY_LOCK = NMSUtils.getNMSClassWithoutException(c + "DifficultyLock");
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(c + "VehicleMove");
BOAT_MOVE = NMSUtils.getNMSClassWithoutException(c + "BoatMove");
PICK_ITEM = NMSUtils.getNMSClassWithoutException(c + "PickItem");
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(c + "AutoRecipe");
RECIPE_DISPLAYED = NMSUtils.getNMSClassWithoutException(c + "RecipeDisplayed");
ITEM_NAME = NMSUtils.getNMSClassWithoutException(c + "ItemName");
//1.8+
RESOURCE_PACK_STATUS = NMSUtils.getNMSClassWithoutException(c + "ResourcePackStatus");
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(c + "Advancements");
TR_SEL = NMSUtils.getNMSClassWithoutException(c + "TrSel");
BEACON = NMSUtils.getNMSClassWithoutException(c + "Beacon");
SET_COMMAND_BLOCK = NMSUtils.getNMSClassWithoutException(c + "SetCommandBlock");
SET_COMMAND_MINECART = NMSUtils.getNMSClassWithoutException(c + "SetCommandMinecart");
SET_JIGSAW = NMSUtils.getNMSClassWithoutException(c + "SetJigsaw");
STRUCT = NMSUtils.getNMSClassWithoutException(c + "Struct");
SPECTATE = NMSUtils.getNMSClassWithoutException(c + "Spectate");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
BLOCK_PLACE = NMSUtils.getNMSClass(c + "BlockPlace");
} catch (ClassNotFoundException e) {
}
try {
USE_ITEM = NMSUtils.getNMSClass(c + "UseItem");
} catch (ClassNotFoundException e2) {
}
PacketType.Client.init();
}
}
public static class Server {
private static final String s = "PacketPlayOut";
public static Class<?> SPAWN_ENTITY, SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_LIVING,
SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_SPAWN, ANIMATION, STATISTIC,
BLOCK_BREAK, BLOCK_BREAK_ANIMATION, TILE_ENTITY_DATA, BLOCK_ACTION,
BLOCK_CHANGE, BOSS, SERVER_DIFFICULTY, CHAT, MULTI_BLOCK_CHANGE,
TAB_COMPLETE, COMMANDS, TRANSACTION, CLOSE_WINDOW,
WINDOW_ITEMS, WINDOW_DATA, SET_SLOT, SET_COOLDOWN,
CUSTOM_PAYLOAD, CUSTOM_SOUND_EFFECT, KICK_DISCONNECT, ENTITY_STATUS,
EXPLOSION, UNLOAD_CHUNK, GAME_STATE_CHANGE, OPEN_WINDOW_HORSE,
KEEP_ALIVE, MAP_CHUNK, WORLD_EVENT, WORLD_PARTICLES,
LIGHT_UPDATE, LOGIN, MAP, OPEN_WINDOW_MERCHANT,
REL_ENTITY_MOVE, REL_ENTITY_MOVE_LOOK, ENTITY_LOOK, ENTITY,
VEHICLE_MOVE, OPEN_BOOK, OPEN_WINDOW, OPEN_SIGN_EDITOR,
AUTO_RECIPE, ABILITIES, COMBAT_EVENT, PLAYER_INFO,
LOOK_AT, POSITION, RECIPES, ENTITY_DESTROY,
REMOVE_ENTITY_EFFECT, RESOURCE_PACK_SEND, RESPAWN, ENTITY_HEAD_ROTATION,
SELECT_ADVANCEMENT_TAB, WORLD_BORDER, CAMERA, HELD_ITEM_SLOT,
VIEW_CENTRE, VIEW_DISTANCE, SCOREBOARD_DISPLAY_OBJECTIVE, ENTITY_METADATA,
ATTACH_ENTITY, ENTITY_VELOCITY, ENTITY_EQUIPMENT, EXPERIENCE,
UPDATE_HEALTH, SCOREBOARD_OBJECTIVE, MOUNT, SCOREBOARD_TEAM,
SCOREBOARD_SCORE, SPAWN_POSITION, UPDATE_TIME, TITLE,
ENTITY_SOUND, NAMED_SOUND_EFFECT, STOP_SOUND, PLAYER_LIST_HEADER_FOOTER,
NBT_QUERY, COLLECT, ENTITY_TELEPORT, ADVANCEMENTS, UPDATE_ATTRIBUTES,
ENTITY_EFFECT, RECIPE_UPDATE, TAGS, MAP_CHUNK_BULK;
public static class Server {
private static final String s = "PacketPlayOut";
public static Class<?> SPAWN_ENTITY, SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_LIVING,
SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_SPAWN, ANIMATION, STATISTIC,
BLOCK_BREAK, BLOCK_BREAK_ANIMATION, TILE_ENTITY_DATA, BLOCK_ACTION,
BLOCK_CHANGE, BOSS, SERVER_DIFFICULTY, CHAT, MULTI_BLOCK_CHANGE,
TAB_COMPLETE, COMMANDS, TRANSACTION, CLOSE_WINDOW,
WINDOW_ITEMS, WINDOW_DATA, SET_SLOT, SET_COOLDOWN,
CUSTOM_PAYLOAD, CUSTOM_SOUND_EFFECT, KICK_DISCONNECT, ENTITY_STATUS,
EXPLOSION, UNLOAD_CHUNK, GAME_STATE_CHANGE, OPEN_WINDOW_HORSE,
KEEP_ALIVE, MAP_CHUNK, WORLD_EVENT, WORLD_PARTICLES,
LIGHT_UPDATE, LOGIN, MAP, OPEN_WINDOW_MERCHANT,
REL_ENTITY_MOVE, REL_ENTITY_MOVE_LOOK, ENTITY_LOOK, ENTITY,
VEHICLE_MOVE, OPEN_BOOK, OPEN_WINDOW, OPEN_SIGN_EDITOR,
AUTO_RECIPE, ABILITIES, COMBAT_EVENT, PLAYER_INFO,
LOOK_AT, POSITION, RECIPES, ENTITY_DESTROY,
REMOVE_ENTITY_EFFECT, RESOURCE_PACK_SEND, RESPAWN, ENTITY_HEAD_ROTATION,
SELECT_ADVANCEMENT_TAB, WORLD_BORDER, CAMERA, HELD_ITEM_SLOT,
VIEW_CENTRE, VIEW_DISTANCE, SCOREBOARD_DISPLAY_OBJECTIVE, ENTITY_METADATA,
ATTACH_ENTITY, ENTITY_VELOCITY, ENTITY_EQUIPMENT, EXPERIENCE,
UPDATE_HEALTH, SCOREBOARD_OBJECTIVE, MOUNT, SCOREBOARD_TEAM,
SCOREBOARD_SCORE, SPAWN_POSITION, UPDATE_TIME, TITLE,
ENTITY_SOUND, NAMED_SOUND_EFFECT, STOP_SOUND, PLAYER_LIST_HEADER_FOOTER,
NBT_QUERY, COLLECT, ENTITY_TELEPORT, ADVANCEMENTS, UPDATE_ATTRIBUTES,
ENTITY_EFFECT, RECIPE_UPDATE, TAGS, MAP_CHUNK_BULK, NAMED_ENTITY_SPAWN;
/**
* Initiate all client-bound packet classes.
*/
public static void load() {
SPAWN_ENTITY = NMSUtils.getNMSClassWithoutException(s + "SpawnEntity");
SPAWN_ENTITY_EXPERIENCE_ORB = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityExperienceOrb");
SPAWN_ENTITY_WEATHER = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityWeather");
SPAWN_ENTITY_LIVING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityLiving");
SPAWN_ENTITY_PAINTING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityPainting");
SPAWN_ENTITY_SPAWN = NMSUtils.getNMSClassWithoutException(s + "SpawnEntitySpawn");
ANIMATION = NMSUtils.getNMSClassWithoutException(s + "Animation");
STATISTIC = NMSUtils.getNMSClassWithoutException(s + "Statistic");
BLOCK_BREAK = NMSUtils.getNMSClassWithoutException(s + "BlockBreak");
BLOCK_BREAK_ANIMATION = NMSUtils.getNMSClassWithoutException(s + "BlockBreakAnimation");
TILE_ENTITY_DATA = NMSUtils.getNMSClassWithoutException(s + "TileEntityData");
BLOCK_ACTION = NMSUtils.getNMSClassWithoutException(s + "BlockAction");
BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "BlockChange");
BOSS = NMSUtils.getNMSClassWithoutException(s + "Boss");
SERVER_DIFFICULTY = NMSUtils.getNMSClassWithoutException(s + "ServerDifficulty");
CHAT = NMSUtils.getNMSClassWithoutException(s + "Chat");
MULTI_BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "MultiBlockChange");
TAB_COMPLETE = NMSUtils.getNMSClassWithoutException(s + "TabComplete");
COMMANDS = NMSUtils.getNMSClassWithoutException(s + "Commands");
TRANSACTION = NMSUtils.getNMSClassWithoutException(s + "Transaction");
CLOSE_WINDOW = NMSUtils.getNMSClassWithoutException(s + "CloseWindow");
WINDOW_ITEMS = NMSUtils.getNMSClassWithoutException(s + "WindowItems");
WINDOW_DATA = NMSUtils.getNMSClassWithoutException(s + "WindowData");
SET_SLOT = NMSUtils.getNMSClassWithoutException(s + "SetSlot");
SET_COOLDOWN = NMSUtils.getNMSClassWithoutException(s + "SetCooldown");
CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException(s + "CustomPayload");
CUSTOM_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "CustomSoundEffect");
KICK_DISCONNECT = NMSUtils.getNMSClassWithoutException(s + "KickDisconnect");
ENTITY_STATUS = NMSUtils.getNMSClassWithoutException(s + "EntityStatus");
EXPLOSION = NMSUtils.getNMSClassWithoutException(s + "Explosion");
UNLOAD_CHUNK = NMSUtils.getNMSClassWithoutException(s + "UnloadChunk");
GAME_STATE_CHANGE = NMSUtils.getNMSClassWithoutException(s + "GameStateChange");
OPEN_WINDOW_HORSE = NMSUtils.getNMSClassWithoutException(s + "OpenWindowHorse");
KEEP_ALIVE = NMSUtils.getNMSClassWithoutException(s + "KeepAlive");
MAP_CHUNK = NMSUtils.getNMSClassWithoutException(s + "MapChunk");
WORLD_EVENT = NMSUtils.getNMSClassWithoutException(s + "WorldEvent");
WORLD_PARTICLES = NMSUtils.getNMSClassWithoutException(s + "WorldParticles");
LIGHT_UPDATE = NMSUtils.getNMSClassWithoutException(s + "LightUpdate");
LOGIN = NMSUtils.getNMSClassWithoutException(s + "Login");
MAP = NMSUtils.getNMSClassWithoutException(s + "Map");
OPEN_WINDOW_MERCHANT = NMSUtils.getNMSClassWithoutException(s + "OpenWindowMerchant");
ENTITY = NMSUtils.getNMSClassWithoutException(s + "Entity");
REL_ENTITY_MOVE = SubclassUtil.getSubClass(ENTITY, s + "RelEntityMove");
REL_ENTITY_MOVE_LOOK = SubclassUtil.getSubClass(ENTITY, s + "RelEntityMoveLook");
ENTITY_LOOK = SubclassUtil.getSubClass(ENTITY, s + "EntityLook");
if (REL_ENTITY_MOVE == null) {
//is not a subclass and should be accessed normally
REL_ENTITY_MOVE = NMSUtils.getNMSClassWithoutException(s + "RelEntityMove");
REL_ENTITY_MOVE_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityMoveLook");
ENTITY_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityLook");
/**
* Initiate all client-bound packet classes.
*/
public static void load() {
SPAWN_ENTITY = NMSUtils.getNMSClassWithoutException(s + "SpawnEntity");
SPAWN_ENTITY_EXPERIENCE_ORB = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityExperienceOrb");
SPAWN_ENTITY_WEATHER = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityWeather");
SPAWN_ENTITY_LIVING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityLiving");
SPAWN_ENTITY_PAINTING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityPainting");
SPAWN_ENTITY_SPAWN = NMSUtils.getNMSClassWithoutException(s + "SpawnEntitySpawn");
ANIMATION = NMSUtils.getNMSClassWithoutException(s + "Animation");
STATISTIC = NMSUtils.getNMSClassWithoutException(s + "Statistic");
BLOCK_BREAK = NMSUtils.getNMSClassWithoutException(s + "BlockBreak");
BLOCK_BREAK_ANIMATION = NMSUtils.getNMSClassWithoutException(s + "BlockBreakAnimation");
TILE_ENTITY_DATA = NMSUtils.getNMSClassWithoutException(s + "TileEntityData");
BLOCK_ACTION = NMSUtils.getNMSClassWithoutException(s + "BlockAction");
BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "BlockChange");
BOSS = NMSUtils.getNMSClassWithoutException(s + "Boss");
SERVER_DIFFICULTY = NMSUtils.getNMSClassWithoutException(s + "ServerDifficulty");
CHAT = NMSUtils.getNMSClassWithoutException(s + "Chat");
MULTI_BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "MultiBlockChange");
TAB_COMPLETE = NMSUtils.getNMSClassWithoutException(s + "TabComplete");
COMMANDS = NMSUtils.getNMSClassWithoutException(s + "Commands");
TRANSACTION = NMSUtils.getNMSClassWithoutException(s + "Transaction");
CLOSE_WINDOW = NMSUtils.getNMSClassWithoutException(s + "CloseWindow");
WINDOW_ITEMS = NMSUtils.getNMSClassWithoutException(s + "WindowItems");
WINDOW_DATA = NMSUtils.getNMSClassWithoutException(s + "WindowData");
SET_SLOT = NMSUtils.getNMSClassWithoutException(s + "SetSlot");
SET_COOLDOWN = NMSUtils.getNMSClassWithoutException(s + "SetCooldown");
CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException(s + "CustomPayload");
CUSTOM_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "CustomSoundEffect");
KICK_DISCONNECT = NMSUtils.getNMSClassWithoutException(s + "KickDisconnect");
ENTITY_STATUS = NMSUtils.getNMSClassWithoutException(s + "EntityStatus");
EXPLOSION = NMSUtils.getNMSClassWithoutException(s + "Explosion");
UNLOAD_CHUNK = NMSUtils.getNMSClassWithoutException(s + "UnloadChunk");
GAME_STATE_CHANGE = NMSUtils.getNMSClassWithoutException(s + "GameStateChange");
OPEN_WINDOW_HORSE = NMSUtils.getNMSClassWithoutException(s + "OpenWindowHorse");
KEEP_ALIVE = NMSUtils.getNMSClassWithoutException(s + "KeepAlive");
MAP_CHUNK = NMSUtils.getNMSClassWithoutException(s + "MapChunk");
WORLD_EVENT = NMSUtils.getNMSClassWithoutException(s + "WorldEvent");
WORLD_PARTICLES = NMSUtils.getNMSClassWithoutException(s + "WorldParticles");
LIGHT_UPDATE = NMSUtils.getNMSClassWithoutException(s + "LightUpdate");
LOGIN = NMSUtils.getNMSClassWithoutException(s + "Login");
MAP = NMSUtils.getNMSClassWithoutException(s + "Map");
OPEN_WINDOW_MERCHANT = NMSUtils.getNMSClassWithoutException(s + "OpenWindowMerchant");
ENTITY = NMSUtils.getNMSClassWithoutException(s + "Entity");
REL_ENTITY_MOVE = SubclassUtil.getSubClass(ENTITY, s + "RelEntityMove");
REL_ENTITY_MOVE_LOOK = SubclassUtil.getSubClass(ENTITY, s + "RelEntityMoveLook");
ENTITY_LOOK = SubclassUtil.getSubClass(ENTITY, s + "EntityLook");
if (REL_ENTITY_MOVE == null) {
//is not a subclass and should be accessed normally
REL_ENTITY_MOVE = NMSUtils.getNMSClassWithoutException(s + "RelEntityMove");
REL_ENTITY_MOVE_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityMoveLook");
ENTITY_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityLook");
}
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(s + "VehicleMove");
OPEN_BOOK = NMSUtils.getNMSClassWithoutException(s + "OpenBook");
OPEN_WINDOW = NMSUtils.getNMSClassWithoutException(s + "OpenWindow");
OPEN_SIGN_EDITOR = NMSUtils.getNMSClassWithoutException(s + "OpenSignEditor");
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(s + "AutoRecipe");
ABILITIES = NMSUtils.getNMSClassWithoutException(s + "Abilities");
COMBAT_EVENT = NMSUtils.getNMSClassWithoutException(s + "CombatEvent");
PLAYER_INFO = NMSUtils.getNMSClassWithoutException(s + "PlayerInfo");
LOOK_AT = NMSUtils.getNMSClassWithoutException(s + "LookAt");
POSITION = NMSUtils.getNMSClassWithoutException(s + "Position");
RECIPES = NMSUtils.getNMSClassWithoutException(s + "Recipes");
ENTITY_DESTROY = NMSUtils.getNMSClassWithoutException(s + "EntityDestroy");
REMOVE_ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "RemoveEntityEffect");
RESOURCE_PACK_SEND = NMSUtils.getNMSClassWithoutException(s + "ResourcePackSend");
RESPAWN = NMSUtils.getNMSClassWithoutException(s + "Respawn");
ENTITY_HEAD_ROTATION = NMSUtils.getNMSClassWithoutException(s + "EntityHeadRotation");
SELECT_ADVANCEMENT_TAB = NMSUtils.getNMSClassWithoutException(s + "SelectAdvancementTab");
WORLD_BORDER = NMSUtils.getNMSClassWithoutException(s + "WorldBorder");
CAMERA = NMSUtils.getNMSClassWithoutException(s + "Camera");
HELD_ITEM_SLOT = NMSUtils.getNMSClassWithoutException(s + "HeldItemSlot");
VIEW_CENTRE = NMSUtils.getNMSClassWithoutException(s + "ViewCentre");
VIEW_DISTANCE = NMSUtils.getNMSClassWithoutException(s + "ViewDistance");
SCOREBOARD_DISPLAY_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardDisplayObjective");
ENTITY_METADATA = NMSUtils.getNMSClassWithoutException(s + "EntityMetadata");
ATTACH_ENTITY = NMSUtils.getNMSClassWithoutException(s + "AttachEntity");
ENTITY_VELOCITY = NMSUtils.getNMSClassWithoutException(s + "EntityVelocity");
ENTITY_EQUIPMENT = NMSUtils.getNMSClassWithoutException(s + "EntityEquipment");
EXPERIENCE = NMSUtils.getNMSClassWithoutException(s + "Experience");
UPDATE_HEALTH = NMSUtils.getNMSClassWithoutException(s + "UpdateHealth");
SCOREBOARD_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardObjective");
MOUNT = NMSUtils.getNMSClassWithoutException(s + "Mount");
SCOREBOARD_TEAM = NMSUtils.getNMSClassWithoutException(s + "ScoreboardTeam");
SCOREBOARD_SCORE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardScore");
SPAWN_POSITION = NMSUtils.getNMSClassWithoutException(s + "SpawnPosition");
UPDATE_TIME = NMSUtils.getNMSClassWithoutException(s + "UpdateTime");
TITLE = NMSUtils.getNMSClassWithoutException(s + "Title");
ENTITY_SOUND = NMSUtils.getNMSClassWithoutException(s + "EntitySound");
NAMED_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "NamedSoundEffect");
STOP_SOUND = NMSUtils.getNMSClassWithoutException(s + "StopSound");
PLAYER_LIST_HEADER_FOOTER = NMSUtils.getNMSClassWithoutException(s + "PlayerListHeaderFooter");
NBT_QUERY = NMSUtils.getNMSClassWithoutException(s + "NBTQuery");
COLLECT = NMSUtils.getNMSClassWithoutException(s + "Collect");
ENTITY_TELEPORT = NMSUtils.getNMSClassWithoutException(s + "EntityTeleport");
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(s + "Advancements");
UPDATE_ATTRIBUTES = NMSUtils.getNMSClassWithoutException(s + "UpdateAttributes");
ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "EntityEffect");
RECIPE_UPDATE = NMSUtils.getNMSClassWithoutException(s + "RecipeUpdate");
TAGS = NMSUtils.getNMSClassWithoutException(s + "Tags");
MAP_CHUNK_BULK = NMSUtils.getNMSClassWithoutException(s + "MapChunkBulk");
NAMED_ENTITY_SPAWN = NMSUtils.getNMSClassWithoutException(s + "NamedEntitySpawn");
PacketType.Play.Server.init();
}
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(s + "VehicleMove");
OPEN_BOOK = NMSUtils.getNMSClassWithoutException(s + "OpenBook");
OPEN_WINDOW = NMSUtils.getNMSClassWithoutException(s + "OpenWindow");
OPEN_SIGN_EDITOR = NMSUtils.getNMSClassWithoutException(s + "OpenSignEditor");
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(s + "AutoRecipe");
ABILITIES = NMSUtils.getNMSClassWithoutException(s + "Abilities");
COMBAT_EVENT = NMSUtils.getNMSClassWithoutException(s + "CombatEvent");
PLAYER_INFO = NMSUtils.getNMSClassWithoutException(s + "PlayerInfo");
LOOK_AT = NMSUtils.getNMSClassWithoutException(s + "LookAt");
POSITION = NMSUtils.getNMSClassWithoutException(s + "Position");
RECIPES = NMSUtils.getNMSClassWithoutException(s + "Recipes");
ENTITY_DESTROY = NMSUtils.getNMSClassWithoutException(s + "EntityDestroy");
REMOVE_ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "RemoveEntityEffect");
RESOURCE_PACK_SEND = NMSUtils.getNMSClassWithoutException(s + "ResourcePackSend");
RESPAWN = NMSUtils.getNMSClassWithoutException(s + "Respawn");
ENTITY_HEAD_ROTATION = NMSUtils.getNMSClassWithoutException(s + "EntityHeadRotation");
SELECT_ADVANCEMENT_TAB = NMSUtils.getNMSClassWithoutException(s + "SelectAdvancementTab");
WORLD_BORDER = NMSUtils.getNMSClassWithoutException(s + "WorldBorder");
CAMERA = NMSUtils.getNMSClassWithoutException(s + "Camera");
HELD_ITEM_SLOT = NMSUtils.getNMSClassWithoutException(s + "HeldItemSlot");
VIEW_CENTRE = NMSUtils.getNMSClassWithoutException(s + "ViewCentre");
VIEW_DISTANCE = NMSUtils.getNMSClassWithoutException(s + "ViewDistance");
SCOREBOARD_DISPLAY_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardDisplayObjective");
ENTITY_METADATA = NMSUtils.getNMSClassWithoutException(s + "EntityMetadata");
ATTACH_ENTITY = NMSUtils.getNMSClassWithoutException(s + "AttachEntity");
ENTITY_VELOCITY = NMSUtils.getNMSClassWithoutException(s + "EntityVelocity");
ENTITY_EQUIPMENT = NMSUtils.getNMSClassWithoutException(s + "EntityEquipment");
EXPERIENCE = NMSUtils.getNMSClassWithoutException(s + "Experience");
UPDATE_HEALTH = NMSUtils.getNMSClassWithoutException(s + "UpdateHealth");
SCOREBOARD_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardObjective");
MOUNT = NMSUtils.getNMSClassWithoutException(s + "Mount");
SCOREBOARD_TEAM = NMSUtils.getNMSClassWithoutException(s + "ScoreboardTeam");
SCOREBOARD_SCORE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardScore");
SPAWN_POSITION = NMSUtils.getNMSClassWithoutException(s + "SpawnPosition");
UPDATE_TIME = NMSUtils.getNMSClassWithoutException(s + "UpdateTime");
TITLE = NMSUtils.getNMSClassWithoutException(s + "Title");
ENTITY_SOUND = NMSUtils.getNMSClassWithoutException(s + "EntitySound");
NAMED_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "NamedSoundEffect");
STOP_SOUND = NMSUtils.getNMSClassWithoutException(s + "StopSound");
PLAYER_LIST_HEADER_FOOTER = NMSUtils.getNMSClassWithoutException(s + "PlayerListHeaderFooter");
NBT_QUERY = NMSUtils.getNMSClassWithoutException(s + "NBTQuery");
COLLECT = NMSUtils.getNMSClassWithoutException(s + "Collect");
ENTITY_TELEPORT = NMSUtils.getNMSClassWithoutException(s + "EntityTeleport");
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(s + "Advancements");
UPDATE_ATTRIBUTES = NMSUtils.getNMSClassWithoutException(s + "UpdateAttributes");
ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "EntityEffect");
RECIPE_UPDATE = NMSUtils.getNMSClassWithoutException(s + "RecipeUpdate");
TAGS = NMSUtils.getNMSClassWithoutException(s + "Tags");
MAP_CHUNK_BULK = NMSUtils.getNMSClassWithoutException(s + "MapChunkBulk");
PacketType.Server.init();
}
}
@@ -22,19 +22,22 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.utils.viaversion;
package io.github.retrooper.packetevents.packetwrappers;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import java.util.UUID;
public class NMSPacket {
private final Object rawNMSPacket;
class ViaAPIAccessor {
public static int getProtocolVersion(final Player player) {
return getProtocolVersion(player.getUniqueId());
public NMSPacket(Object rawNMSPacket) {
this.rawNMSPacket = rawNMSPacket;
}
public static int getProtocolVersion(final UUID uuid) {
return Via.getAPI().getPlayerVersion(uuid);
public Object getRawNMSPacket() {
return rawNMSPacket;
}
public String getName() {
return ClassUtil.getClassSimpleName(rawNMSPacket.getClass());
}
}
@@ -26,481 +26,137 @@ package io.github.retrooper.packetevents.packetwrappers;
import io.github.retrooper.packetevents.exceptions.WrapperFieldNotFoundException;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.in.blockdig.WrappedPacketInBlockDig;
import io.github.retrooper.packetevents.packetwrappers.in.blockplace.WrappedPacketInBlockPlace;
import io.github.retrooper.packetevents.packetwrappers.in.clientcommand.WrappedPacketInClientCommand;
import io.github.retrooper.packetevents.packetwrappers.in.custompayload.WrappedPacketInCustomPayload;
import io.github.retrooper.packetevents.packetwrappers.in.entityaction.WrappedPacketInEntityAction;
import io.github.retrooper.packetevents.packetwrappers.in.keepalive.WrappedPacketInKeepAlive;
import io.github.retrooper.packetevents.packetwrappers.in.settings.WrappedPacketInSettings;
import io.github.retrooper.packetevents.packetwrappers.in.updatesign.WrappedPacketInUpdateSign;
import io.github.retrooper.packetevents.packetwrappers.in.useentity.WrappedPacketInUseEntity;
import io.github.retrooper.packetevents.packetwrappers.in.windowclick.WrappedPacketInWindowClick;
import io.github.retrooper.packetevents.packetwrappers.out.abilities.WrappedPacketOutAbilities;
import io.github.retrooper.packetevents.packetwrappers.out.animation.WrappedPacketOutAnimation;
import io.github.retrooper.packetevents.packetwrappers.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.packetwrappers.out.custompayload.WrappedPacketOutCustomPayload;
import io.github.retrooper.packetevents.packetwrappers.out.entity.WrappedPacketOutEntity;
import io.github.retrooper.packetevents.packetwrappers.out.entitystatus.WrappedPacketOutEntityStatus;
import io.github.retrooper.packetevents.packetwrappers.out.entityteleport.WrappedPacketOutEntityTeleport;
import io.github.retrooper.packetevents.packetwrappers.out.entityvelocity.WrappedPacketOutEntityVelocity;
import io.github.retrooper.packetevents.packetwrappers.out.experience.WrappedPacketOutExperience;
import io.github.retrooper.packetevents.packetwrappers.out.explosion.WrappedPacketOutExplosion;
import io.github.retrooper.packetevents.packetwrappers.out.gamestatechange.WrappedPacketOutGameStateChange;
import io.github.retrooper.packetevents.packetwrappers.out.keepalive.WrappedPacketOutKeepAlive;
import io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect.WrappedPacketOutKickDisconnect;
import io.github.retrooper.packetevents.packetwrappers.out.position.WrappedPacketOutPosition;
import io.github.retrooper.packetevents.packetwrappers.out.transaction.WrappedPacketOutTransaction;
import io.github.retrooper.packetevents.packetwrappers.out.updatehealth.WrappedPacketOutUpdateHealth;
import io.github.retrooper.packetevents.utils.reflection.ClassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
private static final Map<Class<?>, Map<Class<?>, Field[]>> fieldCache = new HashMap<>();
private static final Map<Class<? extends WrappedPacket>, Boolean> LOADED_WRAPPERS = new ConcurrentHashMap<>();
private static final Map<Class<?>, Map<Class<?>, Field[]>> FIELD_CACHE = new ConcurrentHashMap<>();
private static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
public static ServerVersion version;
protected final Player player;
protected Object packet;
private Class<?> packetClass;
protected NMSPacket packet;
private final Class<?> packetClass;
public WrappedPacket() {
this.player = null;
packet = null;
packetClass = null;
load0();
}
public WrappedPacket(final Object packet) {
this(packet, packet.getClass());
public WrappedPacket(final NMSPacket packet) {
this(packet, packet.getRawNMSPacket().getClass());
}
public WrappedPacket(final Object packet, final Class<?> packetClass) {
this(null, packet, packetClass);
}
public WrappedPacket(final Player player, final Object packet) {
this(player, packet, packet.getClass());
}
public WrappedPacket(final Player player, final Object packet, Class<?> packetClass) {
if (packet == null) {
this.player = null;
return;
}
if (packet.getClass().getSuperclass().equals(PacketTypeClasses.Client.FLYING)) {
packetClass = PacketTypeClasses.Client.FLYING;
} else if (packet.getClass().getSuperclass().equals(PacketTypeClasses.Server.ENTITY)) {
packetClass = PacketTypeClasses.Server.ENTITY;
public WrappedPacket(final NMSPacket packet, Class<?> packetClass) {
if (packetClass.getSuperclass().equals(PacketTypeClasses.Play.Client.FLYING)) {
packetClass = PacketTypeClasses.Play.Client.FLYING;
} else if (packetClass.getSuperclass().equals(PacketTypeClasses.Play.Server.ENTITY)) {
packetClass = PacketTypeClasses.Play.Server.ENTITY;
}
this.packetClass = packetClass;
if (!fieldCache.containsKey(packetClass)) {
final Field[] declaredFields = packetClass.getDeclaredFields();
List<Field> boolFields = new ArrayList<>();
List<Field> byteFields = new ArrayList<>();
List<Field> shortFields = new ArrayList<>();
List<Field> intFields = new ArrayList<>();
List<Field> longFields = new ArrayList<>();
List<Field> floatFields = new ArrayList<>();
List<Field> doubleFields = new ArrayList<>();
List<Field> stringFields = new ArrayList<>();
List<Field> boolArrayFields = new ArrayList<>();
List<Field> byteArrayFields = new ArrayList<>();
List<Field> shortArrayFields = new ArrayList<>();
List<Field> intArrayFields = new ArrayList<>();
List<Field> longArrayFields = new ArrayList<>();
List<Field> floatArrayFields = new ArrayList<>();
List<Field> doubleArrayFields = new ArrayList<>();
List<Field> stringArrayFields = new ArrayList<>();
for (Field f : declaredFields) {
f.setAccessible(true);
if (f.getType().equals(boolean.class)) {
boolFields.add(f);
} else if (f.getType().equals(byte.class)) {
byteFields.add(f);
} else if (f.getType().equals(short.class)) {
shortFields.add(f);
} else if (f.getType().equals(int.class)) {
intFields.add(f);
} else if (f.getType().equals(long.class)) {
longFields.add(f);
} else if (f.getType().equals(float.class)) {
floatFields.add(f);
} else if (f.getType().equals(double.class)) {
doubleFields.add(f);
} else if (f.getType().equals(String.class)) {
stringFields.add(f);
} else if (f.getType().equals(boolean[].class)) {
boolArrayFields.add(f);
} else if (f.getType().equals(byte[].class)) {
byteArrayFields.add(f);
} else if (f.getType().equals(short[].class)) {
shortArrayFields.add(f);
} else if (f.getType().equals(int[].class)) {
intArrayFields.add(f);
} else if (f.getType().equals(long[].class)) {
longArrayFields.add(f);
} else if (f.getType().equals(float[].class)) {
floatArrayFields.add(f);
} else if (f.getType().equals(double[].class)) {
doubleArrayFields.add(f);
} else if (f.getType().equals(String[].class)) {
stringArrayFields.add(f);
}
}
Map<Class<?>, Field[]> map = new HashMap<>();
if (!boolFields.isEmpty()) {
map.put(boolean.class, boolFields.toArray(new Field[0]));
}
if (!byteFields.isEmpty()) {
map.put(byte.class, byteFields.toArray(new Field[0]));
}
if (!shortFields.isEmpty()) {
map.put(short.class, shortFields.toArray(new Field[0]));
}
if (!intFields.isEmpty()) {
map.put(int.class, intFields.toArray(new Field[0]));
}
if (!longFields.isEmpty()) {
map.put(long.class, longFields.toArray(new Field[0]));
}
if (!floatFields.isEmpty()) {
map.put(float.class, floatFields.toArray(new Field[0]));
}
if (!doubleFields.isEmpty()) {
map.put(double.class, doubleFields.toArray(new Field[0]));
}
if (!stringFields.isEmpty()) {
map.put(String.class, stringFields.toArray(new Field[0]));
}
if (!boolArrayFields.isEmpty()) {
map.put(boolean[].class, boolArrayFields.toArray(new Field[0]));
}
if (!byteArrayFields.isEmpty()) {
map.put(byte[].class, byteArrayFields.toArray(new Field[0]));
}
if (!shortArrayFields.isEmpty()) {
map.put(short[].class, shortArrayFields.toArray(new Field[0]));
}
if (!intArrayFields.isEmpty()) {
map.put(int[].class, intArrayFields.toArray(new Field[0]));
}
if (!longArrayFields.isEmpty()) {
map.put(long[].class, longArrayFields.toArray(new Field[0]));
}
if (!floatArrayFields.isEmpty()) {
map.put(float[].class, floatArrayFields.toArray(new Field[0]));
}
if (!doubleArrayFields.isEmpty()) {
map.put(double[].class, doubleArrayFields.toArray(new Field[0]));
}
if (!stringArrayFields.isEmpty()) {
map.put(String[].class, stringArrayFields.toArray(new Field[0]));
}
fieldCache.put(packetClass, map);
}
this.player = player;
this.packet = packet;
setup();
load0();
}
public static void loadAllWrappers() {
//SERVER BOUND
WrappedPacketInBlockDig.load();
WrappedPacketInBlockPlace.load();
WrappedPacketInClientCommand.load();
WrappedPacketInCustomPayload.load();
WrappedPacketInEntityAction.load();
WrappedPacketInKeepAlive.load();
WrappedPacketInSettings.load();
WrappedPacketInUseEntity.load();
WrappedPacketInUpdateSign.load();
WrappedPacketInWindowClick.load();
//CLIENTBOUND
WrappedPacketOutAbilities.load();
WrappedPacketOutAnimation.load();
WrappedPacketOutChat.load();
WrappedPacketOutEntity.load();
WrappedPacketOutEntityVelocity.load();
WrappedPacketOutEntityTeleport.load();
WrappedPacketOutKeepAlive.load();
WrappedPacketOutKickDisconnect.load();
WrappedPacketOutPosition.load();
WrappedPacketOutTransaction.load();
WrappedPacketOutUpdateHealth.load();
WrappedPacketOutGameStateChange.load();
WrappedPacketOutCustomPayload.load();
WrappedPacketOutExplosion.load();
WrappedPacketOutEntityStatus.load();
WrappedPacketOutExperience.load();
private void load0() {
final Class<? extends WrappedPacket> clazz = getClass();
if (!LOADED_WRAPPERS.containsKey(clazz)) {
load();
LOADED_WRAPPERS.put(clazz, true);
}
}
protected void setup() {
protected void load() {
}
@Override
public boolean readBoolean(int index) {
return (boolean) read(boolean.class, index);
return read(index, boolean.class);
}
@Override
public byte readByte(int index) {
return (byte) read(byte.class, index);
return read(index, byte.class);
}
@Override
public short readShort(int index) {
return (short) read(short.class, index);
return read(index, short.class);
}
@Override
public int readInt(int index) {
return (int) read(int.class, index);
return read(index, int.class);
}
@Override
public long readLong(int index) {
return (long) read(long.class, index);
return read(index, long.class);
}
@Override
public float readFloat(int index) {
return (float) read(float.class, index);
return read(index, float.class);
}
@Override
public double readDouble(int index) {
return (double) read(double.class, index);
return read(index, double.class);
}
@Override
public boolean[] readBooleanArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (boolean[]) cached.get(boolean[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (boolean[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (boolean[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, boolean[].class, index);
return read(index, boolean[].class);
}
@Override
public byte[] readByteArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (byte[]) cached.get(byte[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (byte[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (byte[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, byte[].class, index);
return read(index, byte[].class);
}
@Override
public short[] readShortArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (short[]) cached.get(short[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (short[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (short[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, short[].class, index);
return read(index, short[].class);
}
@Override
public int[] readIntArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (int[]) cached.get(int[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (int[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (int[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, int[].class, index);
return read(index, int[].class);
}
@Override
public long[] readLongArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (long[]) cached.get(long[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (long[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (long[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, long[].class, index);
return read(index, long[].class);
}
@Override
public float[] readFloatArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (float[]) cached.get(float[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (float.class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (float[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, float[].class, index);
return read(index, float[].class);
}
@Override
public double[] readDoubleArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
return (double[]) cached.get(double[].class)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
int currentIndex = 0;
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (double[].class.isAssignableFrom(f.getType())) {
if (index == currentIndex++) {
try {
return (double[]) f.get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new WrapperFieldNotFoundException(packetClass, double[].class, index);
return read(index, double[].class);
}
@Override
public String[] readStringArray(int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
try {
Object[] array = (Object[]) cached.get(String[].class)[index].get(packet);
int len = array.length;
String[] stringArray = new String[len];
for (int i = 0; i < len; i++) {
stringArray[i] = array[i].toString();
}
return stringArray;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
throw new WrapperFieldNotFoundException(packetClass, String[].class, index);
return read(index, String[].class); // Can we be sure that returning the original array is okay?
}
@Override
public String readString(int index) {
return (String) read(String.class, index);
return read(index, String.class);
}
public Object readAnyObject(int index) {
@@ -510,8 +166,8 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
f.setAccessible(true);
}
try {
return f.get(packet);
} catch (IllegalAccessException e) {
return f.get(packet.getRawNMSPacket());
} catch (IllegalAccessException | NullPointerException | ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
} catch (ArrayIndexOutOfBoundsException e) {
@@ -521,32 +177,17 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
}
public Object readObject(int index, Class<?> type) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached != null) {
if (!cached.containsKey(type)) {
List<Field> typeFields = new ArrayList<>();
for (Field f : packetClass.getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(type)) {
typeFields.add(f);
}
}
if (!typeFields.isEmpty()) {
cached.put(type, typeFields.toArray(new Field[0]));
}
}
}
try {
return cached.get(type)[index].get(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new WrapperFieldNotFoundException(packetClass, type, index);
return read(index, type);
}
public Object[] readObjectArray(int index, Class<?> type) {
return (Object[]) readObject(index, type);
@SuppressWarnings("unchecked")
public <T> T read(int index, Class<? extends T> type) {
Field field = getField(type, index);
try {
return (T) field.get(packet.getRawNMSPacket());
} catch (IllegalAccessException | NullPointerException e) {
throw new WrapperFieldNotFoundException(packetClass, type, index);
}
}
@Override
@@ -589,41 +230,44 @@ public class WrappedPacket implements WrapperPacketReader, WrapperPacketWriter {
write(String.class, index, value);
}
private void write(Class<?> type, int index, Object value) throws WrapperFieldNotFoundException {
Field field = getField(type, index);
if(field == null) {
throw new WrapperFieldNotFoundException(packetClass, type, index);
}
try {
field.set(packet, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
@Override
public void writeObject(int index, Object value) {
write(value.getClass(), index, value);
}
private Object read(Class<?> type, int index) throws WrapperFieldNotFoundException {
public void write(Class<?> type, int index, Object value) throws WrapperFieldNotFoundException {
Field field = getField(type, index);
if(field == null) {
if (field == null) {
throw new WrapperFieldNotFoundException(packetClass, type, index);
}
try {
return field.get(packet);
} catch (IllegalAccessException e) {
field.set(packet.getRawNMSPacket(), value);
} catch (IllegalAccessException | NullPointerException e) {
e.printStackTrace();
}
return null;
}
private Field getField(Class<?> type, int index) {
Map<Class<?>, Field[]> cached = fieldCache.get(packetClass);
if (cached == null) {
return null;
}
Field[] fields = cached.get(type);
if (fields != null) {
return fields[index];
}
return null;
Map<Class<?>, Field[]> cached = FIELD_CACHE.computeIfAbsent(packetClass, k -> new HashMap<>());
Field[] fields = cached.computeIfAbsent(type, typeClass -> getFields(typeClass, packetClass.getDeclaredFields()));
return fields[index];
}
private Field[] getFields(Class<?> type, Field[] fields) {
List<Field> ret = new ArrayList<>();
for (Field field : fields) {
if (field.getType().equals(type)) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
ret.add(field);
}
}
return ret.toArray(EMPTY_FIELD_ARRAY);
}
// Does the server version support reading/sending this packet?
public boolean isSupported() {
return true;
}
}
@@ -61,6 +61,4 @@ public interface WrapperPacketReader {
Object readObject(int index, Class<?> type);
Object readAnyObject(int index);
Object[] readObjectArray(int index, Class<?> type);
}
@@ -26,7 +26,7 @@ package io.github.retrooper.packetevents.packetwrappers;
public interface WrapperPacketWriter {
//TODO write for the arrays
// TODO write for the arrays
void writeBoolean(int index, boolean value);
void writeByte(int index, byte value);
@@ -42,4 +42,6 @@ public interface WrapperPacketWriter {
void writeDouble(int index, double value);
void writeString(int index, String value);
void writeObject(int index, Object object);
}
@@ -1,138 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public final class WrappedPacketInBlockPlace extends WrappedPacket {
private static boolean isHigherThan_v_1_8_8, isHigherThan_v_1_7_10;
private WrappedPacket cachedWrappedPacket;
public WrappedPacketInBlockPlace(final Player player, final Object packet) {
super(player, packet);
}
public static void load() {
isHigherThan_v_1_8_8 = version.isHigherThan(ServerVersion.v_1_8_8);
isHigherThan_v_1_7_10 = version.isHigherThan(ServerVersion.v_1_7_10);
if (isHigherThan_v_1_7_10) {
WrappedPacketInBlockPlace_1_8.load();
}
}
public Player getPlayer() {
return player;
}
public int getX() {
if (isHigherThan_v_1_8_8) {
if (cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
cachedWrappedPacket = blockPlace_1_9;
return blockPlace_1_9.getBlock().getX();
}
return ((WrappedPacketInBlockPlace_1_9)cachedWrappedPacket).getBlock().getX();
} else if (isHigherThan_v_1_7_10) {
if(cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
cachedWrappedPacket = blockPlace_1_8;
return blockPlace_1_8.getX();
}
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.x;
}
return 0;
}
public int getY() {
if (isHigherThan_v_1_8_8) {
if (cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
cachedWrappedPacket = blockPlace_1_9;
return blockPlace_1_9.getBlock().getY();
}
return ((WrappedPacketInBlockPlace_1_9)cachedWrappedPacket).getBlock().getX();
} else if (isHigherThan_v_1_7_10) {
if(cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
cachedWrappedPacket = blockPlace_1_8;
return blockPlace_1_8.getY();
}
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.y;
}
return 0;
}
public int getZ() {
if (isHigherThan_v_1_8_8) {
if (cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
cachedWrappedPacket = blockPlace_1_9;
return blockPlace_1_9.getBlock().getZ();
}
return ((WrappedPacketInBlockPlace_1_9)cachedWrappedPacket).getBlock().getX();
} else if (isHigherThan_v_1_7_10) {
if(cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
cachedWrappedPacket = blockPlace_1_8;
return blockPlace_1_8.getZ();
}
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.z;
}
return 0;
}
public ItemStack getItemStack() {
if (isHigherThan_v_1_8_8) {
if (cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
cachedWrappedPacket = blockPlace_1_9;
return new ItemStack(blockPlace_1_9.getBlock().getType());
}
return new ItemStack(((WrappedPacketInBlockPlace_1_9)cachedWrappedPacket).getBlock().getType());
} else if (isHigherThan_v_1_7_10) {
if(cachedWrappedPacket == null) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
cachedWrappedPacket = blockPlace_1_8;
return blockPlace_1_8.getItemStack();
}
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.itemStack;
}
return null;
}
}
@@ -1,93 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.useentity;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import org.bukkit.entity.Entity;
public final class WrappedPacketInUseEntity extends WrappedPacket {
private static Class<?> enumEntityUseActionClass;
private Entity entity;
private int entityID = -1;
public WrappedPacketInUseEntity(final Object packet) {
super(packet);
}
public static void load() {
//System.out.println("USE ENTITY HAS BEEN LOADED BROOOIOII");
Class<?> useEntityClass = NMSUtils.getNMSClassWithoutException("PacketPlayInUseEntity");
/*if(useEntityClass == null) {
System.out.println("failed to init use entity wtfffff");
}*/
try {
enumEntityUseActionClass = NMSUtils.getNMSClass("EnumEntityUseAction");
} catch (ClassNotFoundException e) {
//That is fine, it is probably a subclass
enumEntityUseActionClass = SubclassUtil.getSubClass(useEntityClass, "EnumEntityUseAction");
}
}
/**
* Lookup the associated entity by the ID that was sent in the packet.
* @return Entity
*/
public Entity getEntity() {
if(entity != null) {
return entity;
}
return entity = NMSUtils.getEntityById(getEntityID());
}
/**
* Get the ID of the entity.
* If you do not want to use {@link #getEntity()},
* you lookup the entity by yourself with this entity ID.
* @return Entity ID
*/
public int getEntityID() {
if(entityID != -1) {
return entityID;
}
else {
return entityID = readInt(0);
}
}
/**
* Get the associated action.
* @return Get EntityUseAction
*/
public EntityUseAction getAction() {
final Object useActionEnum = readObject(0, enumEntityUseActionClass);
return EntityUseAction.valueOf(useActionEnum.toString());
}
public enum EntityUseAction {
INTERACT, INTERACT_AT, ATTACK, INVALID
}
}
@@ -0,0 +1,69 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in.custompayload;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
/**
* This packet exists since 1.13
*/
public class WrappedPacketLoginInCustomPayload extends WrappedPacket {
private static Class<?> byteBufClass;
private static Class<?> packetDataSerializerClass;
public WrappedPacketLoginInCustomPayload(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
try {
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
} catch (ClassNotFoundException ignored) {
}
}
public int getMessageId() {
return readInt(0);
}
public byte[] getData() {
Object dataSerializer = readObject(0, packetDataSerializerClass);
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
}
@Override
public boolean isSupported() {
return version.isHigherThan(ServerVersion.v_1_12_2);
}
}
@@ -22,21 +22,27 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in;
package io.github.retrooper.packetevents.packetwrappers.login.in.encryptionbegin;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketLoginInCustomPayload extends WrappedPacket {
public WrappedPacketLoginInCustomPayload(Object packet) {
public class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
public WrappedPacketLoginInEncryptionBegin(NMSPacket packet) {
super(packet);
}
public byte[] getPublicKey() {
return readByteArray(0);
}
/* TODO wrappers
* net.minecraft.server.v1_16_R2.PacketLoginInCustomPayload inCP;
* net.minecraft.server.v1_16_R2.PacketLoginOutCustomPayload outCP;
* net.minecraft.server.v1_16_R2.PacketPlayOutLogin outLogin;
* Find out about the Status Response packet
*/
public byte[] getVerifyToken() {
return readByteArray(1);
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Client.ENCRYPTION_BEGIN != null;
}
}
@@ -0,0 +1,52 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in.handshake;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketLoginInHandshake extends WrappedPacket {
public WrappedPacketLoginInHandshake(NMSPacket packet) {
super(packet);
}
public int getProtocolVersion() {
return readInt(0);
}
public String getHostName() {
return readString(0);
}
public int getPort() {
return readInt(1);
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Client.HANDSHAKE != null;
}
}
@@ -22,19 +22,26 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in;
package io.github.retrooper.packetevents.packetwrappers.login.in.start;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.gameprofile.GameProfileUtil;
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
public class WrappedPacketLoginInStart extends WrappedPacket {
public WrappedPacketLoginInStart(Object packet) {
public WrappedPacketLoginInStart(NMSPacket packet) {
super(packet);
}
public WrappedGameProfile getGameProfile() {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Client.START != null;
}
}
@@ -0,0 +1,136 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out.custompayload;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class WrappedPacketLoginOutCustomPayload extends WrappedPacket implements SendableWrapper {
private static Constructor<?> constructor;
private static Constructor<?> packetDataSerializerConstructor;
private static Constructor<?> minecraftKeyConstructor;
private static Class<?> byteBufClass;
private static Class<?> packetDataSerializerClass;
private static Class<?> minecraftKeyClass;
private int messageID;
private String channelName;
private byte[] data;
public WrappedPacketLoginOutCustomPayload(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
Class<?> packetClass = PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD;
if (packetClass != null) {
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
minecraftKeyClass = NMSUtils.getNMSClassWithoutException("MinecraftKey");
try {
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
try {
if (packetDataSerializerClass != null) {
packetDataSerializerConstructor = packetDataSerializerClass.getConstructor(byteBufClass);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
if (minecraftKeyClass != null) {
minecraftKeyConstructor = minecraftKeyClass.getConstructor(String.class);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = packetClass.getConstructor();
} catch (NoSuchMethodException e3) {
throw new IllegalStateException("PacketEvents is unable to resolve the PacketPlayOutCustomPayload constructor.");
}
}
}
public int getMessageId() {
if (packet != null) {
return readInt(0);
}
return messageID;
}
public String getChannelName() {
if (packet != null) {
Object minecraftKey = readObject(0, minecraftKeyClass);
WrappedPacket minecraftKeyWrapper = new WrappedPacket(new NMSPacket(minecraftKey));
return minecraftKeyWrapper.readString(1);
}
return channelName;
}
public byte[] getData() {
if (packet != null) {
Object dataSerializer = readObject(0, packetDataSerializerClass);
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
}
return data;
}
@Override
public Object asNMSPacket() {
Object byteBufObject = PacketEvents.get().getByteBufUtil().wrappedBuffer(data);
try {
Object minecraftKey = minecraftKeyConstructor.newInstance(channelName);
Object dataSerializer = packetDataSerializerConstructor.newInstance(byteBufObject);
Object packetInstance = constructor.newInstance();
WrappedPacket packetWrapper = new WrappedPacket(new NMSPacket(packetInstance));
packetWrapper.writeInt(0, messageID);
packetWrapper.writeObject(0, minecraftKey);
packetWrapper.writeObject(0, dataSerializer);
return packetInstance;
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.CUSTOM_PAYLOAD != null;
}
}
@@ -22,14 +22,16 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out;
package io.github.retrooper.packetevents.packetwrappers.login.out.disconnect;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.packetwrappers.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.packetwrappers.play.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
public class WrappedPacketLoginDisconnect extends WrappedPacket {
public WrappedPacketLoginDisconnect(Object packet) {
public class WrappedPacketLoginOutDisconnect extends WrappedPacket {
public WrappedPacketLoginOutDisconnect(NMSPacket packet) {
super(packet);
}
@@ -37,4 +39,9 @@ public class WrappedPacketLoginDisconnect extends WrappedPacket {
Object iChatBaseComponent = readObject(0, NMSUtils.iChatBaseComponentClass);
return WrappedPacketOutChat.toStringFromIChatBaseComponent(iChatBaseComponent);
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.DISCONNECT != null;
}
}
@@ -22,14 +22,16 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out;
package io.github.retrooper.packetevents.packetwrappers.login.out.encryptionbegin;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import java.security.PublicKey;
public class WrappedPacketLoginOutEncryptionBegin extends WrappedPacket {
public WrappedPacketLoginOutEncryptionBegin(Object packet) {
public WrappedPacketLoginOutEncryptionBegin(NMSPacket packet) {
super(packet);
}
@@ -44,4 +46,9 @@ public class WrappedPacketLoginOutEncryptionBegin extends WrappedPacket {
public byte[] getByteArray() {
return readByteArray(0);
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.ENCRYPTION_BEGIN != null;
}
}
@@ -0,0 +1,85 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out.setcompression;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.SendableWrapper;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//This packet does not exist on 1.7.10
public class WrappedPacketLoginOutSetCompression extends WrappedPacket implements SendableWrapper {
private static Constructor<?> constructor;
private int threshold;
public WrappedPacketLoginOutSetCompression(NMSPacket packet) {
super(packet);
}
public WrappedPacketLoginOutSetCompression(int threshold) {
this.threshold = threshold;
}
@Override
protected void load() {
try {
if (PacketTypeClasses.Login.Server.SET_COMPRESSION != null) {
constructor = PacketTypeClasses.Login.Server.SET_COMPRESSION.getConstructor(int.class);
}
} catch (NoSuchMethodException e) {
//probably 1.7.10
}
}
/**
* Maximum size of a packet before it can be compressed.
*
* @return threshold Threshold
*/
public int getThreshold() {
if (packet != null) {
return readInt(0);
}
return threshold;
}
@Override
public Object asNMSPacket() {
try {
return constructor.newInstance(threshold);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.SET_COMPRESSION != null;
}
}
@@ -22,19 +22,26 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out;
package io.github.retrooper.packetevents.packetwrappers.login.out.success;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.gameprofile.GameProfileUtil;
import io.github.retrooper.packetevents.utils.gameprofile.WrappedGameProfile;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
public class WrappedPacketLoginOutSuccess extends WrappedPacket {
public WrappedPacketLoginOutSuccess(Object packet) {
public WrappedPacketLoginOutSuccess(NMSPacket packet) {
super(packet);
}
public WrappedGameProfile getGameProfile() {
return GameProfileUtil.getWrappedGameProfile(readObject(0, NMSUtils.gameProfileClass));
}
@Override
public boolean isSupported() {
return PacketTypeClasses.Login.Server.SUCCESS != null;
}
}
@@ -22,33 +22,44 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.abilities;
package io.github.retrooper.packetevents.packetwrappers.play.in.abilities;
import io.github.retrooper.packetevents.annotations.NotNull;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
public final class WrappedPacketInAbilities extends WrappedPacket {
private static boolean v_1_16_Mode = false;
public WrappedPacketInAbilities(Object packet) {
public WrappedPacketInAbilities(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
v_1_16_Mode = Reflection.getField(PacketTypeClasses.Play.Client.ABILITIES, boolean.class, 1) == null;
}
/**
* This will return null if the server version is not available in 1.16.x and above
*
* @return Whether the player is vulnerable to damage or not.
*/
@Deprecated
@Nullable
public boolean isVulnerable() {
public boolean isVulnerable() throws UnsupportedOperationException {
if (v_1_16_Mode) {
throw new UnsupportedOperationException("This field does not exist on your version!");
}
return readBoolean(0);
}
@NotNull
public boolean isFlying() {
return readBoolean(1);
if (v_1_16_Mode) {
return readBoolean(0);
} else {
return readBoolean(1);
}
}
/**
@@ -57,8 +68,10 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
* @return Whether or not the player can fly.
*/
@Deprecated
@Nullable
public boolean isFlightAllowed() {
if (v_1_16_Mode) {
throw new UnsupportedOperationException("This field does not exist on your version!");
}
return readBoolean(2);
}
@@ -68,8 +81,10 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
* @return Whether or not the player can break blocks instantly.
*/
@Deprecated
@Nullable
public boolean canInstantlyBuild() {
if (v_1_16_Mode) {
throw new UnsupportedOperationException("This field does not exist on your version!");
}
return readBoolean(3);
}
@@ -79,8 +94,10 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
* @return The speed at which the player can fly, as a float.
*/
@Deprecated
@Nullable
public float getFlySpeed() {
if (v_1_16_Mode) {
throw new UnsupportedOperationException("This field does not exist on your version!");
}
return readFloat(0);
}
@@ -90,8 +107,10 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
* @return The speed at which the player can walk, as a float.
*/
@Deprecated
@Nullable
public float getWalkSpeed() {
if (v_1_16_Mode) {
throw new UnsupportedOperationException("This field does not exist on your version!");
}
return readFloat(1);
}
}
@@ -0,0 +1,18 @@
package io.github.retrooper.packetevents.packetwrappers.play.in.beacon;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInBeacon extends WrappedPacket {
public WrappedPacketInBeacon(NMSPacket packet) {
super(packet);
}
public int getPrimaryEffect() {
return readInt(0);
}
public int getSecondaryEffect() {
return readInt(1);
}
}
@@ -22,26 +22,35 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.blockdig;
package io.github.retrooper.packetevents.packetwrappers.play.in.blockdig;
import io.github.retrooper.packetevents.enums.Direction;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.player.Direction;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketInBlockDig extends WrappedPacket {
private static Class<?> blockDigClass, blockPositionClass, enumDirectionClass, digTypeClass;
private static Class<?> blockPositionClass;
private static Class<?> enumDirectionClass;
private static Class<?> digTypeClass;
private static boolean isVersionLowerThan_v_1_8;
private Object blockPosObj, enumDirObj, digTypeObj;
public WrappedPacketInBlockDig(Object packet) {
private Object blockPosObj;
private Object enumDirObj;
public WrappedPacketInBlockDig(NMSPacket packet) {
super(packet);
}
public static void load() {
blockDigClass = PacketTypeClasses.Client.BLOCK_DIG;
@Override
protected void load() {
Class<?> blockDigClass = PacketTypeClasses.Play.Client.BLOCK_DIG;
try {
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
@@ -64,82 +73,98 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
/**
* Get X position of the block
*
* @return Block Position X
*/
public int getX() {
if(isVersionLowerThan_v_1_8) {
if (isVersionLowerThan_v_1_8) {
return readInt(0);
}
else {
if(blockPosObj == null) {
} else {
if (blockPosObj == null) {
blockPosObj = readObject(0, blockPositionClass);
}
WrappedPacket blockPosWrapper = new WrappedPacket(blockPosObj);
return blockPosWrapper.readInt(0);
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
}
}
/**
* Get Y position of the block
*
* @return Block Position Y
*/
public int getY() {
if(isVersionLowerThan_v_1_8) {
if (isVersionLowerThan_v_1_8) {
return readInt(1);
}
else {
if(blockPosObj == null) {
} else {
if (blockPosObj == null) {
blockPosObj = readObject(0, blockPositionClass);
}
WrappedPacket blockPosWrapper = new WrappedPacket(blockPosObj);
return blockPosWrapper.readInt(1);
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
}
}
/**
* Get Z position of the block
*
* @return Block Position Z
*/
public int getZ() {
if(isVersionLowerThan_v_1_8) {
if (isVersionLowerThan_v_1_8) {
return readInt(2);
}
else {
if(blockPosObj == null) {
} else {
if (blockPosObj == null) {
blockPosObj = readObject(0, blockPositionClass);
}
WrappedPacket blockPosWrapper = new WrappedPacket(blockPosObj);
return blockPosWrapper.readInt(2);
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return -1;
}
}
/**
* Get the direction
* Is Direction.NULL on 1.7.10 FOR NOW
* Get the direction / Get the face.
*
* @return Direction
*/
@Nullable
public Direction getDirection() {
if(isVersionLowerThan_v_1_8) {
return Direction.NULL;
}
else {
if(enumDirObj == null) {
net.minecraft.server.v1_7_R4.PacketPlayInBlockDig bd;
if (isVersionLowerThan_v_1_8) {
return new Direction((byte) readInt(3));
} else {
if (enumDirObj == null) {
enumDirObj = readObject(0, enumDirectionClass);
if (enumDirObj == null) {
return null;
}
}
return Direction.valueOf(((Enum)enumDirObj).name());
return Direction.getByName(((Enum) enumDirObj).name());
}
}
/**
* Get the PlayerDigType enum sent in this packet.
*
* @return Dig Type
*/
public PlayerDigType getDigType() {
if(isVersionLowerThan_v_1_8) {
if (isVersionLowerThan_v_1_8) {
return PlayerDigType.values()[readInt(4)];
}
else {
return PlayerDigType.valueOf(((Enum)readObject(0, digTypeClass)).name());
} else {
return PlayerDigType.valueOf(((Enum) readObject(0, digTypeClass)).name());
}
}
@@ -152,6 +177,6 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
RELEASE_USE_ITEM,
SWAP_HELD_ITEMS,
SWAP_ITEM_WITH_OFFHAND,
WRONG_PACKET
UNKNOWN
}
}
@@ -0,0 +1,101 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.player.Direction;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.jetbrains.annotations.Nullable;
public final class WrappedPacketInBlockPlace extends WrappedPacket {
private static boolean isHigherThan_v_1_8_8, isHigherThan_v_1_7_10;
public WrappedPacketInBlockPlace(final NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
isHigherThan_v_1_8_8 = version.isHigherThan(ServerVersion.v_1_8_8);
isHigherThan_v_1_7_10 = version.isHigherThan(ServerVersion.v_1_7_10);
}
@Nullable
public Direction getDirection() {
if (isHigherThan_v_1_8_8) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
return Direction.getByName(((Enum) blockPlace_1_9.getEnumDirectionObject()).name());
} else if (isHigherThan_v_1_7_10) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
return new Direction((byte) blockPlace_1_8.getFace());
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return new Direction((byte) blockPlace_1_7_10.face);
}
}
public int getX() {
if (isHigherThan_v_1_8_8) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
return blockPlace_1_9.getX();
} else if (isHigherThan_v_1_7_10) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
return blockPlace_1_8.getX();
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.x;
}
}
public int getY() {
if (isHigherThan_v_1_8_8) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
return blockPlace_1_9.getY();
} else if (isHigherThan_v_1_7_10) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
return blockPlace_1_8.getY();
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.y;
}
}
public int getZ() {
if (isHigherThan_v_1_8_8) {
WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(packet);
return blockPlace_1_9.getZ();
} else if (isHigherThan_v_1_7_10) {
WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
return blockPlace_1_8.getZ();
} else {
WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(packet);
return blockPlace_1_7_10.z;
}
}
}
@@ -22,32 +22,27 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
final class WrappedPacketInBlockPlace_1_7_10 extends WrappedPacket {
public int x, y, z;
public ItemStack itemStack;
public int blockFace;
public int face;
WrappedPacketInBlockPlace_1_7_10(final Object packet) {
WrappedPacketInBlockPlace_1_7_10(final NMSPacket packet) {
super(packet);
}
@Override
protected void setup() {
final PacketPlayInBlockPlace blockPlace = (PacketPlayInBlockPlace) packet;
final net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace blockPlace =
(net.minecraft.server.v1_7_R4.PacketPlayInBlockPlace) packet.getRawNMSPacket();
x = blockPlace.c();
y = blockPlace.d();
z = blockPlace.e();
this.blockFace = blockPlace.d();
this.face = blockPlace.d();
net.minecraft.server.v1_7_R4.ItemStack stack = blockPlace.getItemStack();
this.itemStack = org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asBukkitCopy(stack);
@@ -22,10 +22,9 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
import io.github.retrooper.packetevents.exceptions.WrapperFieldNotFoundException;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
@@ -34,41 +33,31 @@ import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
private static Class<?> blockPlaceClass, blockPositionClass, blockPositionSuperClass;
private Object blockPosObj;
WrappedPacketInBlockPlace_1_8(final Object packet) {
WrappedPacketInBlockPlace_1_8(final NMSPacket packet) {
super(packet);
}
protected static void load() {
blockPlaceClass = PacketTypeClasses.Client.BLOCK_PLACE;
try {
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
blockPositionSuperClass = blockPositionClass.getSuperclass();
}
public int getX() {
if(blockPosObj == null) {
blockPosObj = new WrappedPacket(packet).readObject(0, blockPositionClass);
if (blockPosObj == null) {
blockPosObj = readObject(1, NMSUtils.blockPosClass);
}
try {
return (int)Reflection.getMethod(blockPositionSuperClass, "getX", 0).invoke(blockPosObj);
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
public int getY() {
if(blockPosObj == null) {
blockPosObj = new WrappedPacket(packet).readObject(0, blockPositionClass);
if (blockPosObj == null) {
blockPosObj = readObject(1, NMSUtils.blockPosClass);
}
try {
return (int)Reflection.getMethod(blockPositionSuperClass, "getY", 0).invoke(blockPosObj);
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
@@ -76,11 +65,11 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
}
public int getZ() {
if(blockPosObj == null) {
blockPosObj = new WrappedPacket(packet).readObject(0, blockPositionClass);
if (blockPosObj == null) {
blockPosObj = readObject(1, NMSUtils.blockPosClass);
}
try {
return (int)Reflection.getMethod(blockPositionSuperClass, "getZ", 0).invoke(blockPosObj);
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
@@ -90,4 +79,8 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
public ItemStack getItemStack() {
return NMSUtils.toBukkitItemStack(readObject(0, NMSUtils.nmsItemStackClass));
}
public int getFace() {
return readInt(0);
}
}
@@ -0,0 +1,111 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.play.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
import java.lang.reflect.InvocationTargetException;
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
private static Class<?> movingObjectPositionBlockClass;
private Object blockPosObj;
public WrappedPacketInBlockPlace_1_9(final NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
movingObjectPositionBlockClass = NMSUtils.getNMSClassWithoutException("MovingObjectPositionBlock");
}
public int getX() {
if (blockPosObj == null) {
if (movingObjectPositionBlockClass == null) {
blockPosObj = readObject(0, NMSUtils.blockPosClass);
} else {
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
}
}
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getX", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
public int getY() {
if (blockPosObj == null) {
if (movingObjectPositionBlockClass == null) {
blockPosObj = readObject(0, NMSUtils.blockPosClass);
} else {
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
}
}
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getY", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
public int getZ() {
if (blockPosObj == null) {
if (movingObjectPositionBlockClass == null) {
blockPosObj = readObject(0, NMSUtils.blockPosClass);
} else {
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
blockPosObj = movingObjectPosWrapper.readObject(0, NMSUtils.blockPosClass);
}
}
try {
return (int) Reflection.getMethod(blockPosObj.getClass().getSuperclass(), "getZ", 0).invoke(blockPosObj);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
public Object getEnumDirectionObject() {
if (movingObjectPositionBlockClass == null) {
return readObject(0, NMSUtils.enumDirectionClass);
} else {
Object movingObjectPos = readObject(0, movingObjectPositionBlockClass);
WrappedPacket movingObjectPosWrapper = new WrappedPacket(new NMSPacket(movingObjectPos));
return movingObjectPosWrapper.readObject(0, NMSUtils.enumDirectionClass);
}
}
}
@@ -22,12 +22,13 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.chat;
package io.github.retrooper.packetevents.packetwrappers.play.in.chat;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public final class WrappedPacketInChat extends WrappedPacket {
public WrappedPacketInChat(Object packet) {
public WrappedPacketInChat(NMSPacket packet) {
super(packet);
}
@@ -22,9 +22,10 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.clientcommand;
package io.github.retrooper.packetevents.packetwrappers.play.in.clientcommand;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
@@ -33,13 +34,13 @@ public final class WrappedPacketInClientCommand extends WrappedPacket {
private static Class<?> enumClientCommandClass;
private Object enumObj;
public WrappedPacketInClientCommand(Object packet) {
public WrappedPacketInClientCommand(NMSPacket packet) {
super(packet);
}
public static void load() {
Class<?> packetClass = PacketTypeClasses.Client.CLIENT_COMMAND;
@Override
protected void load() {
Class<?> packetClass = PacketTypeClasses.Play.Client.CLIENT_COMMAND;
try {
enumClientCommandClass = NMSUtils.getNMSClass("EnumClientCommand");
} catch (ClassNotFoundException e) {
@@ -54,7 +55,7 @@ public final class WrappedPacketInClientCommand extends WrappedPacket {
* @return ClientCommand
*/
public ClientCommand getClientCommand() {
if(enumObj == null) {
if (enumObj == null) {
enumObj = readObject(0, enumClientCommandClass);
}
return ClientCommand.valueOf(enumObj.toString());
@@ -63,6 +64,8 @@ public final class WrappedPacketInClientCommand extends WrappedPacket {
public enum ClientCommand {
PERFORM_RESPAWN,
REQUEST_STATS,
//This field doesn't exist on 1.16
OPEN_INVENTORY_ACHIEVEMENT
}
@@ -22,20 +22,18 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.out;
package io.github.retrooper.packetevents.packetwrappers.play.in.closewindow;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
//This packet does not exist on 1.7.10
public class WrappedPacketLoginOutSetCompression extends WrappedPacket {
public WrappedPacketLoginOutSetCompression(Object packet) {
public class WrappedPacketInCloseWindow extends WrappedPacket {
public WrappedPacketInCloseWindow(NMSPacket packet) {
super(packet);
}
/**
* Maximum size of a packet before it can be compressed.
*/
public int getThreshold() {
//0 for player inv.
public int getWindowId() {
return readInt(0);
}
}
@@ -22,11 +22,12 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.custompayload;
package io.github.retrooper.packetevents.packetwrappers.play.in.custompayload;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.bytebuf.ByteBufUtil;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
@@ -35,18 +36,19 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
private static boolean strPresent, byteArrayPresent;
public WrappedPacketInCustomPayload(Object packet) {
public WrappedPacketInCustomPayload(NMSPacket packet) {
super(packet);
}
public static void load() {
Class<?> packetClass = PacketTypeClasses.Client.CUSTOM_PAYLOAD;
@Override
protected void load() {
Class<?> packetClass = PacketTypeClasses.Play.Client.CUSTOM_PAYLOAD;
strPresent = Reflection.getField(packetClass, String.class, 0) != null;
byteArrayPresent = Reflection.getField(packetClass, byte[].class, 0) != null;
packetDataSerializerClass = NMSUtils.getNMSClassWithoutException("PacketDataSerializer");
try {
byteBufClass = NMSUtils.getNettyClass("buffer.ByteBuf");
} catch (ClassNotFoundException e) {
} catch (ClassNotFoundException ignored) {
}
try {
@@ -62,7 +64,7 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
return readString(0);
} else {
Object minecraftKey = readObject(0, nmsMinecraftKey);
WrappedPacket minecraftKeyWrapper = new WrappedPacket(minecraftKey);
WrappedPacket minecraftKeyWrapper = new WrappedPacket(new NMSPacket(minecraftKey));
return minecraftKeyWrapper.readString(1);
}
}
@@ -72,11 +74,11 @@ public final class WrappedPacketInCustomPayload extends WrappedPacket {
return readByteArray(0);
} else {
Object dataSerializer = readObject(0, packetDataSerializerClass);
WrappedPacket byteBufWrapper = new WrappedPacket(dataSerializer);
WrappedPacket byteBufWrapper = new WrappedPacket(new NMSPacket(dataSerializer));
Object byteBuf = byteBufWrapper.readObject(0, byteBufClass);
return ByteBufUtil.getBytes(byteBuf);
return PacketEvents.get().getByteBufUtil().getBytes(byteBuf);
}
}
}
@@ -22,24 +22,21 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in;
package io.github.retrooper.packetevents.packetwrappers.play.in.enchantitem;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketLoginHandshake extends WrappedPacket {
public WrappedPacketLoginHandshake(Object packet) {
public class WrappedPacketInEnchantItem extends WrappedPacket {
public WrappedPacketInEnchantItem(NMSPacket packet) {
super(packet);
}
public int getProtocolVersion() {
public int getWindowId() {
return readInt(0);
}
public String getHostName() {
return readString(0);
}
public int getPort() {
public int getButton() {
return readInt(1);
}
}
@@ -22,36 +22,35 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.entityaction;
package io.github.retrooper.packetevents.packetwrappers.play.in.entityaction;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
import org.bukkit.entity.Entity;
import java.util.HashMap;
public final class WrappedPacketInEntityAction extends WrappedPacket {
private static final HashMap<String, PlayerAction> cachedPlayerActionNames = new HashMap<String, PlayerAction>();
private static final HashMap<Integer, PlayerAction> cachedPlayerActionIDs = new HashMap<Integer, PlayerAction>();
@Nullable
private static final HashMap<String, PlayerAction> cachedPlayerActionNames = new HashMap<>();
private static final HashMap<Integer, PlayerAction> cachedPlayerActionIDs = new HashMap<>();
private static Class<?> enumPlayerActionClass;
private static boolean isLowerThan_v_1_8;
private Entity entity;
private int entityId = -1;
private PlayerAction action;
public WrappedPacketInEntityAction(final Object packet) {
public WrappedPacketInEntityAction(final NMSPacket packet) {
super(packet);
}
public static void load() {
Class<?> entityActionClass = NMSUtils.getNMSClassWithoutException("PacketPlayInEntityAction");
@Override
protected void load() {
isLowerThan_v_1_8 = version.isLowerThan(ServerVersion.v_1_8);
if (!isLowerThan_v_1_8) {
enumPlayerActionClass = SubclassUtil.getSubClass(entityActionClass, "EnumPlayerAction");
enumPlayerActionClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.ENTITY_ACTION, "EnumPlayerAction");
}
//All the already existing values
for (PlayerAction val : PlayerAction.values()) {
@@ -71,13 +70,14 @@ public final class WrappedPacketInEntityAction extends WrappedPacket {
cachedPlayerActionIDs.put(7, PlayerAction.OPEN_INVENTORY); //horse interaction
}
/**
* Lookup the associated entity by the ID that was sent in the packet.
*
* @return Entity
*/
public Entity getEntity() {
if(entity == null) {
if (entity == null) {
return entity = NMSUtils.getEntityById(getEntityId());
}
return entity;
@@ -91,10 +91,10 @@ public final class WrappedPacketInEntityAction extends WrappedPacket {
* @return Entity ID
*/
public int getEntityId() {
if(entityId != -1) {
return entityId;
if (entityId == -1) {
entityId = readInt(0);
}
return readInt(0);
return entityId;
}
/**
@@ -22,16 +22,17 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.flying;
package io.github.retrooper.packetevents.packetwrappers.play.in.flying;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInFlying extends WrappedPacket {
public WrappedPacketInFlying(Object packet) {
public WrappedPacketInFlying(NMSPacket packet) {
super(packet);
}
public double getX() {
return readDouble(0);
}
@@ -22,18 +22,19 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.helditemslot;
package io.github.retrooper.packetevents.packetwrappers.play.in.helditemslot;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public final class WrappedPacketInHeldItemSlot extends WrappedPacket {
public WrappedPacketInHeldItemSlot(Object packet) {
public WrappedPacketInHeldItemSlot(NMSPacket packet) {
super(packet);
}
/**
* Get the index of the item we currently have in hand.
*
* @return Item in hand Index
*/
public int getCurrentSelectedSlot() {
@@ -0,0 +1,14 @@
package io.github.retrooper.packetevents.packetwrappers.play.in.itemname;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInItemName extends WrappedPacket {
public WrappedPacketInItemName(NMSPacket packet) {
super(packet);
}
public String getItemName() {
return readString(0);
}
}
@@ -22,38 +22,38 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.keepalive;
package io.github.retrooper.packetevents.packetwrappers.play.in.keepalive;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.reflection.Reflection;
public final class WrappedPacketInKeepAlive extends WrappedPacket {
private static Class<?> packetClass;
private static boolean integerPresentInIndex0;
private long id;
public WrappedPacketInKeepAlive(final Object packet) {
public WrappedPacketInKeepAlive(final NMSPacket packet) {
super(packet);
}
public static void load() {
packetClass = PacketTypeClasses.Client.KEEP_ALIVE;
@Override
protected void load() {
Class<?> packetClass = PacketTypeClasses.Play.Client.KEEP_ALIVE;
integerPresentInIndex0 = Reflection.getField(packetClass, int.class, 0) != null;
}
/**
* Get the ID response from the client.
*
* <p>
* You may cast this down to an int if you are on 1.7.10 - 1.12.2.
* On 1.13.2 - 1.16.3 a long is sent.
*
* @return response ID
*/
public long getId() {
if(!integerPresentInIndex0) {
if (!integerPresentInIndex0) {
return readLong(0);
}
else {
} else {
return readInt(0);
}
}
@@ -0,0 +1,14 @@
package io.github.retrooper.packetevents.packetwrappers.play.in.pickitem;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInPickItem extends WrappedPacket {
public WrappedPacketInPickItem(NMSPacket packet) {
super(packet);
}
public int getSlot() {
return readInt(0);
}
}
@@ -0,0 +1,61 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.play.in.resourcepackstatus;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
import io.github.retrooper.packetevents.utils.server.ServerVersion;
public class WrappedPacketInResourcePackStatus extends WrappedPacket {
private static Class<?> enumResourcePackStatusClass;
public WrappedPacketInResourcePackStatus(NMSPacket packet) {
super(packet);
}
@Override
protected void load() {
enumResourcePackStatusClass = SubclassUtil.getSubClass(PacketTypeClasses.Play.Client.RESOURCE_PACK_STATUS, "EnumResourcePackStatus");
}
public ResourcePackStatus getStatus() {
Object enumObj = readObject(0, enumResourcePackStatusClass);
return ResourcePackStatus.valueOf(enumObj.toString());
}
public enum ResourcePackStatus {
SUCCESSFULLY_LOADED,
DECLINED,
FAILED_DOWNLOAD,
ACCEPTED
}
@Override
public boolean isSupported() {
return version.isHigherThan(ServerVersion.v_1_7_10);
}
}
@@ -0,0 +1,69 @@
/*
* MIT License
*
* Copyright (c) 2020 retrooper
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.play.in.setcreativeslot;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import org.bukkit.inventory.ItemStack;
public class WrappedPacketInSetCreativeSlot extends WrappedPacket {
public WrappedPacketInSetCreativeSlot(final NMSPacket packet) {
super(packet);
}
/**
* Get the clicked slot
*
* @return the slot
*/
public int getSlot() {
return readInt(0);
}
/**
* Set the clicked slot
*
* @param value the slot
*/
public void setSlot(int value) {
writeInt(0, value);
}
/**
* Get the clicked item
*
* @return the clicked item
*/
public ItemStack getClickedItem() {
Object nmsItemStack = readObject(0, NMSUtils.nmsItemStackClass);
return NMSUtils.toBukkitItemStack(nmsItemStack);
}
public void setClickedItem(ItemStack stack) {
write(NMSUtils.nmsItemStackClass, 0, NMSUtils.toNMSItemStack(stack));
}
}
@@ -22,10 +22,9 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.settings;
package io.github.retrooper.packetevents.packetwrappers.play.in.settings;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.packettype.PacketTypeClasses;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
import io.github.retrooper.packetevents.utils.nms.NMSUtils;
import io.github.retrooper.packetevents.utils.reflection.SubclassUtil;
@@ -40,12 +39,12 @@ public class WrappedPacketInSettings extends WrappedPacket {
private Object chatVisibilityEnumObj;
private HashMap<DisplayedSkinPart, Boolean> displayedSkinParts = new HashMap<>();
public WrappedPacketInSettings(final Object packet) {
public WrappedPacketInSettings(final NMSPacket packet) {
super(packet);
}
public static void load() {
Class<?> packetClass = PacketTypeClasses.Client.SETTINGS;
@Override
protected void load() {
isLowerThan_v_1_8 = version.isLowerThan(ServerVersion.v_1_8);
@@ -114,7 +113,6 @@ public class WrappedPacketInSettings extends WrappedPacket {
*
* @return A map with a Skin Parts as a key, and a boolean as a value.
*/
@Nullable
public HashMap<DisplayedSkinPart, Boolean> getDisplayedSkinPartsMap() {
if (displayedSkinParts.isEmpty()) {
if (isLowerThan_v_1_8) {
@@ -146,7 +144,7 @@ public class WrappedPacketInSettings extends WrappedPacket {
* @return Is the skin part enabled
*/
public boolean isDisplaySkinPartEnabled(DisplayedSkinPart part) {
if(displayedSkinParts.isEmpty()) {
if (displayedSkinParts.isEmpty()) {
displayedSkinParts = getDisplayedSkinPartsMap();
}
//1.7.10, we will default the other skin parts to return false.
@@ -22,23 +22,19 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.out.entitymetadata;
package io.github.retrooper.packetevents.packetwrappers.play.in.spectate;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketOutEntityMetadata extends WrappedPacket {
private boolean isListening = false;
private int entityID;
public WrappedPacketOutEntityMetadata(Object packet) {
import java.util.UUID;
public class WrappedPacketInSpectate extends WrappedPacket {
public WrappedPacketInSpectate(NMSPacket packet) {
super(packet);
isListening = true;
}
public int getEntityId() {
if (isListening) {
return readInt(0);
} else {
return entityID;
}
public UUID getUUID() {
return (UUID) readObject(0, UUID.class);
}
}
@@ -22,12 +22,13 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.in.steervehicle;
package io.github.retrooper.packetevents.packetwrappers.play.in.steervehicle;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInSteerVehicle extends WrappedPacket {
public WrappedPacketInSteerVehicle(Object packet) {
public WrappedPacketInSteerVehicle(NMSPacket packet) {
super(packet);
}
@@ -22,20 +22,17 @@
* SOFTWARE.
*/
package io.github.retrooper.packetevents.packetwrappers.login.in;
package io.github.retrooper.packetevents.packetwrappers.play.in.tabcomplete;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrapppedPacketLoginInEncryptionBegin extends WrappedPacket {
public WrapppedPacketLoginInEncryptionBegin(Object packet) {
public class WrappedPacketInTabComplete extends WrappedPacket {
public WrappedPacketInTabComplete(NMSPacket packet) {
super(packet);
}
public byte[] getPublicKey() {
return readByteArray(0);
}
public byte[] getVerifyToken() {
return readByteArray(1);
public String getText() {
return readString(0);
}
}
@@ -0,0 +1,14 @@
package io.github.retrooper.packetevents.packetwrappers.play.in.teleportaccept;
import io.github.retrooper.packetevents.packetwrappers.NMSPacket;
import io.github.retrooper.packetevents.packetwrappers.WrappedPacket;
public class WrappedPacketInTeleportAccept extends WrappedPacket {
public WrappedPacketInTeleportAccept(NMSPacket packet) {
super(packet);
}
public int getTeleportId() {
return readInt(0);
}
}
Loaded 100 of 173 files, more files were not shown because too many files have changed in this diff. Show more