Compare commits

...
127 Commits
Author SHA1 Message Date
purplexdev 07692f87f2 1.3.3 Release STABLE
* EventManager small optimization
* Imports optimized
* Own GameProfile class added
* New wrappers, this version is going to go on spigotmc!
2020-06-17 17:29:51 +02:00
purplexdev 7f94b254a2 LoginInEncryptionBegin & LoginOutEncryptionBegin wrapper added,
LoginStart & LoginStatusPing wrapper added,
Bug fixed with PostPlayerInjectEvent not being called,
Custom GameProfile class coded,
Main example class readded
2020-06-17 13:15:35 +02:00
purplexdev ceb3581c28 PostPlayerInjectEvent not called bug fix! 2020-06-17 11:04:16 +02:00
purplexdev c3bf5d75d3 1.3.2 Release Stable!
* Code cleanup

* Custom NotNull and Nullable annotations added

* Example packages removed, please see https://github.com/retrooper/packetevents-example
2020-06-16 15:38:54 +02:00
purplexdev 297d261ca9 1.3.1.3 Beta
* ClientVersion added isHigherThan(ClientVersion version) and isLowerThan(ClientVersion version) methods for simple client version comparison.

* Packet.isInstanceOf(fatherPacketName, childPacketName) has now been deprecated, will be removed in the next version!

It has been replaced by Packet.isFlyingPacket(nmsPacketObject), as the flying packet is the only packet that has subclasses.
The flying packet is also used a lot, so I made an efficient way to check if the nms packet object is an instanceof of it!
If you are on a 1.9+ server, it will just check if the packet is an instance of "PacketPlayInPosition" or "PacketPlayInPositionLook" or "PacketPlayInLook".
2020-06-16 14:21:05 +02:00
purplexdev 89a67e7ee4 1.3.1.2 Stable!
* All wrapper classes are now FINAL classes as they are not meant to be extended.

* New wrapper class -> WrappedPacketOutKickDisconnect.
You can send this packet to any player if you want to kick them, or even read the message from such a packet.
2020-06-16 13:43:39 +02:00
purplexdev 0d6d34a93b Merge remote-tracking branch 'origin/master' 2020-06-14 13:33:07 +02:00
purplexdev cb89a42184 * plugin.yml removed so Bukkit doesn't detect PacketEvents as a plugin 2020-06-14 13:32:52 +02:00
GladUrBad 6837b1d803 Update README.md
fixed typo
2020-06-13 18:52:45 -05:00
purplexdev 8967babc37 Merge remote-tracking branch 'origin/master' 2020-06-13 18:54:57 +02:00
purplexdev a4f93cfe8d Stable 1.3.0 Release!
Changelog:

* Code cleanup
* PostPlayerInjectEvent not called bug fixed
* PacketEvents.injectPlayer(player)
* PacketEvents.uninjectPlayer(player)
* PacketEvents.hasInjected(player)
* TinyProtocolHandler now accessed statically, we no longer store an instance
2020-06-13 18:54:41 +02:00
retrooper 5dde0b56f8 deprecated github account added 2020-06-13 15:50:59 +02:00
purplexdev 43dee3dfeb Merge remote-tracking branch 'origin/master' 2020-06-13 15:27:40 +02:00
purplexdev 937dbc5c03 1.3.0 Beta!
* PostPlayerInjectEvent added (use this to register your players safely as the PlayerInjectEvent's player object might have some null values)
* PlayerInjectEvent is now cancellable
* Player joining while server is still loading plugins bug should fix afaik, please test it, I am unsure if it is 100% fixed
* ServerReloadEvent.java has been removed
* PacketEvents.start() function only takes in one argument and that is your main plugin's instance.
(If you don't want the server tick task, you may cancel it like this: PacketEvents.getServerTickTask().cancel();)
* Imports optimized
* Random debug messages removed
* More documentation added to the PacketEvents class!
2020-06-13 15:27:28 +02:00
retrooper 78e17c2abb about updated 2020-06-13 15:00:43 +02:00
retrooper 4653dbcaba some info changed and setup guide added 2020-06-13 14:59:50 +02:00
retrooper 057e1b960a added tabs 2020-06-13 08:27:42 +02:00
retrooper 5feaabad92 added tabs 2020-06-13 08:27:37 +02:00
purplexdev 2c395d4313 Merge remote-tracking branch 'origin/master' 2020-06-10 17:56:51 +02:00
purplexdev 6af68cfc7a player.getTargetBlock(null, 3) -> player.getTargetBlock((HashSet<Material>) null, 3) as on some versions of java it doesn't work I believe 2020-06-10 17:56:28 +02:00
retrooper 66f2c371ec updated info 2020-06-10 12:12:12 +02:00
purplexdev c5bcf50d66 Merge remote-tracking branch 'origin/master' 2020-06-10 11:58:55 +02:00
purplexdev 86625694fc 1.2.9.2 stable
* BlockPlace wrapper fixed for 1.8->1.8.8

* Imports optimized

* Server-bound Packet BLOCK_PLACE is no longer initialized at compilation time, its name changes depending on your server version

(On 1.7->1.8 servers it is equal to "PacketPlayInBlockPlace", 1.9+ servers it is equal to "PacketPlayInUseItem"), you can use the WrappedPacketInBlockPlace no matter what version you are running on, PacketEvents takes care of this!

* toBukkitItemStack function added in NMSUtils.java, you can easily convert an NMS itemstack to a bukkit itemstack

* Unneeded BlockFinder class removed, we use player.getTargetBlock(null, range); instead
2020-06-10 11:56:53 +02:00
retrooper dcaae8a15a spigot forks data 2020-06-09 22:07:20 +02:00
retrooper 1996399cde update to readme 2020-06-09 22:03:39 +02:00
retrooper 62d3fdd276 update to readme 2020-06-09 22:03:34 +02:00
purplexdev 7740cf6eae Bug fix, Login packets are no longer calling the client receive function! 2020-06-09 18:40:38 +02:00
purplexdev 5bbaa5d7c2 1.2.9 Fixed bug with the BlockDig event!
You may now use it, and the block place too on legacy versions!
2020-06-08 07:33:13 +02:00
purplexdev 70cb1ad0fb 1.2.9 Beta commit!
* ClientVersion checking added: PacketEvents.getClientVersion(player);

* PacketEvents.currentTimeMS() method renamed to -> PacketEvents.currentCalculatedMS();

* WrappedPacketLoginHandshake wrapper added, you can check protocol version, hostname, and port.

* A few bug fixes and a few classes renamed to avoid import confusing.

* Apparently the block dig wrapper is broken, will be fixed in the next commit!
* Avoid using the block dig wrapper.

* Unused vector classes removed to reduce file size

* Server reload event is not finished yet, but working on it and changed some stuff

* PacketEvents.java now listens to events and stores the protocol version, so you can lookup.

* NMSUtils.getCraftPlayer() function added and some stuff simplified

* I am now using TinyProtocol's Reflection util, it really speeds up wrapper making process and all reflection access so in future versions I might slowly rewrite some wrappers with it

* ClientVersion checking added: PacketEvents.getClientVersion(player);

* PacketEvents.currentTimeMS() method renamed to -> PacketEvents.currentCalculatedMS();

* WrappedPacketLoginHandshake wrapper added, you can check protocol version, hostname, and port.

* A few bug fixes and a few classes renamed to avoid import confusing.

* Apparently the block dig wrapper is broken, will be fixed in the next commit!
* Avoid using the block dig wrapper.

* Unused vector classes removed to reduce file size

* Server reload event is not finished yet, but working on it and changed some stuff

* PacketEvents.java now listens to events and stores the protocol version, so you can lookup.

* NMSUtils.getCraftPlayer() function added and some stuff simplified

* I am now using TinyProtocol's Reflection util, it really speeds up wrapper making process and all reflection access so in future versions I might slowly rewrite some wrappers with it

* This commit has only been tested on a 1.15.2 spigot server, I cannot guarantee it will work for the rest of the versions yet, but it should!

PLEASE DO NOT USE THE RELEASED VERSION 1.2.8! IT DOESN'T WORK AT ALL!
2020-06-07 22:43:47 +02:00
purplexdev fcfc404120 * ClientVersion checking added: PacketEvents.getClientVersion(player);
* PacketEvents.currentTimeMS() method renamed to -> PacketEvents.currentCalculatedMS();

* WrappedPacketLoginHandshake wrapper added, you can check protocol version, hostname, and port.

* A few bug fixes and a few classes renamed to avoid import confusing.

* Apparently the block dig wrapper is broken, will be fixed in the next commit!
* Avoid using the block dig wrapper.

* Unused vector classes removed to reduce file size

* Server reload event is not finished yet, but working on it and changed some stuff

* PacketEvents.java now listens to events and stores the protocol version, so you can lookup.

* NMSUtils.getCraftPlayer() function added and some stuff simplified

* I am now using TinyProtocol's Reflection util, it really speeds up wrapper making process and all reflection access so in future versions I might slowly rewrite some wrappers with it

* ClientVersion checking added: PacketEvents.getClientVersion(player);

* PacketEvents.currentTimeMS() method renamed to -> PacketEvents.currentCalculatedMS();

* WrappedPacketLoginHandshake wrapper added, you can check protocol version, hostname, and port.

* A few bug fixes and a few classes renamed to avoid import confusing.

* Apparently the block dig wrapper is broken, will be fixed in the next commit!
* Avoid using the block dig wrapper.

* Unused vector classes removed to reduce file size

* Server reload event is not finished yet, but working on it and changed some stuff

* PacketEvents.java now listens to events and stores the protocol version, so you can lookup.

* NMSUtils.getCraftPlayer() function added and some stuff simplified

* I am now using TinyProtocol's Reflection util, it really speeds up wrapper making process and all reflection access so in future versions I might slowly rewrite some wrappers with it

* This commit has only been tested on a 1.15.2 spigot server, I cannot guarantee it will work for the rest of the versions yet, but it should!

PLEASE DO NOT USE THE RELEASED VERSION 1.2.8! IT DOESN'T WORK AT ALL!
2020-06-07 22:42:54 +02:00
purplexdev 2f855874a6 Some bug fixes.
Now should work fine on 1.15 spigot forks. (Like tuinity & paperspigot)

Sorry, didn't notice this small bug for a long time.

Handshaking packets are also a thing now so yay!
2020-06-07 20:39:07 +02:00
purplexdev 26d5542864 Some bug fixes.
Now should work fine on 1.15 spigot forks. (Like tuinity & paperspigot)

Sorry, didn't notice this small bug for a long time.

Handshaking packets are also a thing now so yay!
2020-06-07 20:37:12 +02:00
purplexdev ee5e0ef3a7 Random nms import removed,
Handshake packetwrapper added, now possible to check protocol versions,
Random missing classes added(sorry idk why github fails to add these)
2020-06-07 20:04:13 +02:00
purplexdev 51e5cf5c55 Random nms import removed 2020-06-07 19:46:55 +02:00
purplexdev 3c09b8c3a7 * Bug fixes & better organization
Chat packetwrapper now working(sendable),
Working on login wrappers.
2020-06-07 19:45:11 +02:00
purplexdev 6e25876230 Random "success" debugs removed when fixing the last error! 2020-06-07 12:42:15 +02:00
purplexdev c5a3e57974 Merge remote-tracking branch 'origin/master' 2020-06-07 12:31:30 +02:00
purplexdev 508fb5f1e2 Bug fix with initiating Entity Velocity wrapper, accidentally imported and stored an instance of the Vec3D class!
Everything should work fine now!
2020-06-07 12:31:16 +02:00
retrooper e9b6f5ab0f some small changes 2020-06-07 07:55:46 +02:00
purplexdev efb79cc7d2 Merge remote-tracking branch 'origin/master' 2020-06-06 22:14:43 +02:00
purplexdev 901084f1f6 Bug fixes, not sure if stable, for some reason last push didn't go through 2020-06-06 22:14:23 +02:00
retrooper acb4ca7619 release version updated from 1.2.7 to 1.2.8 2020-06-06 16:42:24 +02:00
purplexdev 691684c828 Merge remote-tracking branch 'origin/master' 2020-06-06 16:17:54 +02:00
purplexdev 06482124ce 1.2.8 Release!
1.14 & 1.15 bug fixes!(entity velocity error and api not starting up fixed)

Now fully works on 1.7.10->1.15.2

Stable build!
2020-06-06 16:17:40 +02:00
retrooper d61fda966f updated readme and corrected, also added attribution to tinyprotocol
We changed the License to GPL2, as we are using a modified version of TinyProtcol(which uses GPL2), sublicensing is not allowed with GPL2
2020-06-06 15:23:08 +02:00
purplexdev 63df6cdf80 Merge remote-tracking branch 'origin/master' 2020-06-06 14:55:52 +02:00
purplexdev 3365fb569f * Using a modified version of TinyProtocol
* Multiple bug fixes

* New client-bound sendable wrappers -> EntityVelocity, Animation(containing stuff like ARM swing), Chat.

All the current client bound wrappers can be sent to clients, currently the Chat wrapper cannot be used for listening to packets, will be fixed in the next commit!

sendPacket(Player, Sendable packet) function added in PacketEvents.
2020-06-06 14:55:35 +02:00
retrooper f9c48e488e data updated 2020-06-06 12:46:18 +02:00
retrooper 0c81e0fd54 gpl 2 license because of new update coming 2020-06-06 12:36:14 +02:00
retrooper 0cddca1847 gpl 2 license 2020-06-06 12:35:49 +02:00
retrooper 23574cd075 license updated to gpl 2 2020-06-06 12:32:46 +02:00
purplexdev cc7897752d * EntityVelocity wrapper added
Please only use the velocity wrapper for listening to packets with this build.
I have not tested it for listening to packets though..

What I have tested is sending velocity packets with it doesn't work, hopefully next push we can fix this!
2020-06-05 22:22:18 +02:00
purplexdev dc4dc80bdc Merge remote-tracking branch 'origin/master' 2020-06-05 20:17:47 +02:00
purplexdev 808a7b69d8 1.2.7 release,
Optimizations & bug fixes

* WrappedPacketInUseEntity getHand() null bug, so for now I just removed the getHand() method.

* WrappedPacketInEntityAction added as a couple of you suggested

* Optimization to getting entities by their id(used in use entity and entity action packet)

* After optimizing getEntity, file size has reduced by about 10%
2020-06-05 20:17:00 +02:00
retrooper 5b3b6ff509 jitpack version updated to 1.2.6 and link updated 2020-06-03 16:43:39 +02:00
purplexdev b923e86a91 Merge remote-tracking branch 'origin/master' 2020-06-03 13:43:54 +02:00
purplexdev 2c078dd1d4 Packages moved
io.github.explored.packetevents -> io.github.retrooper.packetevents
2020-06-03 13:43:41 +02:00
retrooper feb80c38b8 username changed 2020-06-03 13:29:16 +02:00
purplexdev b525407ad5 Keep alive packet added 2020-06-03 13:26:13 +02:00
purplexdev b660673743 * Get player ping
PacketEvents.getPing(Player);
2020-06-03 12:17:14 +02:00
purplexdev ba6e7c03fb 1.2.6 Bug fixes!
* Fixed listener not calling events outside of the "onPacket" function in the new
optimized event system!

* pom.xml updated to use new group id

* Registered listener example updated, more documented

This will be the 1.2.6 release build!
2020-06-02 10:22:08 +02:00
purplexdev 50e4b46018 Merge remote-tracking branch 'origin/master' 2020-06-02 09:57:12 +02:00
purplexdev a837bf38b1 Version 1.2.6 out,
* Packages moved from me.purplex.packetevents -> io.github.explored.packetevents
* The event calling has been massively optimized!
* Some unneeded imports have been removed.
2020-06-02 09:56:48 +02:00
explored 6fb102edf9 if link doesnt work 2020-06-01 17:58:31 +02:00
explored e45ed75e91 proper spacing 2020-06-01 17:56:32 +02:00
explored ef6b6b9466 readme details changed
* Changed my username (purplexdev -> explored)

* check out the details on the link specified
2020-06-01 17:55:35 +02:00
explored f6df333304 name changed 2020-05-31 20:33:49 +02:00
purplexdev 83aee85f48 Random debugs removed 2020-05-31 17:45:36 +02:00
purplexdev 73c5a0dfad Random debugs removed,
Now injecting players in PlayerLoginEvent
2020-05-29 13:06:29 +02:00
purplexdev 555c2b86c7 Merge remote-tracking branch 'origin/master' 2020-05-29 12:44:37 +02:00
purplexdev b5fd4b68bf LoginHandshake wrappers removed, BlockPlace added, WrappedPacketInUseEntity getEntity() optimized, to use worldServer.getEntity(ID); (faster) 2020-05-29 12:44:08 +02:00
purplex 3baaa64754 release version updated to 1.2.5 2020-05-28 20:34:22 +02:00
purplexdev e142d95abc attempt because github annoying 2020-05-28 19:53:33 +02:00
purplexdev 6ac93a97df attempt because github annoying 2020-05-28 19:50:57 +02:00
purplexdev 7db7e44bfc channelmanager 2020-05-28 19:48:32 +02:00
purplexdev 4792bda57b listener example commit failure fix 2020-05-28 19:46:12 +02:00
purplexdev cd009e7080 listener example commit failure fix 2020-05-28 19:32:51 +02:00
purplexdev bcc967d72d 1.2.5 Beta out!
Tested on 1.7.10 & 1.8.8, but should work for 1.7.10->1.15.2
Massive code cleanup, massive file size reduction.
Vector utility classes added,
TPS Accessing, All current wrapper classes OPTIMIZED.

Packets not received when relogging BUG FIXED!

New custom enums: Hand, Direction.
2020-05-28 19:16:02 +02:00
purplexdev 913cbf94f4 1.2.4 Update, pretty stable, many bugs fixed and lots of optimizations!
* PacketManager renamed to EventManager
* 1.7.10 player injecting fixed
* Channel handling for injecting players optimized
* Unneeded wrapper classes are not public anymore(unaccessible and your IDE shouldn't recommend them anymore)
* Wrapper classes start with WrappedPacketIn and not WrappedPacketPlayIn to shorten, for example WrappedPacketInAbilities,
* Handshake packet adding attempt but not finished
Next update wrappers and TPS accessing will be optimized!
2020-05-28 08:26:04 +02:00
purplexdev 1941d2c34d useless comments removed, NOT STABLE, 1.2.3 2020-05-26 18:45:55 +02:00
purplexdev 36140fb42b Stackoverflow exception fixed, dumb mistake 2020-05-26 18:39:59 +02:00
purplexdev 91e2668998 1.2.3 Massive beta, lots of code cleanup,
reload event not started,
packetloginevent added,
Not tested, most likely not stable.
2020-05-26 18:36:39 +02:00
purplexdev b6f625b498 Merge remote-tracking branch 'og/master' 2020-05-26 17:51:46 +02:00
purplexdev 0c176aabd2 Crazy package movement, mass code cleanup and working on player version manager 2020-05-26 17:51:23 +02:00
purplexdev 39ec5958e1 Crazy package movement, mass code cleanup and working on player version manager 2020-05-26 17:51:10 +02:00
purplex 6467fece64 no dependencies :) 2020-05-25 21:31:40 +02:00
purplexdev c6a8d5ad84 Massive code cleanup and optimizations for 1.2.2 2020-05-25 21:15:45 +02:00
purplexdev 42b1f2b1a9 1.2.2 PacketEvents cleanup method unnecessary argument removed 2020-05-25 21:07:21 +02:00
purplexdev 208823466c 1.2.2 PacketEvents cleanup method unnecessary argument removed 2020-05-25 21:07:02 +02:00
purplexdev 0c67bfb999 PacketEvents.getCurrentServerTPS() //Easily get current and recent server tps,
Many class packages moved, better package organization.
2020-05-25 21:01:54 +02:00
purplexdev d64e92d84a 1.2.1, ServerTickEvent.java now includes the current tick count and if a second has passed 2020-05-25 20:22:11 +02:00
purplexdev 29ec5f6638 MainExample (main class) better documented! 2020-05-25 19:49:50 +02:00
purplexdev 9d10d5001d Merge remote-tracking branch 'og/master' 2020-05-25 19:18:08 +02:00
purplexdev 834b29f84a testexample top edited 2020-05-25 19:16:41 +02:00
purplex 7787ce9f33 random config file removed 2020-05-25 18:24:38 +02:00
purplexdev 4775e9f815 Merge remote-tracking branch 'og/master' 2020-05-25 18:22:31 +02:00
purplexdev 7764939208 More documentation, tested and working for sure! 2020-05-25 18:22:07 +02:00
purplex 9c331ef630 Set theme jekyll-theme-cayman 2020-05-20 20:59:15 +02:00
purplex 3c3261bd96 Set theme jekyll-theme-architect 2020-05-20 20:57:09 +02:00
purplex f71530a4ee Set theme jekyll-theme-cayman 2020-05-20 20:54:07 +02:00
purplex c9e4f627c8 readme small update 2020-05-20 20:49:21 +02:00
purplex 75a5ec6022 readme small update 2020-05-20 20:49:13 +02:00
purplexdev 366490d7fc Merge remote-tracking branch 'og/master' 2020-05-11 10:42:25 +02:00
purplexdev 9f22bebd3b More understandable examples added and comments added 2020-05-11 10:42:00 +02:00
purplex 35b0e6ccd8 jitpack version updated to 1.1.9 2020-05-07 20:12:31 +02:00
purplexdev 3073342482 1.1.9 update, netty deadlock bug fixed by injecting player asynchronously 2020-05-07 09:28:31 +02:00
purplex e83086fd21 readme version updated
1.1.8 is new update
2020-05-04 17:17:06 +02:00
unknown 9c886d8abb injecting errors fixed 2020-05-04 12:28:29 +02:00
purplex 36b574edda release version updated 2020-05-01 22:18:09 +02:00
unknown 90e490466e Massive code cleanup, multiple 1.9+ bugs fixed, reflection usage is minimalized and optimized! 2020-05-01 14:49:30 +02:00
purplex 2743dafc40 latest stable versions 2020-05-01 09:38:42 +02:00
purplex 7443f3f965 readme updated and highlighted gradle, maven,.... bold 2020-05-01 08:51:03 +02:00
purplex 5e493a386c license tag part removed 2020-05-01 08:47:26 +02:00
purplex 321b306a34 gpl3 license badge update 2020-05-01 08:47:04 +02:00
purplex 08996c3e17 gpl3 badge added 2020-05-01 08:46:09 +02:00
purplex 39fc28def6 readme text updated 2020-04-30 20:53:56 +02:00
purplex c2b0109820 readme text updated 2020-04-30 11:22:38 +02:00
purplex 86dbca109b jitpack.io badge repositioned 2020-04-30 11:21:59 +02:00
purplex 904a9c458d jitpack.io badge 2020-04-30 11:21:30 +02:00
unknown 36431251c0 bug fix, unregistered testexample 2020-04-30 11:16:38 +02:00
purplex d51eb9b11e release version updated to 1.1.5, name added in title 2020-04-30 11:09:56 +02:00
unknown 9af0183a04 Flying, position, position_look wrapper added, further optimizations, various bugs fixed, imports changed, event system cleaned up 2020-04-30 11:08:20 +02:00
unknown 92cc803207 Merge branch 'master' of https://github.com/purplexdev/packetevents 2020-04-29 10:24:02 +02:00
unknown d5b693fcc4 1.7.10 support added, abilities, block_dig packet added, use_entity packet optimized 2020-04-29 10:23:51 +02:00
purplex 26a4b57915 license updated to GNU general public v3 2020-04-28 14:44:00 +02:00
purplex 56b3217cf7 tinyprotocol dependency removed 2020-04-28 14:41:38 +02:00
purplex c205f07fa3 gradle, maven,.... version updated to 1.1.3 2020-04-28 14:37:37 +02:00
88 changed files with 4720 additions and 1633 deletions

No files matched your search

+16 -53
View File
@@ -1,65 +1,28 @@
# PacketEvents
Listen to minecraft packets and send minecraft packets.
# packetevents by retrooper
Credit to TinyProtocol
A lightweight spigot packetlistener & packetsender coded by retrooper.
PacketEvents coded by purplex.
## Credit:
Coding help discord server: https://discord.gg/ZWTkg4v
PacketEvents uses a modified version of [TinyProtocol](http://github.com/dmulloy2/ProtocolLib/blob/master/TinyProtocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java) by [@DeprecatedLuke](https://github.com/DeprecatedLuke) to support 1.7.10 & 1.8.
I modified DeprecatedLuke's version of TinyProtocol and added support for 1.9+ versions.
Examples can be found at
me/purplex/packetevents/example/TestExample.java
PacketEvents also took Atlas' Packet class.(all the packet names)
# Gradle
## About
```gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
This packetlistener is **only** supported on spigot servers and has been tested to work on these spigot forks: PaperSpigot, Tuinity
dependencies {
implementation 'com.github.purplexdev:packetevents:1.0.9'
}
```
* No dependencies
* Licensed under the GPL2 license.
# Maven
```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.purplexdev</groupId>
<artifactId>packetevents</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
```
# sbt
```
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.purplexdev" % "packetevents" % "1.0.9"
```
# leiningen
```
:repositories [["jitpack" "https://jitpack.io"]]
:dependencies [[com.github.purplexdev/packetevents "1.0.9"]]
```
[![](https://img.shields.io/badge/License-GPLv2-blue.svg)](https://www.gnu.org/licenses/gpl-2.0)
Join my discord server(to talk to me): https://discord.gg/ZWTkg4v
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
To learn how to setup this API please click on the link below
[Setup Guide](https://github.com/retrooper/packetevents/wiki/PacketEvents-Setup-Guide)
(or just paste this into your browser: https://github.com/retrooper/packetevents/wiki/PacketEvents-Setup-Guide)
+9 -12
View File
@@ -4,11 +4,11 @@
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>me.purplex</groupId>
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.1.2</version>
<version>1.3.3</version>
<packaging>jar</packaging>
<name>PacketEvents</name>
<name>packetevents</name>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -56,7 +56,6 @@
<id>funkemunky-releases</id>
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
</repository>
</repositories>
@@ -103,6 +102,12 @@
<version>1.13.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.7.10</artifactId>
<version>1.7.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.8</artifactId>
@@ -175,13 +180,5 @@
<version>1.14</version>
<scope>provided</scope>
</dependency>
<!--Bukkit-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,280 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.annotations.PacketHandler;
import io.github.retrooper.packetevents.enums.ClientVersion;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.event.manager.EventManager;
import io.github.retrooper.packetevents.handler.TinyProtocolHandler;
import io.github.retrooper.packetevents.packet.Packet;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.login.WrappedPacketLoginHandshake;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
public final class PacketEvents implements PacketListener, Listener {
/*
* Wrappers TODO:
* Spawn entity
*/
private static boolean hasRegistered;
private static final ServerVersion version = ServerVersion.getVersion();
private static PacketEvents instance;
private static final EventManager eventManager = new EventManager();
private static int currentTick;
private static BukkitTask serverTickTask;
private static final HashMap<Object, ClientVersion> clientVersionLookup = new HashMap<Object, ClientVersion>();
public static EventManager getEventManager() {
return eventManager;
}
/**
* Starts the server tick task and initiates the TinyProtocolHandler
*
* @param plugin
*/
public static void start(final Plugin plugin) {
if (!hasRegistered) {
//Register Bukkit and PacketListener
getEventManager().registerListener(getInstance());
Bukkit.getPluginManager().registerEvents(getInstance(), plugin);
//Initialize the TinyProtocolHandler
TinyProtocolHandler.initTinyProtocol(plugin);
//Start the server tick task
final Runnable tickRunnable = new Runnable() {
@Override
public void run() {
getEventManager().callEvent(new ServerTickEvent(currentTick++, PacketEvents.currentCalculatedMS()));
}
};
serverTickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, tickRunnable, 0L, 1L);
hasRegistered = true;
}
}
/**
* Stop all tasks and unregisters all packetevent listeners
*/
public static void stop() {
if (serverTickTask != null) {
serverTickTask.cancel();
}
getEventManager().unregisterAllListeners();
}
/**
* Get the server's version
*
* @return version
*/
public static ServerVersion getServerVersion() {
return version;
}
/**
* Returns the server tick task, you may cancel it if you wish.
* To cancel it do PacketEvents.getServerTickTask().cancel();
* <p>
* This bukkit task runs asynchronously every tick and is started in the start(plugin) function
*
* @return serverTickTask
*/
public static BukkitTask getServerTickTask() {
return serverTickTask;
}
/**
* Get an instance of the PacketEvents API class
*
* @return instance
*/
public static PacketEvents getInstance() {
return instance == null ? instance = new PacketEvents() : instance;
}
/**
* Get the server's recent TPS values
* TPS stands for ticks per second.
* Learn more about ticks <a href="https://apexminecrafthosting.com/what-is-minecraft-tps/">"https://apexminecrafthosting.com/what-is-minecraft-tps/"</a>
*
* @return recentTPS[]
*/
public static double[] getRecentServerTPS() {
double[] tpsArray = new double[0];
try {
tpsArray = NMSUtils.recentTPS();
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return tpsArray;
}
/**
* Get the server's current TPS
* TPS stands for ticks per second.
* Learn more about ticks <a href="https://apexminecrafthosting.com/what-is-minecraft-tps/">"https://apexminecrafthosting.com/what-is-minecraft-tps/"</a>
*
* @return currentTPS / recentTPS[0]
*/
public static double getCurrentServerTPS() {
return getRecentServerTPS()[0];
}
/**
* Get the player's ping.
* Learn more about ping <a href="https://en.wikipedia.org/wiki/Ping_(networking_utility)">https://en.wikipedia.org/wiki/Ping_(networking_utility)</a>
*
* @param player
* @return ping
*/
public static int getPing(final Player player) {
return NMSUtils.getPlayerPing(player);
}
/**
* Should I use this over System.currentTimeMillis()?
* <p>
* 1. System.currentTimeMillis() isn't supported on all machines
* 2. This is way more accurate than System.currentTimeMillis()
* 3. System.currentTimeMillis() can be up to 50ms off, depending on the operating system.
*
* @return nanoTime / 1 million
*/
public static long currentCalculatedMS() {
return System.nanoTime() / 1000000;
}
/**
* Get the player's version.
* Do not call this method in the PlayerInjectEvent, it is safe to call it in the PostPlayerInjectEvent.
* The EntityPlayer object is null at that time, resulting in the version lookup to fail.
*
* @param player
* @return ClientVersion
*/
@Nullable
public static ClientVersion getClientVersion(final Player player) {
final Object channel = TinyProtocolHandler.getPlayerChannel(player);
return clientVersionLookup.get(channel);
}
/**
* Get the players' client version
* Do not call this method in the PlayerInjectEvent, it is safe to call it in the PostPlayerInjectEvent.
* The EntityPlayer object is null at that time, resulting in the version lookup to fail.
*
* @param channel
* @return ClientVersion
*/
@Nullable
public static ClientVersion getClientVersion(final Object channel) {
return clientVersionLookup.get(channel);
}
@PacketHandler
public void onLogin(final PacketLoginEvent e) {
if (e.getPacketName().equals(Packet.Login.HANDSHAKE)) {
final WrappedPacketLoginHandshake handshake = new WrappedPacketLoginHandshake(e.getPacket());
final ClientVersion clientVersion = ClientVersion.fromProtocolVersion(handshake.getProtocolVersion());
clientVersionLookup.put(e.getNettyChannel(), clientVersion);
}
}
@PacketHandler
public void onPacket(final PacketEvent e) {
if(e instanceof PacketReceiveEvent) {
// System.out.println("RECEIVED");
}
}
/**
* Do not check the client version in or before the PlayerInjectEvent, use the PostPlayerInjectEvent.
* It is not recommended to do much in the PlayerInjectEvent, as some fields in the Player object are be null.
* Use the PostPlayerInjectEvent which is only called after the PlayerJoinEvent if the player was injected.
*
* @param e
*/
@PacketHandler
public void onInject(final PlayerInjectEvent e) {
final String username = e.getPlayer().getName();
}
/**
* Called after the PlayerJoinEvent ONLY if the player has been injected!
*
* @param e
*/
@PacketHandler
public void onPostInject(final PostPlayerInjectEvent e) {
//It is safe to get his client version in here.
final ClientVersion clientVersion = PacketEvents.getClientVersion(e.getPlayer());
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
if (hasInjected(e.getPlayer())) {
PacketEvents.getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer()));
}
}
/**
* Version independent player injection
* @param player
*/
public static void injectPlayer(final Player player) {
TinyProtocolHandler.inject(player);
}
/**
* Version independant player injection
*
* @param player
*/
public static void uninjectPlayer(final Player player) {
TinyProtocolHandler.uninject(player);
}
/**
* Returns whether we have injected the player
*
* @param player
* @return hasInjected
*/
public static boolean hasInjected(final Player player) {
return TinyProtocolHandler.hasInjected(player);
}
/**
* Send a wrapped sendable packet to a player
*
* @param player
* @param sendable
*/
public static void sendPacket(final Player player, final Sendable sendable) {
NMSUtils.sendSendableWrapper(player, sendable);
}
}
@@ -0,0 +1,15 @@
package io.github.retrooper.packetevents.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Is for sure not null.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Could be null.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Nullable {
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.events.handler;
package io.github.retrooper.packetevents.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -7,6 +7,11 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
/**
* Just like Bukkit's @EventHandler, but for packets.
* Make sure your class implements the PacketListener interface, and is registered!
*/
public @interface PacketHandler {
}
@@ -0,0 +1,98 @@
package io.github.retrooper.packetevents.enums;
public enum ClientVersion {
LESS_THAN_V_1_7_10, v_1_7_10, v_1_8, v_1_9, v_1_9_1, v_1_9_2, v_1_9_3, v_1_10, v_1_11, v_1_11_1, v_1_12, v_1_12_1, v_1_12_2,
v_1_13, v_1_13_1, v_1_13_2, v_1_14, v_1_14_1, v_1_14_2, v_1_14_3, v_1_14_4, v_1_15, v_1_15_1, v_1_15_2, HIGHER_THAN_V_1_15_2, INVALID;
public static ClientVersion fromProtocolVersion(final int protocolVersion) {
int remainder = -1;
switch (protocolVersion) {
case 1:
case 2:
case 3:
case 4:
return LESS_THAN_V_1_7_10;
case 47://ranging from 1.8->1.8.9
return v_1_8;
case 107:
return v_1_9;
case 108:
return v_1_9_1;
case 109:
return v_1_9_2;
case 110:
return v_1_9_3; //can be 1.9.3 or 1.9.4
case 210:
return v_1_10; //could be 1.10,1.10.1, 1.10.2
case 315:
return v_1_11;
case 316: //could be 11.1 or 11.2
return v_1_11_1;
case 335:
return v_1_12;
case 338:
return v_1_12_1;
case 340:
return v_1_12_2;
case 393:
return v_1_13;
case 401:
return v_1_13_1;
case 404:
return v_1_13_2;
case 477:
return v_1_14;
case 480:
return v_1_14_1;
case 485:
return v_1_14_2;
case 490:
return v_1_14_3;
case 498:
return v_1_14_4;
case 573:
return v_1_15;
case 575:
return v_1_15_1;
case 578:
return v_1_15_2;
default:
remainder = protocolVersion;
}
if(remainder > 578) {
return HIGHER_THAN_V_1_15_2;
}
return INVALID;
}
/**
* Returns if the client's version is more up to date than the argument passed version
*
* @param version
* @return
*/
public boolean isHigherThan(final ClientVersion version) {
if (this == version) return false;
return !isLowerThan(version);
}
/**
* Returns if the client's version is more outdated than the argument passed version
* @param version
* @return
*/
public boolean isLowerThan(final ClientVersion version) {
if(version == this) return false;
byte len = (byte) values().length;
for (byte i = 0; i < len; i++) {
final ClientVersion v = values()[i];
if(v == this) {
return true;
}
else if(v == version) {
return false;
}
}
return false;
}
}
@@ -0,0 +1,17 @@
package io.github.retrooper.packetevents.enums;
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;
public static Direction get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,19 @@
package io.github.retrooper.packetevents.enums;
public enum EntityAnimationType {
SWING_MAIN_ARM, DAMAGE, LEAVE_BED, SWING_OFFHAND, CRITICAL_EFFECT, MAGIC_CRITICAL_EFFECT;
public static final EntityAnimationType get(final int i) {
return values()[i];
}
public final int getIndex() {
for(int i = 0; i < values().length; i++) {
final EntityAnimationType curType = values()[0];
if(curType == this) {
return i;
}
}
return -1;
}
}
@@ -0,0 +1,9 @@
package io.github.retrooper.packetevents.enums;
public enum EntityUseAction {
INTERACT, INTERACT_AT, ATTACK, INVALID;
public static EntityUseAction get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,6 @@
package io.github.retrooper.packetevents.enums;
public enum Hand {
MAIN_HAND,
OFF_HAND;
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.enums;
package io.github.retrooper.packetevents.enums;
public enum PlayerAction {
START_SNEAKING,
@@ -18,4 +18,8 @@ public enum PlayerAction {
OPEN_INVENTORY,
START_FALL_FLYING;
public static PlayerAction get(final byte i) {
return values()[i];
}
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.enums;
package io.github.retrooper.packetevents.enums;
public enum PlayerDigType {
@@ -18,6 +18,7 @@ public enum PlayerDigType {
WRONG_PACKET;
public static PlayerDigType get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,71 @@
package io.github.retrooper.packetevents.enums;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
public enum ServerVersion {
v_1_7_10, v_1_8, v_1_8_3, v_1_8_8, v_1_9, v_1_9_4, v_1_10, v_1_11, v_1_12, v_1_13, v_1_13_2, v_1_14, v_1_15,
ERROR;
public static ServerVersion getVersion() {
ServerVersion[] vals = values();
ArrayUtils.reverse(vals);
for (ServerVersion val : vals) {
String valName = val.name().substring(2).replace("_", ".");
if (Bukkit.getBukkitVersion().contains(valName)) {
return val;
}
}
return ERROR;
}
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static String getNmsSuffix() {
return nmsVersionSuffix;
}
public static String getNMSDirectory() {
return "net.minecraft.server." + nmsVersionSuffix;
}
public static String getOBCDirectory() {
return "org.bukkit.craftbukkit." + getNmsSuffix();
}
/**
* Returns if the current version is more up to date than the argument passed version
*
* @param version
* @return
*/
public boolean isHigherThan(final ServerVersion version) {
if (this == version) return false;
return !isLowerThan(version);
}
/**
* Returns if the current version is more outdated than the argument passed version
*
* @param version
* @return
*/
public boolean isLowerThan(final ServerVersion version) {
if(version == this) return false;
byte len = (byte) values().length;
for (byte i = 0; i < len; i++) {
final ServerVersion v = values()[i];
if(v == this) {
return true;
}
else if(v == version) {
return false;
}
}
return false;
}
}
@@ -0,0 +1,22 @@
package io.github.retrooper.packetevents.event;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
/**
* Incoming and sent packets are called asynchronously,
* recommended to avoid non thread safe bukkit operations
*/
public class PacketEvent {
protected long timestamp = PacketEvents.currentCalculatedMS();
protected static ServerVersion version = PacketEvents.getServerVersion();
/**
* Timestamp of the packet
* @return
*/
public long getTimestamp() {
return timestamp;
}
}
@@ -0,0 +1,4 @@
package io.github.retrooper.packetevents.event;
public interface PacketListener {
}
@@ -0,0 +1,26 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
public final class PacketLoginEvent extends PacketEvent {
private final Object channel;
private final String name;
private final Object packet;
public PacketLoginEvent(final Object channel, final String packetName, final Object packet) {
this.channel =channel;
this.name = packetName;
this.packet = packet;
}
public Object getNettyChannel() {
return channel;
}
public String getPacketName() {
return name;
}
public Object getPacket() {
return packet;
}
}
@@ -1,26 +1,18 @@
package me.purplex.packetevents.events.packetevent;
package io.github.retrooper.packetevents.event.impl;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.PacketEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PacketReceiveEvent extends PacketEvent {
public final class PacketReceiveEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
private final long timestamp;
private boolean cancelled;
public final ServerVersion version;
public PacketReceiveEvent(Player player, String packetName, Object packet) {
this.version = PacketEvents.getServerVersion();
public PacketReceiveEvent(final Player player, final String packetName, final Object packet) {
this.player = player;
this.name = packetName;
this.packet = packet;
this.timestamp = (System.nanoTime() / 1000000);
this.cancelled = false;
}
/**
@@ -50,15 +42,6 @@ public class PacketReceiveEvent extends PacketEvent {
return this.packet;
}
/**
* The time the packet was received(ms)
*
* @return
*/
public long getTimestamp() {
return timestamp;
}
/**
* Cancel the packet
*
@@ -0,0 +1,47 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public final class PacketSendEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
private boolean cancelled;
public PacketSendEvent(final Player player, final String packetName, final Object packet) {
this.player = player;
this.name = packetName;
this.packet = packet;
this.cancelled = false;
}
public Player getPlayer() {
return this.player;
}
public String getPacketName() {
return this.name;
}
/**
* Get the raw packet object
*
* @return nmsPacket
*/
public Object getPacket() {
return this.packet;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public boolean isCancelled() {
return cancelled;
}
}
@@ -0,0 +1,28 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public final class PlayerInjectEvent extends PacketEvent {
private final Player player;
private boolean cancelled;
public PlayerInjectEvent(final Player player) {
this.player = player;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public void cancel() {
setCancelled(true);
}
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public final class PlayerUninjectEvent extends PacketEvent {
private final Player player;
public PlayerUninjectEvent(final Player player) {
this.player =player;
}
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public final class PostPlayerInjectEvent extends PacketEvent {
private final Player player;
public PostPlayerInjectEvent(final Player player) {
this.player = player;
}
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,32 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
public final class ServerTickEvent extends PacketEvent {
private final int tick;
private final double tps;
public ServerTickEvent(final int tick, final long timestamp) {
this.tick = tick;
this.timestamp = timestamp;
this.tps = PacketEvents.getCurrentServerTPS();
}
public ServerTickEvent(final int tick) {
this.tick = tick;
this.tps = PacketEvents.getCurrentServerTPS();
}
public long getTimestamp() {
return timestamp;
}
public int getCurrentTick() {
return tick;
}
public double getCurrentServerTPS() {
return tps;
}
}
@@ -0,0 +1,63 @@
package io.github.retrooper.packetevents.event.manager;
import io.github.retrooper.packetevents.annotations.PacketHandler;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public final class EventManager {
private HashMap<PacketListener, List<Method>> registeredMethods = new HashMap<PacketListener, List<Method>>();
public void callEvent(final PacketEvent e) {
for (final PacketListener listener : registeredMethods.keySet()) {
//Annotated methods
final List<Method> methods = registeredMethods.get(listener);
for (final Method method : methods) {
final Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(e)) {
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
}
}
public void registerListener(final PacketListener e) {
if (registeredMethods.containsKey(e)) {
return;
}
final List<Method> methods = new ArrayList<Method>();
for (final Method m : e.getClass().getMethods()) {
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
if (!methods.isEmpty()) {
registeredMethods.put(e, methods);
}
}
public void unregisterListener(final PacketListener e) {
registeredMethods.remove(e);
}
public void unregisterAllListeners() {
registeredMethods.clear();
}
public boolean hasRegistered(final PacketListener listener) {
return registeredMethods.containsKey(listener);
}
}
@@ -0,0 +1,17 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin {
@Override
public void onEnable() {
PacketEvents.start(this);
}
@Override
public void onDisable() {
PacketEvents.stop();
}
}
@@ -0,0 +1,92 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public final class TinyProtocolHandler {
private static final ServerVersion version = PacketEvents.getServerVersion();
private static Object tinyProtocol;
public static void initTinyProtocol(final Plugin plugin) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
TinyProtocolHandler_1_7 tiny = new TinyProtocolHandler_1_7(plugin);
tiny.initTinyProtocol();
tinyProtocol = tiny;
} else {
TinyProtocolHandler_1_8 tiny = new TinyProtocolHandler_1_8(plugin);
tiny.initTinyProtocol();
tinyProtocol = tiny;
}
}
public static boolean hasInjected(final Player player) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
assert tiny.tinyProtocol != null;
return tiny.tinyProtocol.hasInjected(player);
} else {
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
assert tiny.tinyProtocol != null;
return tiny.tinyProtocol.hasInjected(player);
}
}
public static void inject(final Player player) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
assert tiny.tinyProtocol != null;
tiny.tinyProtocol.injectPlayer(player);
} else {
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
assert tiny.tinyProtocol != null;
tiny.tinyProtocol.injectPlayer(player);
}
}
public static void uninject(final Player player) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
assert tiny.tinyProtocol != null;
tiny.tinyProtocol.uninjectPlayer(player);
} else {
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
assert tiny.tinyProtocol != null;
tiny.tinyProtocol.uninjectPlayer(player);
}
}
public static Object getPlayerChannel(final Player player) {
final Object entityPlayer = NMSUtils.getEntityPlayer(player);
final Object playerConnection = playerConnectionAccessor.get(entityPlayer);
final Object networkManager = networkManagerAccessor.get(playerConnection);
return nettyChannelAccessor.get(networkManager);
}
private static Class<?> networkManagerClass;
private static final FieldAccessor<?> playerConnectionAccessor, networkManagerAccessor, nettyChannelAccessor;
private static Class<?> channelClass;
static {
try {
networkManagerClass = NMSUtils.getNMSClass("NetworkManager");
channelClass = NMSUtils.getNettyClass("channel.Channel");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
playerConnectionAccessor = Reflection.getField(NMSUtils.entityPlayerClass, NMSUtils.playerConnectionClass, 0);
networkManagerAccessor = Reflection.getField(NMSUtils.playerConnectionClass, networkManagerClass, 0);
nettyChannelAccessor = Reflection.getField(networkManagerClass, channelClass, 0);
}
}
@@ -0,0 +1,59 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.event.impl.PacketLoginEvent;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.packet.Packet;
import io.github.retrooper.packetevents.tinyprotocol.TinyProtocol7;
import net.minecraft.util.io.netty.channel.Channel;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public final class TinyProtocolHandler_1_7 {
private final Plugin plugin;
public TinyProtocolHandler_1_7(final Plugin plugin) {
this.plugin = plugin;
}
@Nullable
public TinyProtocol7 tinyProtocol;
public void initTinyProtocol() {
tinyProtocol = new TinyProtocol7(getPlugin()) {
@Override
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
final String packetName = packet.getClass().getSimpleName();
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
PacketEvents.getEventManager().callEvent(packetSendEvent);
if (!packetSendEvent.isCancelled()) {
return packet;
}
return null;
}
@Override
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
final String packetName = packet.getClass().getSimpleName();
for(final String loginPacket : Packet.Login.LOGIN_PACKETS) {
if(packetName.equals(loginPacket)) {
PacketEvents.getEventManager().callEvent(new PacketLoginEvent(channel, packetName, packet));
return packet;
}
}
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
if (!packetReceiveEvent.isCancelled()) {
return packet;
}
return null;
}
};
}
public Plugin getPlugin() {
return plugin;
}
}
@@ -0,0 +1,84 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.event.impl.PacketLoginEvent;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.packet.Packet;
import io.github.retrooper.packetevents.tinyprotocol.TinyProtocol8;
import io.netty.channel.Channel;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public final class TinyProtocolHandler_1_8 {
private static final ServerVersion version = PacketEvents.getServerVersion();
private final Plugin plugin;
public TinyProtocolHandler_1_8(final Plugin plugin) {
this.plugin = plugin;
}
@Nullable
public TinyProtocol8 tinyProtocol;
public void initTinyProtocol() {
tinyProtocol = new TinyProtocol8(getPlugin()) {
@Override
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
final String packetName = packet.getClass().getSimpleName();
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
PacketEvents.getEventManager().callEvent(packetSendEvent);
if (!packetSendEvent.isCancelled()) {
return packet;
}
return null;
}
@Override
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
final String packetName = packet.getClass().getSimpleName();
for (final String loginPacket : Packet.Login.LOGIN_PACKETS) {
if (packetName.equals(loginPacket)) {
PacketEvents.getEventManager().callEvent(new PacketLoginEvent(channel, packetName, packet));
return packet;
}
}
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
if (!packetReceiveEvent.isCancelled()) {
return packet;
}
return null;
}
};
}
public static String getNetworkManagersFieldName() {
//1.8
if (version.equals(ServerVersion.v_1_8)) {
return "g";
}
//1.8.3->1.12
else if (version.isLowerThan(ServerVersion.v_1_13)) {
return "h";
}
//1.13->1.14
else if (version.isLowerThan(ServerVersion.v_1_15)) {
return "g";
}
//1.15
else {
return "listeningChannels";
}
}
public Plugin getPlugin() {
return plugin;
}
}
@@ -0,0 +1,90 @@
package io.github.retrooper.packetevents.mojang;
import com.mojang.authlib.properties.PropertyMap;
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.StringUtils;
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.UUID;
public class GameProfile {
private final UUID id;
private final String name;
private final PropertyMap properties = new PropertyMap();
private boolean legacy;
public GameProfile(UUID id, String name) {
if (id == null && StringUtils.isBlank(name)) {
throw new IllegalArgumentException("Name and ID cannot both be blank");
} else {
this.id = id;
this.name = name;
}
}
public UUID getId() {
return this.id;
}
public String getName() {
return this.name;
}
public PropertyMap getProperties() {
return this.properties;
}
public boolean isComplete() {
return this.id != null && StringUtils.isNotBlank(this.getName());
}
public boolean equalsMojangGameProfile(com.mojang.authlib.GameProfile profile) {
if (profile != null) {
if (profile.getId() != null && getId() != null && profile.getId() == getId()
&& profile.getName() != null && getName() != null && profile.getName().equals(getName())) {
return true;
}
}
return false;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
GameProfile that = (GameProfile) o;
if (this.id != null) {
if (!this.id.equals(that.id)) {
return false;
}
} else if (that.id != null) {
return false;
}
if (this.name != null) {
if (this.name.equals(that.name)) {
return true;
}
} else if (that.name == null) {
return true;
}
return false;
} else {
return false;
}
}
public int hashCode() {
int result = this.id != null ? this.id.hashCode() : 0;
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
return result;
}
public String toString() {
return (new ToStringBuilder(this)).append("id", this.id).append("name", this.name).append("properties", this.properties).append("legacy", this.legacy).toString();
}
public boolean isLegacy() {
return this.legacy;
}
}
@@ -0,0 +1,136 @@
package io.github.retrooper.packetevents.packet;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.utils.NMSUtils;
public abstract class Packet {
public static class Client {
private static final String c = "PacketPlayIn";
@Deprecated
public static final String FLYING = c + "Flying";
public static final String POSITION = c + "Position";
public static final String POSITION_LOOK = c + "PositionLook";
public static final String LOOK = c + "Look";
public static final String CLIENT_COMMAND = c + "ClientCommand";
public static final String TRANSACTION = c + "Transaction";
public static final String BLOCK_DIG = c + "BlockDig";
public static final String ENTITY_ACTION = c + "EntityAction";
public static final String USE_ENTITY = c + "UseEntity";
public static final String WINDOW_CLICK = c + "WindowClick";
public static final String STEER_VEHICLE = c + "SteerVehicle";
public static final String CUSTOM_PAYLOAD = c + "CustomPayload";
public static final String ARM_ANIMATION = c + "ArmAnimation";
/**
* The packet name of the block place depending on your server version, "PacketPlayInBlockPlace" or "PacketPlayInUseItem"
*/
public static final String BLOCK_PLACE = c + ((ServerVersion.getVersion().isHigherThan(ServerVersion.v_1_8_8)) ? "UseItem" : "BlockPlace");
public static final String ABILITIES = c + "Abilities";
public static final String HELD_ITEM_SLOT = c + "HeldItemSlot";
public static final String CLOSE_WINDOW = c + "CloseWindow";
public static final String TAB_COMPLETE = c + "TabComplete";
public static final String CHAT = c + "Chat";
public static final String SET_CREATIVE_SLOT = c + "SetCreativeSlot";
public static final String KEEP_ALIVE = c + "KeepAlive";
}
public static class Server {
private static final String s = "PacketPlayOut";
public static final String ANIMATION = s + "Animation";
public static final String KEEP_ALIVE = s + "KeepAlive";
public static final String CHAT = s + "Chat";
public static final String POSITION = s + "Position";
public static final String TRANSACTION = s + "Transaction";
public static final String NAMED_ENTITY_SPAWN = s + "NamedEntitySpawn";
public static final String SPAWN_ENTITY_LIVING = s + "SpawnEntityLiving";
public static final String SPAWN_ENTITY = s + "SpawnEntity";
public static final String CUSTOM_PAYLOAD = s + "CustomPayload";
public static final String ABILITIES = s + "Abilities";
public static final String ENTITY_METADATA = s + "EntityMetadata";
public static final String ENTITY_VELOCITY = s + "EntityVelocity";
public static final String ENTITY_DESTROY = s + "EntityDestroy";
public static final String ENTITY_HEAD_ROTATION = s + "EntityHeadRotation";
public static final String BLOCK_CHANGE = s + "BlockChange";
public static final String CLOSE_WINDOW = s + "CloseWindow";
public static final String HELD_ITEM_SLOT = s + "HeldItemSlot";
public static final String TAB_COMPLETE = s + "TabComplete";
public static final String RESPAWN = s + "Respawn";
public static final String WORLD_PARTICLES = s + "WorldParticles";
public static final String COMMANDS = s + "Commands";
public static final String OPEN_WINDOW = s + "OpenWindow";
public static final String LOGIN = s + "Login";
public static final String SERVER_DIFFICULTY = s + "ServerDifficulty";
}
public static class Login {
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
public static final String PING = "PacketStatusInPing";
public static final String START = "PacketStatusInStart";
public static final String SUCCESS = "PacketLoginOutSuccess";
public static final String ENCRYPTION_BEGIN_IN = "PacketLoginInEncryptionBegin";
public static final String ENCRYPTION_BEGIN_OUT = "PacketLoginOutEncryptionBegin";
public static final String[] LOGIN_PACKETS = new String[]{"PacketHandshakingInSetProtocol", "PacketLoginInStart", "PacketLoginInEncryptionBegin"};
}
/**
* Is this NMS packet an instanceof the "PacketPlayInFlying" packet in the 1.8 protocol?
* Supports 1.9->1.15.2 too!
* @param nmsPacket
* @return If the nms packet provided is an instanceof the "PacketPlayInFlying" packet in the 1.8 protocol!
*/
public static boolean isInstanceOfFlyingPacket(Object nmsPacket) {
//1.7->1.8.8
if (packetPlayInFlying != null) {
return packetPlayInFlying.isInstance(nmsPacket);
} else {
//1.9->1.15.2
return packetPlayInPosition.isInstance(nmsPacket)
|| packetPlayInPositionLook.isInstance(nmsPacket)
|| packetPlayInLook.isInstance(nmsPacket);
}
}
/**
* Use isInstanceOfFlyingPacket(nmsPacketObject) instead of this, as the flying packet is the only packet that has subclasses (in 1.8 atleast).
* Will be removed in newer versions of PacketEvents!
* @param fatherPacket
* @param childPacket
* @return isInstanceOf
*/
@Deprecated
public static boolean isInstanceOf(String fatherPacket, String childPacket) {
if (fatherPacket.equals(Client.FLYING) && childPacket.equals(Client.POSITION) || childPacket.equals(Client.POSITION_LOOK) || childPacket.equals(Client.LOOK)) {
return true;
}
return fatherPacket.equals(childPacket);
}
private static Class<?> packetPlayInFlying, packetPlayInPosition, packetPlayInPositionLook, packetPlayInLook;
static {
try {
packetPlayInFlying = NMSUtils.getNMSClass(Client.FLYING);
} catch (ClassNotFoundException e) {
//That is fine, they are on 1.9+ so we just initiate the rest of the variables
try {
packetPlayInPosition = NMSUtils.getNMSClass(Client.POSITION);
packetPlayInPositionLook = NMSUtils.getNMSClass(Client.POSITION_LOOK);
packetPlayInLook = NMSUtils.getNMSClass(Client.LOOK);
} catch (ClassNotFoundException e2) {
e2.printStackTrace();
}
}
}
}
@@ -0,0 +1,5 @@
package io.github.retrooper.packetevents.packetwrappers;
public interface Sendable {
public Object asNMSPacket();
}
@@ -0,0 +1,37 @@
package io.github.retrooper.packetevents.packetwrappers.api;
import io.github.retrooper.packetevents.enums.ServerVersion;
import org.bukkit.entity.Player;
public class WrappedPacket {
protected final Player player;
protected Object packet;
protected static ServerVersion version = ServerVersion.getVersion();
public WrappedPacket(final Object packet) {
this.player = null;
if(packet == null)return;
this.packet = packet;
try {
setup();
} catch (final Exception e) {
e.printStackTrace();
}
}
public WrappedPacket(final Player player, final Object packet) {
this.player = player;
if(packet == null)return;
this.packet = packet;
try {
setup();
} catch (final Exception e) {
e.printStackTrace();
}
}
protected void setup() {
}
}
@@ -0,0 +1,88 @@
package io.github.retrooper.packetevents.packetwrappers.in.abilities;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public final class WrappedPacketInAbilities extends WrappedPacket {
private boolean isVulnerable;
private boolean isFlying;
private boolean allowFly;
private boolean instantBuild;
private float flySpeed;
private float walkSpeed;
public WrappedPacketInAbilities(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.isVulnerable = fields[0].getBoolean(packet);
this.isFlying = fields[1].getBoolean(packet);
this.allowFly = fields[2].getBoolean(packet);
this.instantBuild = fields[3].getBoolean(packet);
this.flySpeed = fields[4].getFloat(packet);
this.walkSpeed = fields[5].getFloat(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public boolean isVulnerable() {
return isVulnerable;
}
public boolean isFlying() {
return isFlying;
}
public boolean canFly() {
return allowFly;
}
public boolean canInstantlyBuild() {
return instantBuild;
}
public float getFlySpeed() {
return flySpeed;
}
public float getWalkSpeed() {
return walkSpeed;
}
private static Class<?> abilitiesClass;
private static Field[] fields = new Field[6];
static {
try {
abilitiesClass = NMSUtils.getNMSClass("PacketPlayInAbilities");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
fields[0] = abilitiesClass.getDeclaredField("a");
fields[1] = abilitiesClass.getDeclaredField("b");
fields[2] = abilitiesClass.getDeclaredField("c");
fields[3] = abilitiesClass.getDeclaredField("d");
fields[4] = abilitiesClass.getDeclaredField("e");
fields[5] = abilitiesClass.getDeclaredField("f");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
}
}
@@ -0,0 +1,137 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockdig;
import io.github.retrooper.packetevents.enums.Direction;
import io.github.retrooper.packetevents.enums.PlayerDigType;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import java.lang.reflect.Field;
public final class WrappedPacketInBlockDig extends WrappedPacket {
private Vector3i blockPosition;
private Direction direction;
private PlayerDigType digType;
public WrappedPacketInBlockDig(Object packet) {
super(packet);
}
@Override
protected void setup() {
Direction enumDirection = null;
PlayerDigType enumDigType = null;
//1.7.10
try {
if (version == ServerVersion.v_1_7_10) {
final int x = fields[0].getInt(packet);
final int y = fields[1].getInt(packet);
final int z = fields[2].getInt(packet);
this.blockPosition = new Vector3i(x, y, z);
enumDirection = Direction.get((byte) face.getInt(packet));
enumDigType = PlayerDigType.get((byte) e.getInt(packet));
} else {
//1.8+
final Object blockPosObj = fields[0].get(packet);
final Object enumDirectionObj = fields[1].get(packet);
final Object digTypeObj = fields[2].get(packet);
final int x = blockPosXYZ[0].get(blockPosObj);
final int y = blockPosXYZ[1].get(blockPosObj);
final int z = blockPosXYZ[2].get(blockPosObj);
this.blockPosition = new Vector3i(x, y, z);
enumDirection = Direction.valueOf(((Enum) enumDirectionObj).name());
enumDigType = PlayerDigType.valueOf(((Enum) digTypeObj).name());
}
}
catch(IllegalAccessException e) {
e.printStackTrace();
}
this.direction = enumDirection;
this.digType = enumDigType;
}
public Vector3i getBlockPosition() {
return blockPosition;
}
public Direction getDirection() {
return direction;
}
public PlayerDigType getDigType() {
return digType;
}
//ALL
private static Class<?> blockDigClass;
//1.8
private static Field[] fields = new Field[3];
private static Class<?> blockPositionClass;
private static Reflection.FieldAccessor<Integer>[] blockPosXYZ = new Reflection.FieldAccessor[3];
//1.7
private static Field face;
private static Field e;
static {
try {
blockDigClass = NMSUtils.getNMSClass("PacketPlayInBlockDig");
if (version != ServerVersion.v_1_7_10) {
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//blockpos
fields[0] = blockDigClass.getDeclaredField("a");
//direction
fields[1] = blockDigClass.getDeclaredField("b");
//digtype
fields[2] = blockDigClass.getDeclaredField("c");
if (version != ServerVersion.v_1_7_10) {
blockPosXYZ[0] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 0);
blockPosXYZ[1] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 1);
blockPosXYZ[2] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 2);
} else {
face = blockDigClass.getDeclaredField("face");
e = blockDigClass.getDeclaredField("e");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for(Field f : fields) {
if(f != null) {
f.setAccessible(true);
}
}
if(e != null) {
e.setAccessible(true);
}
if(face != null) {
face.setAccessible(true);
}
}
}
@@ -0,0 +1,61 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public final class WrappedPacketInBlockPlace extends WrappedPacket {
private Vector3i blockPosition;
private ItemStack itemStack;
public WrappedPacketInBlockPlace(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
//1.7.10
Vector3i position = null;
ItemStack itemStack = null;
try {
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
final WrappedPacketInBlockPlace_1_9 updatedBlockPlace = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
final Block block = updatedBlockPlace.getBlock();
position = new Vector3i(block.getX(), block.getY(), block.getZ());
itemStack = new ItemStack(block.getType());
} else {
final WrappedPacketInBlockPlace_1_8 legacyBlockPlace = new WrappedPacketInBlockPlace_1_8(packet);
position = legacyBlockPlace.getBlockPosition();
itemStack = legacyBlockPlace.getItemStack();
} }
catch(IllegalArgumentException e) {
e.printStackTrace();
}
this.blockPosition = position;
this.itemStack = itemStack;
}
public Player getPlayer() {
return this.player;
}
public Vector3i getBlockPosition() {
return blockPosition;
}
public ItemStack getItemStack() {
return itemStack;
}
static {
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
WrappedPacketInBlockPlace_1_9.initStatic();
} else if(version.isLowerThan(ServerVersion.v_1_9) && version.isHigherThan(ServerVersion.v_1_7_10)){
WrappedPacketInBlockPlace_1_8.initStatic();
}
}
}
@@ -0,0 +1,41 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
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 {
private Vector3i blockPosition;
private ItemStack itemStack;
private int blockFace;
WrappedPacketInBlockPlace_1_7_10(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
final PacketPlayInBlockPlace blockPlace = (PacketPlayInBlockPlace)packet;
this.blockPosition = new Vector3i(blockPlace.c(), blockPlace.d(), blockPlace.e());
this.blockFace = blockPlace.d();
net.minecraft.server.v1_7_R4.ItemStack stack = blockPlace.getItemStack();
this.itemStack = org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asBukkitCopy(stack);
}
public Vector3i getBlockPosition() {
return blockPosition;
}
public ItemStack getItemStack() {
return itemStack;
}
public int getBlockFace() {
return blockFace;
}
}
@@ -0,0 +1,59 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import org.bukkit.inventory.ItemStack;
final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
private Vector3i blockPosition;
private ItemStack itemStack;
WrappedPacketInBlockPlace_1_8(final Object packet) {
super(packet);
}
@Override
protected void setup() {
Object nmsBlockPos = blockPositionAccessor.get(packet);
int x = (int) blockPositionXYZInvoker[0].invoke(nmsBlockPos);
int y = (int) blockPositionXYZInvoker[1].invoke(nmsBlockPos);
int z = (int) blockPositionXYZInvoker[2].invoke(nmsBlockPos);
this.blockPosition = new Vector3i(x, y, z);
this.itemStack = NMSUtils.toBukkitItemStack(itemStackFieldAccessor.get(packet));
}
public Vector3i getBlockPosition() {
return blockPosition;
}
public ItemStack getItemStack() {
return itemStack;
}
private static Class<?> blockPlaceClass, blockPositionClass;
private static Reflection.FieldAccessor<?> blockPositionAccessor, itemStackFieldAccessor;
private static final Reflection.MethodInvoker[] blockPositionXYZInvoker = new Reflection.MethodInvoker[3];
protected static void initStatic(){
try {
blockPlaceClass = NMSUtils.getNMSClass("PacketPlayInBlockPlace");
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
itemStackFieldAccessor = Reflection.getField(blockPlaceClass, NMSUtils.nmsItemStackClass, 0);
blockPositionAccessor = Reflection.getField(blockPlaceClass, blockPositionClass, 1);
blockPositionXYZInvoker[0] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getX");
blockPositionXYZInvoker[1] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getY");
blockPositionXYZInvoker[2] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getZ");
}
}
@@ -0,0 +1,43 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.HashSet;
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
private Block block;
public WrappedPacketInBlockPlace_1_9(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
this.block = getPlayer().getTargetBlock((HashSet<Material>)null, 3);
}
public Player getPlayer() {
return this.player;
}
public Block getBlock() {
return block;
}
private static Class<?> blockPlaceClass_1_9;
protected static void initStatic() {
try {
blockPlaceClass_1_9 = NMSUtils.getNMSClass("PacketPlayInUseItem");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,57 @@
package io.github.retrooper.packetevents.packetwrappers.in.chat;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public final class WrappedPacketInChat extends WrappedPacket {
private String message;
public WrappedPacketInChat(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
final Object obj = field.get(packet);
this.message = obj.toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public String getMessage() {
return message;
}
private static Class<?> chatPacketClass;
private static Field field;
static {
try {
chatPacketClass = NMSUtils.getNMSClass("PacketPlayInChat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
field = chatPacketClass.getDeclaredField(getChatFieldName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
}
private static String getChatFieldName() {
if (version == ServerVersion.v_1_7_10) {
return "message";
}
return "a";
}
}
@@ -0,0 +1,111 @@
package io.github.retrooper.packetevents.packetwrappers.in.entityaction;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.enums.PlayerAction;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Field;
public final class WrappedPacketInEntityAction extends WrappedPacket {
private Entity entity;
private int entityId;
private PlayerAction action;
private int jumpBoost;
public WrappedPacketInEntityAction(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
final int entityId = fields[0].getInt(packet);
final int jumpBoost = fields[2].getInt(packet);
int animationIndex = -1;
//1.7.10
if (version.isLowerThan(ServerVersion.v_1_8)) {
animationIndex = fields[1].getInt(packet);
} else {
final Object enumObj = fields[1].get(packet);
final Object[] enumValues = enumPlayerActionConstants;
final int len = enumValues.length;
for (int i = 0; i < len; i++) {
final Object val = enumValues[i];
if (val.toString().equals(enumObj.toString())) {
animationIndex = i;
break;
}
}
}
this.entityId = entityId;
this.action = action;
this.jumpBoost = jumpBoost;
this.action = PlayerAction.get((byte) animationIndex);
this.entity = NMSUtils.getEntityById(this.entityId);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Entity getEntity() {
return entity;
}
public int getEntityId() {
return entityId;
}
public PlayerAction getAction() {
return action;
}
public int getJumpBoost() {
return jumpBoost;
}
private static Class<?> entityActionClass;
@Nullable
private static Class<?> enumPlayerActionClass;
private static Field[] fields = new Field[3];
@Nullable
private static Object[] enumPlayerActionConstants;
static {
try {
entityActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction");
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
enumPlayerActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction$EnumPlayerAction");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//ints in 1.7.10, EnumPlayerAction in 1.8+
fields[0] = entityActionClass.getDeclaredField("a");
fields[1] = entityActionClass.getDeclaredField("animation");
fields[2] = entityActionClass.getDeclaredField("c");
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
enumPlayerActionConstants = enumPlayerActionClass.getEnumConstants();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,147 @@
package io.github.retrooper.packetevents.packetwrappers.in.flying;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInFlying extends WrappedPacket {
private double x;
private double y;
private double z;
private float yaw;
private float pitch;
private boolean onGround;
private boolean isPosition;
private boolean isLook;
public WrappedPacketInFlying(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.x = fields[0].getDouble(packet);
this.y = fields[1].getDouble(packet);
this.z = fields[2].getDouble(packet);
this.yaw = fields[3].getFloat(packet);
this.pitch = fields[4].getFloat(packet);
this.onGround = fields[5].getBoolean(packet);
this.isPosition = fields[6].getBoolean(packet);
this.isLook = fields[7].getBoolean(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static class WrappedPacketInPosition extends WrappedPacketInFlying {
public WrappedPacketInPosition(Object packet) {
super(packet);
}
@Override
public boolean isPosition() {
return true;
}
@Override
public boolean isLook() {
return false;
}
}
public static class WrappedPacketInPosition_Look extends WrappedPacketInFlying {
public WrappedPacketInPosition_Look(Object packet) {
super(packet);
}
@Override
public boolean isLook() {
return true;
}
@Override
public boolean isPosition() {
return false;
}
}
public final double getX() {
return x;
}
public final double getY() {
return y;
}
public final double getZ() {
return z;
}
public final float getYaw() {
return yaw;
}
public final float getPitch() {
return pitch;
}
public final boolean isOnGround() {
return onGround;
}
public boolean isPosition() {
return isPosition;
}
public boolean isLook() {
return isLook;
}
private static Class<?> flyingClass;
private static Field[] fields = new Field[8]; //x, y, z, yaw pitch, onGround, isPositionPacket, isLookPacket
static {
try {
flyingClass = NMSUtils.getNMSClass("PacketPlayInFlying");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
fields[0] = flyingClass.getDeclaredField("x");
fields[1] = flyingClass.getDeclaredField("y");
fields[2] = flyingClass.getDeclaredField("z");
fields[3] = flyingClass.getDeclaredField("yaw");
fields[4] = flyingClass.getDeclaredField("pitch");
fields[5] = flyingClass.getDeclaredField(getOnGroundFieldName());
fields[6] = flyingClass.getDeclaredField("hasPos");
fields[7] = flyingClass.getDeclaredField("hasLook");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
}
private static String getOnGroundFieldName() {
if (version == ServerVersion.v_1_7_10) {
return "g";
}
return "f";
}
}
@@ -0,0 +1,58 @@
package io.github.retrooper.packetevents.packetwrappers.in.keepalive;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public final class WrappedPacketInKeepAlive extends WrappedPacket {
public WrappedPacketInKeepAlive(final Object packet) {
super(packet);
}
private long id;
@Override
protected void setup() {
try {
if (version.isHigherThan(ServerVersion.v_1_12)) {
this.id = idField.getLong(packet);
} else {
this.id = idField.getInt(packet);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* Cast this long to an integer if you are using 1.7.10->1.12.2!
* In 1.13.2->1.15.2 a long is sent
*
* @return
*/
public long getId() {
return id;
}
private static Class<?> keepAliveClass;
//1.7.10->1.12.2 has int field "a", rest as long field "a"
private static Field idField;
static {
try {
keepAliveClass = NMSUtils.getNMSClass("PacketPlayInKeepAlive");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
idField = keepAliveClass.getDeclaredField("a");
idField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,78 @@
package io.github.retrooper.packetevents.packetwrappers.in.useentity;
import io.github.retrooper.packetevents.enums.EntityUseAction;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Field;
public final class WrappedPacketInUseEntity extends WrappedPacket {
private int entityId;
private Entity entity;
private EntityUseAction action;
public WrappedPacketInUseEntity(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.entityId = fields[0].getInt(packet);
this.entity = NMSUtils.getEntityById(this.entityId);
final Object useActionEnum = fields[1].get(packet);
this.action = EntityUseAction.valueOf(useActionEnum.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Entity getEntity() {
return entity;
}
public int getEntityId() {
return entityId;
}
public EntityUseAction getAction() {
return action;
}
private static Class<?> useEntityClass;
private static Class<?> entityClass;
private static Field[] fields = new Field[2];
static {
try {
useEntityClass = NMSUtils.getNMSClass("PacketPlayInUseEntity");
entityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
fields[0] = useEntityClass.getDeclaredField("a");
fields[1] = useEntityClass.getDeclaredField("action");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
}
}
@@ -0,0 +1,55 @@
package io.github.retrooper.packetevents.packetwrappers.login;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class WrappedPacketLoginHandshake extends WrappedPacket {
private int protocolVersion, port;
private String hostname;
public WrappedPacketLoginHandshake(final Object packet) {
super(packet);
}
@Override
protected void setup() {
final Object protocolVersionObj = fields[0].get(packet);
final Object hostNameObj = fields[1].get(packet);
final Object portObj = fields[2].get(packet);
this.protocolVersion = (int)protocolVersionObj;
this.hostname = hostNameObj.toString();
this.port = (int)portObj;
}
public int getProtocolVersion() {
return protocolVersion;
}
public String getHostname() {
return hostname;
}
public int getPort() {
return port;
}
private static Class<?> loginHandshakeClass;
private static FieldAccessor<?>[] fields = new FieldAccessor[3];
static {
try {
loginHandshakeClass = NMSUtils.getNMSClass("PacketHandshakingInSetProtocol");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
fields[0] = Reflection.getField(loginHandshakeClass, int.class, 0);
fields[1] = Reflection.getField(loginHandshakeClass, String.class, 0);
fields[2] = Reflection.getField(loginHandshakeClass, int.class, 1);
}
}
@@ -0,0 +1,41 @@
package io.github.retrooper.packetevents.packetwrappers.login;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
private byte[] publicKey, verifyToken;
public WrappedPacketLoginInEncryptionBegin(final Object packet) {
super(packet);
}
@Override
protected void setup() {
this.publicKey = fields[0].get(packet);
this.verifyToken = fields[1].get(packet);
}
public byte[] getPublicKey() {
return publicKey;
}
public byte[] getVerifyToken() {
return verifyToken;
}
private static Class<?> packetClass;
private static final Reflection.FieldAccessor<byte[]>[] fields = new Reflection.FieldAccessor[2];
static {
try {
packetClass = NMSUtils.getNMSClass("PacketLoginInEncryptionBegin");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
fields[0] = Reflection.getField(packetClass, byte[].class, 0);
fields[1] = Reflection.getField(packetClass, byte[].class, 1);
}
}
@@ -0,0 +1,58 @@
package io.github.retrooper.packetevents.packetwrappers.login;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.security.PublicKey;
public final class WrappedPacketLoginOutEncryptionBegin extends WrappedPacket {
private String encodedString;
private PublicKey encodedKey;
private byte[] byteArray;
public WrappedPacketLoginOutEncryptionBegin(final Object packet) {
super(packet);
}
@Override
protected void setup() {
//string - a (encodedstring)
//public key - b (encoded)
//byte array - c(byte array)
this.encodedString = fields[0].get(packet).toString();
this.encodedKey = (PublicKey) fields[1].get(packet);
this.byteArray = (byte[]) fields[2].get(packet);
}
public String getEncodedString() {
return encodedString;
}
public PublicKey getEncodedKey() {
return encodedKey;
}
public byte[] getByteArray() {
return byteArray;
}
private static Class<?> packetClass;
private static final Reflection.FieldAccessor<?>[] fields = new Reflection.FieldAccessor[3];
static {
try {
packetClass = NMSUtils.getNMSClass("PacketLoginOutEncryptionBegin");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
fields[0] = Reflection.getField(packetClass, String.class, 0);
fields[1] = Reflection.getField(packetClass, PublicKey.class, 1);
fields[2] = Reflection.getField(packetClass, byte[].class, 2);
}
}
@@ -0,0 +1,36 @@
package io.github.retrooper.packetevents.packetwrappers.login;
import io.github.retrooper.packetevents.mojang.GameProfile;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class WrappedPacketLoginStart extends WrappedPacket {
private GameProfile gameProfile;
public WrappedPacketLoginStart(final Object packet) {
super(packet);
}
@Override
protected void setup() {
com.mojang.authlib.GameProfile gp = gameProfileAccessor.get(packet);
this.gameProfile = new GameProfile(gp.getId(), gp.getName());
}
public GameProfile getGameProfile() {
return gameProfile;
}
private static Class<?> packetClass;
private static final Reflection.FieldAccessor<com.mojang.authlib.GameProfile> gameProfileAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketLoginInStart");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
gameProfileAccessor = Reflection.getField(packetClass, com.mojang.authlib.GameProfile.class, 0);
}
}
@@ -0,0 +1,36 @@
package io.github.retrooper.packetevents.packetwrappers.login;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class WrappedPacketLoginStatusPing extends WrappedPacket {
private long number;
public WrappedPacketLoginStatusPing(final Object packet) {
super(packet);
}
@Override
protected void setup() {
this.number = numberAccessor.get(packet);
}
public long getNumber() {
return number;
}
private static Class<?> packetClass;
private static final Reflection.FieldAccessor<Long> numberAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketStatusInPing");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
numberAccessor = Reflection.getField(packetClass, long.class, 0);
}
}
@@ -0,0 +1,98 @@
package io.github.retrooper.packetevents.packetwrappers.out.animation;
import io.github.retrooper.packetevents.enums.EntityAnimationType;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketOutAnimation extends WrappedPacket implements Sendable {
private Entity entity;
private int entityID;
private EntityAnimationType type;
public WrappedPacketOutAnimation(final Object packet) {
super(packet);
}
public WrappedPacketOutAnimation(final Entity target, final EntityAnimationType type) {
super(null);
this.entityID = target.getEntityId();
this.entity = target;
this.type = type;
}
@Override
protected void setup() {
try {
//a - ID
//b - TYPE
this.entityID = fields[0].getInt(packet);
this.entity = NMSUtils.getEntityById(this.entityID);
this.type = EntityAnimationType.get(fields[1].getInt(packet));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Entity getEntity() {
return this.entity;
}
public int getEntityId() {
return this.entityID;
}
public EntityAnimationType getAnimationType() {
return type;
}
@Override
public Object asNMSPacket() {
final Object nmsEntity = NMSUtils.getNMSEntity(this.entity);
final int index = type.getIndex();
try {
return animationConstructor.newInstance(nmsEntity, index);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> animationClass, nmsEntityClass;
private static Constructor<?> animationConstructor;
private static Field[] fields = new Field[2];
static {
try {
animationClass = NMSUtils.getNMSClass("PacketPlayOutAnimation");
nmsEntityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
animationConstructor = animationClass.getConstructor(nmsEntityClass, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
fields[0] = animationClass.getDeclaredField("a");
fields[1] = animationClass.getDeclaredField("b");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,132 @@
package io.github.retrooper.packetevents.packetwrappers.out.chat;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class WrappedPacketOutChat extends WrappedPacket implements Sendable {
private String message;
public WrappedPacketOutChat(final Object packet) {
super(packet);
}
public WrappedPacketOutChat(final String message) {
super(null);
this.message = "{\"text\": \"" + message + "\"}";
}
@Override
protected void setup() {
//all fields are IChatBaseComponents, and named 'a'
try {
Object iChatBaseObj = iChatBaseField.get(packet);
Object contentString = getStringOfIChatBase.invoke(iChatBaseObj);
this.message = contentString.toString();
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
@Override
public Object asNMSPacket() {
try {
return chatClassConstructor.newInstance(toIChatBaseComponent(this.message));
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static String toStringFromIChatBaseComponent(Object obj) {
try {
return getStringOfIChatBase.invoke(obj).toString();
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object toIChatBaseComponent(String msg) {
try {
return serialize.invoke(null, msg);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public String getMessage() {
return this.message;
}
private static Constructor<?> chatClassConstructor;
private static Class<?> chatClass, iChatBaseComponentClass, chatSerializerClass;
private static Field iChatBaseField;
private static Method serialize, getStringOfIChatBase;
static {
try {
chatClass = NMSUtils.getNMSClass("PacketPlayOutChat");
iChatBaseComponentClass = NMSUtils.getNMSClass("IChatBaseComponent");
//In 1.8.3+ the ChatSerializer class is declared in the IChatBaseComponent class, so we have to handle tahat
if(version.isHigherThan(ServerVersion.v_1_8)) {
for(final Class<?> cls : iChatBaseComponentClass.getDeclaredClasses()) {
if(cls.getSimpleName().equals("ChatSerializer")) {
chatSerializerClass = cls;
break;
}
}
}
else {
chatSerializerClass = NMSUtils.getNMSClass("ChatSerializer");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
chatClassConstructor = chatClass.getConstructor(iChatBaseComponentClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
serialize = chatSerializerClass.getMethod("a", String.class);
getStringOfIChatBase = iChatBaseComponentClass.getMethod(getTextMethodName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
iChatBaseField = chatClass.getDeclaredField("a");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
iChatBaseField.setAccessible(true);
}
private static String getTextMethodName() {
//1.7.10
if (version.isLowerThan(ServerVersion.v_1_8)) {
return "e"; //or c
} else {
return "getText";
}
}
}
@@ -0,0 +1,145 @@
package io.github.retrooper.packetevents.packetwrappers.out.entityvelocity;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketOutEntityVelocity extends WrappedPacket implements Sendable {
private Entity entity;
private int entityId;
private double velocityX, velocityY, velocityZ;
public WrappedPacketOutEntityVelocity(final Object packet) {
super(packet);
}
public WrappedPacketOutEntityVelocity(final Entity entity, final double velocityX, final double velocityY, final double velocityZ) {
super(null);
this.entityId = entity.getEntityId();
this.entity = entity;
this.velocityX = velocityX;
this.velocityY = velocityY;
this.velocityZ = velocityZ;
}
@Override
protected void setup() {
try {
int i = 0;
final int entityId = fields[0].getInt(packet);
final int x = fields[1].getInt(packet);
final int y = fields[2].getInt(packet);
final int z = fields[3].getInt(packet);
this.entityId = entityId;
this.entity = NMSUtils.getEntityById(this.entityId);
this.velocityX = x / 8000.0D;
this.velocityY = y / 8000.0D;
this.velocityZ = z / 8000.0D;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public int getEntityId() {
return entityId;
}
public Entity getEntity() {
return entity;
}
public double getVelocityX() {
return velocityX;
}
public double getVelocityY() {
return velocityY;
}
public double getVelocityZ() {
return velocityZ;
}
@Override
public Object asNMSPacket() {
if (version.isLowerThan(ServerVersion.v_1_14)) {
try {
return velocityConstructor.newInstance(entityId, velocityX, velocityY, velocityZ);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} else {
try {
return velocityConstructor.newInstance(entityId, vec3dConstructor.newInstance(velocityX, velocityY, velocityZ));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}
private static Constructor<?> velocityConstructor, vec3dConstructor;
private static Class<?> velocityClass, vec3dClass;
private static Field[] fields = new Field[4];
/**
* Velocity Constructor parameter types:
* 1.7.10->1.13.2 use int, double, double, double style,
* 1.14+ use int, Vec3D style
*/
static {
try {
velocityClass = NMSUtils.getNMSClass("PacketPlayOutEntityVelocity");
if (version.isHigherThan(ServerVersion.v_1_13_2)) {
vec3dClass = NMSUtils.getNMSClass("Vec3D");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
if (version.isHigherThan(ServerVersion.v_1_13_2)) {
velocityConstructor = velocityClass.getConstructor(int.class, vec3dClass);
//vec3d constructor
vec3dConstructor = vec3dClass.getConstructor(double.class, double.class, double.class);
} else {
velocityConstructor = velocityClass.getConstructor(int.class, double.class, double.class, double.class);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
//entity id
fields[0] = velocityClass.getDeclaredField("a");
//x
fields[1] = velocityClass.getDeclaredField("b");
//y
fields[2] = velocityClass.getDeclaredField("c");
//z
fields[3] = velocityClass.getDeclaredField("d");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,64 @@
package io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.packetwrappers.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketOutKickDisconnect extends WrappedPacket implements Sendable {
private String kickMessage;
public WrappedPacketOutKickDisconnect(final Object packet) {
super(packet);
}
public WrappedPacketOutKickDisconnect(final String kickMessage) {
super(null);
this.kickMessage = kickMessage;
}
@Override
protected void setup() {
this.kickMessage = WrappedPacketOutChat.toStringFromIChatBaseComponent(iChatBaseComponentAccessor.get(packet));
}
public String getKickMessage() {
return kickMessage;
}
@Override
public Object asNMSPacket() {
try {
return kickDisconnectConstructor.newInstance(WrappedPacketOutChat.toIChatBaseComponent("{\"text\": \"" + kickMessage + "\"}"));
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> packetClass, iChatBaseComponentClass;
private static Constructor<?> kickDisconnectConstructor;
private static final Reflection.FieldAccessor<?> iChatBaseComponentAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketPlayOutKickDisconnect");
iChatBaseComponentClass = NMSUtils.getNMSClass("IChatBaseComponent");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
kickDisconnectConstructor = packetClass.getConstructor(iChatBaseComponentClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
iChatBaseComponentAccessor = Reflection.getField(packetClass, iChatBaseComponentClass, 0);
}
}
@@ -0,0 +1,403 @@
package io.github.retrooper.packetevents.tinyprotocol;
import org.bukkit.Bukkit;
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;
/**
* 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;
}
/**
* Retrieve a class from its full name.
* <p>
* Strings enclosed with curly brackets - such as {TEXT} - will be replaced according to the following table:
* <p>
* <table border="1">
* <tr>
* <th>Variable</th>
* <th>Content</th>
* </tr>
* <tr>
* <td>{nms}</td>
* <td>Actual package name of net.minecraft.server.VERSION</td>
* </tr>
* <tr>
* <td>{obc}</td>
* <td>Actual pacakge name of org.bukkit.craftbukkit.VERSION</td>
* </tr>
* <tr>
* <td>{version}</td>
* <td>The current Minecraft package VERSION, if any.</td>
* </tr>
* </table>
*
* @param lookupName - the class name with variables.
* @return The looked up class.
* @throws IllegalArgumentException If a variable or class could not be found.
*/
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();
}
}
@@ -0,0 +1,544 @@
/*
* 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.tinyprotocol;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
import io.github.retrooper.packetevents.event.impl.PlayerUninjectEvent;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.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 abstract class TinyProtocol7 {
private static final AtomicInteger ID = new AtomicInteger(0);
// 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 FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
// Speedup channel/protocol lookup
private final Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Listener listener;
// Channels that have already been removed
private final 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();
// Prepare existing players
registerBukkitEvents();
try {
registerChannelHandler();
registerPlayers(plugin);
} catch (IllegalArgumentException ex) {
// Damn you, late bind
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
new BukkitRunnable() {
@Override
public void run() {
registerChannelHandler();
registerPlayers(plugin);
plugin.getLogger().info("[TinyProtocol] 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.
*/
private void registerBukkitEvents() {
listener = new Listener() {
@EventHandler(priority = EventPriority.LOWEST)
public final void onPlayerLogin(PlayerLoginEvent e) {
if (closed)
return;
Channel channel = getChannel(e.getPlayer());
// Don't inject players that have been explicitly uninjected
if (!uninjectedChannels.contains(channel)) {
injectPlayer(e.getPlayer());
}
}
@EventHandler
public final void onPluginDisable(PluginDisableEvent e) {
if (e.getPlugin().equals(plugin)) {
close();
}
}
};
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
}
@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) {
final String packetName = packet.getClass().getSimpleName();
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
PacketEvents.getEventManager().callEvent(packetSendEvent);
if (!packetSendEvent.isCancelled()) {
return packet;
}
return null;
}
/**
* 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 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);
}
/**
* 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);
}
/**
* Changed from "tiny-" to "packetevents"
* @return handlerName
*/
protected String getHandlerName() {
return "packetevents-" + plugin.getName() + "-" + 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) {
final PlayerInjectEvent playerInjectEvent = new PlayerInjectEvent(player);
PacketEvents.getEventManager().callEvent(playerInjectEvent);
if (!playerInjectEvent.isCancelled()) {
injectChannelInternal(getChannel(player)).player = player;
}
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
* @return The intercepted channel, or NULL if it has already been injected.
*/
public void injectChannel(Channel channel) {
injectChannelInternal(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);
}
}
/**
* 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));
PacketEvents.getEventManager().callEvent(new PlayerUninjectEvent(player));
}
/**
* 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.eventLoop().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);
}
}
@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);
}
}
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
GameProfile profile = getGameProfile.get(packet);
channelLookup.put(profile.getName(), channel);
}
}
}
}
@@ -0,0 +1,550 @@
/*
* 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.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.event.impl.PlayerInjectEvent;
import io.github.retrooper.packetevents.event.impl.PlayerUninjectEvent;
import io.github.retrooper.packetevents.handler.TinyProtocolHandler_1_8;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
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.lang.reflect.Field;
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 abstract class TinyProtocol8 {
private static final AtomicInteger ID = new AtomicInteger(0);
// Used in order to lookup a channel
private static final Reflection.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);
// Packets we have to intercept
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
// Speedup channel/protocol lookup
private final Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Listener listener;
// Channels that have already been removed
private final Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
// List of network markers
private List<Object> networkManagers;
// Injected channel handlers
private final 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();
// Prepare existing players
registerBukkitEvents();
try {
registerChannelHandler();
registerPlayers(plugin);
} catch (IllegalArgumentException | NoSuchFieldException | IllegalAccessException ex) {
// Damn you, late bind
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
new BukkitRunnable() {
@Override
public void run() {
try {
registerChannelHandler();
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
registerPlayers(plugin);
plugin.getLogger().info("[TinyProtocol] 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.
*/
private void registerBukkitEvents() {
listener = new Listener() {
@EventHandler(priority = EventPriority.LOWEST)
public final void onPlayerLogin(PlayerLoginEvent e) {
if (closed)
return;
Channel channel = getChannel(e.getPlayer());
// Don't inject players that have been explicitly uninjected
if (!uninjectedChannels.contains(channel)) {
injectPlayer(e.getPlayer());
}
}
@EventHandler
public final void onPluginDisable(PluginDisableEvent e) {
if (e.getPlugin().equals(plugin)) {
close();
}
}
};
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
}
/**
* Function modified by Retrooper
*
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
@SuppressWarnings("unchecked")
private void registerChannelHandler() throws NoSuchFieldException, IllegalAccessException {
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
Object serverConnection = getServerConnection.get(mcServer);
boolean looking = true;
/*
* I am doing this so we can support 1.8->1.15.2, the previous method TinyProtocol used wasn't supported on some versions
* like 1.15.2
*/
final Field networkManagersField = serverConnection.getClass().getDeclaredField(TinyProtocolHandler_1_8.getNetworkManagersFieldName());
networkManagersField.setAccessible(true);
networkManagers = (List<Object>) networkManagersField.get(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 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 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);
}
/**
* 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);
}
/**
* Changed from "tiny-" to "packetevents"
*
* @return handlerName
*/
protected String getHandlerName() {
return "packetevents-" + plugin.getName() + "-" + 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) {
final PlayerInjectEvent playerInjectEvent = new PlayerInjectEvent(player);
PacketEvents.getEventManager().callEvent(playerInjectEvent);
if (!playerInjectEvent.isCancelled()) {
injectChannelInternal(getChannel(player)).player = player;
}
}
/**
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
* @return The intercepted channel, or NULL if it has already been injected.
*/
public void injectChannel(Channel channel) {
injectChannelInternal(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);
}
}
/**
* 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));
PacketEvents.getEventManager().callEvent(new PlayerUninjectEvent(player));
}
/**
* 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.eventLoop().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);
}
}
@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);
}
}
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
GameProfile profile = getGameProfile.get(packet);
channelLookup.put(profile.getName(), channel);
}
}
}
}
@@ -0,0 +1,187 @@
package io.github.retrooper.packetevents.utils;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.utils.nms_entityfinder.EntityFinderUtils;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class NMSUtils {
private static final ServerVersion version = ServerVersion.getVersion();
public static final String nettyPrefix = version.isLowerThan(ServerVersion.v_1_8) ? "net.minecraft.util.io.netty" : "io.netty";
private static final String nmsDir = ServerVersion.getNMSDirectory();
private static final String obcDir = ServerVersion.getOBCDirectory();
public static Class<?> minecraftServerClass, craftWorldsClass,
packetClass, entityPlayerClass, playerConnectionClass, craftPlayerClass, serverConnectionClass, craftEntityClass, craftItemStack, nmsItemStackClass;
private static Method getServerMethod, getCraftWorldHandleMethod, getServerConnection, getCraftPlayerHandle, getCraftEntityHandle, sendPacketMethod, asBukkitCopy;
private static Field recentTPSField, entityPlayerPingField, playerConnectionField;
static {
try {
minecraftServerClass = getNMSClass("MinecraftServer");
craftWorldsClass = getOBCClass("CraftWorld");
craftPlayerClass = getOBCClass("entity.CraftPlayer");
entityPlayerClass = getNMSClass("EntityPlayer");
packetClass = getNMSClass("Packet");
playerConnectionClass = getNMSClass("PlayerConnection");
serverConnectionClass = getNMSClass("ServerConnection");
craftEntityClass = getOBCClass("entity.CraftEntity");
craftItemStack = getOBCClass("inventory.CraftItemStack");
nmsItemStackClass = getNMSClass("ItemStack");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//METHODS
try {
getServerMethod = minecraftServerClass.getMethod("getServer");
getCraftWorldHandleMethod = craftWorldsClass.getMethod("getHandle");
getCraftPlayerHandle = craftPlayerClass.getMethod("getHandle");
getCraftEntityHandle = craftEntityClass.getMethod("getHandle");
sendPacketMethod = playerConnectionClass.getMethod("sendPacket", packetClass);
getServerConnection = minecraftServerClass.getMethod("getServerConnection");
asBukkitCopy = craftItemStack.getMethod("asBukkitCopy", nmsItemStackClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
recentTPSField = minecraftServerClass.getField("recentTps");
entityPlayerPingField = entityPlayerClass.getField("ping");
playerConnectionField = entityPlayerClass.getField("playerConnection");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public static Object getMinecraftServerInstance() throws InvocationTargetException, IllegalAccessException {
return getServerMethod.invoke(null);
}
public static double[] recentTPS() throws IllegalAccessException, InvocationTargetException {
final Object minecraftServerObj = getMinecraftServerInstance();
double[] recentTPS = (double[]) recentTPSField.get(minecraftServerObj);
return recentTPS;
}
public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
return Class.forName(nmsDir + "." + name);
}
public static Class<?> getOBCClass(String name) throws ClassNotFoundException {
return Class.forName(obcDir + "." + name);
}
public static Class<?> getNettyClass(String name) throws ClassNotFoundException {
return Class.forName(nettyPrefix + "." + name);
}
public static final String getChannelFutureListFieldName() {
if (version.isLowerThan(ServerVersion.v_1_8))
return "e";
if (version.isLowerThan(ServerVersion.v_1_13))
return "g";
return "f";
}
@Nullable
public static Entity getEntityById(final int id) {
return EntityFinderUtils.getEntityById(id);
}
@Nullable
public static Entity getEntityByIdWithWorld(final World world, final int id) {
return EntityFinderUtils.getEntityByIdWithWorld(world, id);
}
public static Object getNMSEntity(final Entity entity) {
final Object craftEntity = craftEntityClass.cast(entity);
try {
return getCraftEntityHandle.invoke(craftEntity);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object getCraftPlayer(final Player player) {
return craftPlayerClass.cast(player);
}
public static Object getEntityPlayer(final Player player) {
final Object craftPlayer = getCraftPlayer(player);
Object entityPlayer = null;
try {
return getCraftPlayerHandle.invoke(craftPlayer);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static int getPlayerPing(final Player player) {
Object entityPlayer = getEntityPlayer(player);
try {
return entityPlayerPingField.getInt(entityPlayer);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}
public static ItemStack toBukkitItemStack(final Object nmsItemstack) {
try {
return (ItemStack) asBukkitCopy.invoke(null, nmsItemstack);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static boolean is_1_8() {
return version.isHigherThan(ServerVersion.v_1_7_10)
&& version.isLowerThan(ServerVersion.v_1_9);
}
public static void sendSendableWrapper(final Player player, final Sendable sendable) {
sendNMSPacket(player, sendable.asNMSPacket());
}
public static void sendNMSPacket(final Player player, final Object nmsPacket) {
Object entityPlayer = getEntityPlayer(player);
Object playerConnection = null;
try {
playerConnection = playerConnectionField.get(entityPlayer);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
sendPacketMethod.invoke(playerConnection, nmsPacket);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
public static String getServerConnectionFieldName() {
return "p";
}
}
@@ -0,0 +1,94 @@
package io.github.retrooper.packetevents.utils.nms_entityfinder;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.annotations.Nullable;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class EntityFinderUtils {
@Nullable
private static ServerVersion version = PacketEvents.getServerVersion();
public static Entity getEntityById(final int id) {
for (final World world : Bukkit.getWorlds()) {
final Entity entity = getEntityByIdWithWorld(world, id);
if (entity != null) {
return entity;
}
}
return null;
}
@Nullable
public static Entity getEntityByIdWithWorld(final World world, final int id) {
if(world == null) {
return null;
}
Object craftWorld = craftWorldClass.cast(world);
Object worldServer = null;
try {
worldServer = craftWorldGetHandle.invoke(craftWorld);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
Object nmsEntity = null;
try {
nmsEntity = getEntityByIdMethod.invoke(worldServer, id);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
if(nmsEntity == null) {
return null;
}
try {
return (Entity) getBukkitEntity.invoke(nmsEntity);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> worldServerClass;
private static Class<?> craftWorldClass;
private static Class<?> entityClass;
private static Method getEntityByIdMethod;
private static Method craftWorldGetHandle;
private static Method getBukkitEntity;
static {
try {
worldServerClass = NMSUtils.getNMSClass("WorldServer");
craftWorldClass = NMSUtils.getOBCClass("CraftWorld");
entityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
getEntityByIdMethod = worldServerClass.getMethod(getEntityByNameMethodName(), int.class);
craftWorldGetHandle = craftWorldClass.getMethod("getHandle");
getBukkitEntity = entityClass.getMethod("getBukkitEntity");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static String getEntityByNameMethodName() {
if (version.isHigherThan(ServerVersion.v_1_7_10) && version.isLowerThan(ServerVersion.v_1_9)) {
return "a";
}
return "getEntity";
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public final class Vector3d {
public double x, y, z;
public Vector3d(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public final class Vector3f {
public float x, y, z;
public Vector3f(final float x, final float y, final float z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public final class Vector3i {
public int x, y, z;
public Vector3i(final int x, final int y, final int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents;
import me.purplex.packetevents.customlistener.injector.PacketInjector;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.example.TestExample;
import org.bukkit.Bukkit;
import org.bukkit.event.*;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin implements Listener {
private static Main instance;
private static PacketInjector packetInjector;
@Override
public void onEnable() {
instance = this;
Bukkit.getPluginManager().registerEvents(this, this);
packetInjector = new PacketInjector();
PacketEvents.getPacketManager().registerPacketListener(new TestExample());
Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, new Runnable() {
@Override
public void run() {
long now = System.currentTimeMillis();
PacketEvents.getPacketManager().callServerTickEvent(new ServerTickEvent(now));
}
}, 0L, 1L);
}
@Override
public void onDisable() {
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
packetInjector.injectPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
packetInjector.uninjectPlayer(e.getPlayer());
}
public static Main getInstance() {
return instance;
}
}
@@ -1,20 +0,0 @@
package me.purplex.packetevents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.manager.PacketManager;
public class PacketEvents {
private static PacketManager packetManager;
public static ServerVersion getServerVersion() {
return ServerVersion.getVersion();
}
public static PacketManager getPacketManager() {
if (packetManager == null) {
packetManager = new PacketManager();
}
return packetManager;
}
}
@@ -1,118 +0,0 @@
package me.purplex.packetevents.customlistener.injector;
import io.netty.channel.*;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.*;
import org.bukkit.entity.Player;
public class PacketInjector {
private final static ServerVersion version = ServerVersion.getVersion();
public void injectPlayer(Player player) {
ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
String packetName = packet.getClass().getSimpleName();
PacketReceiveEvent e = new PacketReceiveEvent(player, packetName, packet);
PacketEvents.getPacketManager().callPacketReceiveEvent(e);
if(e.isCancelled()) {
return;
}
try {
super.channelRead(ctx, packet);
} catch (Exception exception) {
exception.printStackTrace();
}
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) {
String packetName = packet.getClass().getSimpleName();
PacketSendEvent e = new PacketSendEvent(player, packetName, packet);
PacketEvents.getPacketManager().callPacketSendEvent(e);
if(e.isCancelled()) {
return;
}
try {
super.write(ctx, packet, promise);
} catch (Exception exception) {
exception.printStackTrace();
}
}
};
Channel channel = getChannel(player);
ChannelPipeline pipeline = channel.pipeline();
pipeline.addBefore("packet_handler", player.getName(), channelDuplexHandler);
}
public void uninjectPlayer(Player player) {
Channel channel = getChannel(player);
channel.eventLoop().submit(()->{
channel.pipeline().remove(player.getName());
return null;
});
}
public Channel getChannel(Player player) {
Channel channel = null;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
try {
channel = (Channel) networkManager.getClass().getField("i").get(networkManager);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
else if(version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.k;
}
else if(version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_10) {
net.minecraft.server.v1_10_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_11) {
net.minecraft.server.v1_11_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_12) {
net.minecraft.server.v1_12_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_14) {
net.minecraft.server.v1_14_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_15) {
net.minecraft.server.v1_15_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else {
System.err.println("Version unsupported, please contact purplex#0001 and tell him what version your server is running on! Make sure you are using paperspigot or spigot.");
}
return channel;
}
}
@@ -1,5 +0,0 @@
package me.purplex.packetevents.enums;
public enum EntityUseAction {
INTERACT, INTERACT_AT, ATTACK, INVALID;
}
@@ -1,24 +0,0 @@
package me.purplex.packetevents.enums;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
public enum ServerVersion
{
v_1_8, v_1_8_3, v_1_8_8, v_1_9, v_1_9_4, v_1_10, v_1_11, v_1_12, v_1_13, v_1_13_2, v_1_14, v_1_15,
ERROR;
public static ServerVersion getVersion() {
ServerVersion[] vals = values();
ArrayUtils.reverse(vals);
for(ServerVersion val : vals) {
String valName = val.name().substring(2).replace("_", ".");
if(Bukkit.getBukkitVersion().contains(valName)) {
return val;
}
}
return ERROR;
}
}
@@ -1,6 +0,0 @@
package me.purplex.packetevents.events;
public class PacketEvent {
}
@@ -1,20 +0,0 @@
package me.purplex.packetevents.events.eventmanager;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.PacketReceiveEvent;
import me.purplex.packetevents.events.packetevent.PacketSendEvent;
import java.util.LinkedList;
public interface PacketEventManager {
public LinkedList<PacketListener> packetListeners = new LinkedList<>();
public void callPacketReceiveEvent(PacketReceiveEvent e);
public void callPacketSendEvent(PacketSendEvent e);
public void registerPacketListener(PacketListener e);
public void unregisterPacketListener(PacketListener e);
public void callServerTickEvent(ServerTickEvent e);
}
@@ -1,4 +0,0 @@
package me.purplex.packetevents.events.listener;
public interface PacketListener {
}
@@ -1,77 +0,0 @@
package me.purplex.packetevents.events.manager;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.eventmanager.PacketEventManager;
import me.purplex.packetevents.events.handler.PacketHandler;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.PacketReceiveEvent;
import me.purplex.packetevents.events.packetevent.PacketSendEvent;
import java.lang.reflect.Method;
public class PacketManager implements PacketEventManager {
@Override
public void callPacketReceiveEvent(PacketReceiveEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
@Override
public void callPacketSendEvent(PacketSendEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
@Override
public void registerPacketListener(PacketListener e) {
this.packetListeners.add(e);
}
@Override
public void unregisterPacketListener(PacketListener e) {
this.packetListeners.remove(e);
}
@Override
public void callServerTickEvent(ServerTickEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
}
@@ -1,270 +0,0 @@
package me.purplex.packetevents.events.packetevent;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.PacketEvent;
import org.bukkit.entity.Player;
public class PacketSendEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
private final long timestamp;
private boolean cancelled;
public final ServerVersion version;
public PacketSendEvent(Player player, String packetName, Object packet) {
this.version = PacketEvents.getServerVersion();
this.player = player;
this.name = packetName;
this.packet = packet;
this.timestamp = (System.nanoTime() / 1000000);
this.cancelled = false;
}
public Player getPlayer() {
return this.player;
}
public String getPacketName() {
return this.name;
}
/**
* Get the raw packet object
*
* @return nmsPacket
*/
public Object getPacket() {
return this.packet;
}
public long getTimestamp() {
return timestamp;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public boolean isCancelled() {
return cancelled;
}
/*
/**
* Get the player's ping in the EntityPlayer's class
* @return ping
* @throws VersionNotFoundException
public int getPing() throws VersionNotFoundException {
int ping;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_10_2) {
net.minecraft.server.v1_10_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_11_1 || version == ServerVersion.v_1_11_2) {
net.minecraft.server.v1_11_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_12_1 || version == ServerVersion.v_1_12_2) {
net.minecraft.server.v1_12_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
}
else if (version == ServerVersion.v_1_14 || version == ServerVersion.v_1_14_1) {
net.minecraft.server.v1_14_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else if (version == ServerVersion.v_1_15_1) {
net.minecraft.server.v1_15_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer)player).getHandle();
ping = ePlayer.ping;
} else {
throw new VersionNotFoundException();
}
return ping;
}
/**
* Get the motX variable in the EntityPlayer class
*
* @return motX
public double getMotX() throws VersionNotFoundException {
double motX;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_10_2) {
net.minecraft.server.v1_10_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_11_1 || version == ServerVersion.v_1_11_2) {
net.minecraft.server.v1_11_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_12_1 || version == ServerVersion.v_1_12_2) {
net.minecraft.server.v1_12_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
} else if (version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer)player).getHandle();
motX = ePlayer.motX;
}
else if (version == ServerVersion.v_1_14 || version == ServerVersion.v_1_14_1) {
net.minecraft.server.v1_14_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.getMot().getX();
} else if (version == ServerVersion.v_1_15_1) {
net.minecraft.server.v1_15_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer)player).getHandle();
motX = ePlayer.getMot().getX();
} else {
throw new VersionNotFoundException();
}
return motX;
}
/**
* Get the motY variable in the EntityPlayer class
*
* @return motY
public double getMotY() throws VersionNotFoundException {
double motY;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_10_2) {
net.minecraft.server.v1_10_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_11_1 || version == ServerVersion.v_1_11_2) {
net.minecraft.server.v1_11_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_12_1 || version == ServerVersion.v_1_12_2) {
net.minecraft.server.v1_12_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
} else if (version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer)player).getHandle();
motY = ePlayer.motY;
}
else if (version == ServerVersion.v_1_14 || version == ServerVersion.v_1_14_1) {
net.minecraft.server.v1_14_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.getMot().getY();
} else if (version == ServerVersion.v_1_15_1) {
net.minecraft.server.v1_15_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer)player).getHandle();
motY = ePlayer.getMot().getY();
} else {
throw new VersionNotFoundException();
}
return motY;
}
/**
* Get the motZ variable in the EntityPlayer class
*
* @return motZ
public double getMotZ() throws VersionNotFoundException {
double motZ;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_10_2) {
net.minecraft.server.v1_10_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_11_1 || version == ServerVersion.v_1_11_2) {
net.minecraft.server.v1_11_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_12_1 || version == ServerVersion.v_1_12_2) {
net.minecraft.server.v1_12_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
} else if (version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.motZ;
}
else if (version == ServerVersion.v_1_14 || version == ServerVersion.v_1_14_1) {
net.minecraft.server.v1_14_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.getMot().getZ();
} else if (version == ServerVersion.v_1_15_1) {
net.minecraft.server.v1_15_R1.EntityPlayer ePlayer = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer)player).getHandle();
motZ = ePlayer.getMot().getZ();
} else {
throw new VersionNotFoundException();
}
return motZ;
}
*/
}
@@ -1,19 +0,0 @@
package me.purplex.packetevents.events.packetevent;
import me.purplex.packetevents.events.PacketEvent;
public class ServerTickEvent extends PacketEvent {
private long timestamp;
public ServerTickEvent(long timestamp) {
this.timestamp = timestamp;
}
public long getTimestamp() {
return timestamp;
}
}
@@ -1,99 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_10.WrappedPacketPlayInUseEntity_1_10;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_11.WrappedPacketPlayInUseEntity_1_11;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_12.WrappedPacketPlayInUseEntity_1_12;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_13.WrappedPacketPlayInUseEntity_1_13;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_13_2.WrappedPacketPlayInUseEntity_1_13_2;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_14.WrappedPacketPlayInUseEntity_1_14;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_15.WrappedPacketPlayInUseEntity_1_15;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8.WrappedPacketPlayInUseEntity_1_8;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_3.WrappedPacketPlayInUseEntity_1_8_3;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8.WrappedPacketPlayInUseEntity_1_8_8;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_9.WrappedPacketPlayInUseEntity_1_9;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_9_4.WrappedPacketPlayInUseEntity_1_9_4;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
if (version == ServerVersion.v_1_8) {
this.entity = new WrappedPacketPlayInUseEntity_1_8(packet).getEntity();
} else if (version == ServerVersion.v_1_8_3) {
this.entity = new WrappedPacketPlayInUseEntity_1_8_3(packet).getEntity();
} else if (version == ServerVersion.v_1_8_8) {
this.entity = new WrappedPacketPlayInUseEntity_1_8_8(packet).getEntity();
} else if (version == ServerVersion.v_1_9) {
this.entity = new WrappedPacketPlayInUseEntity_1_9(packet).getEntity();
} else if (version == ServerVersion.v_1_9_4) {
this.entity = new WrappedPacketPlayInUseEntity_1_9_4(packet).getEntity();
} else if (version == ServerVersion.v_1_10) {
this.entity = new WrappedPacketPlayInUseEntity_1_10(packet).getEntity();
} else if (version == ServerVersion.v_1_11) {
this.entity = new WrappedPacketPlayInUseEntity_1_11(packet).getEntity();
} else if (version == ServerVersion.v_1_12) {
this.entity = new WrappedPacketPlayInUseEntity_1_12(packet).getEntity();
} else if (version == ServerVersion.v_1_13) {
this.entity = new WrappedPacketPlayInUseEntity_1_13(packet).getEntity();
} else if (version == ServerVersion.v_1_13_2) {
this.entity = new WrappedPacketPlayInUseEntity_1_13_2(packet).getEntity();
} else if (version == ServerVersion.v_1_14) {
this.entity = new WrappedPacketPlayInUseEntity_1_14(packet).getEntity();
} else if (version == ServerVersion.v_1_15) {
this.entity = new WrappedPacketPlayInUseEntity_1_15(packet).getEntity();
}
}
private void setupAction() {
if (version == ServerVersion.v_1_8) {
this.action = new WrappedPacketPlayInUseEntity_1_8(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_8_3) {
this.action = new WrappedPacketPlayInUseEntity_1_8_3(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_8_8) {
this.action = new WrappedPacketPlayInUseEntity_1_8_8(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_9) {
this.action = new WrappedPacketPlayInUseEntity_1_9(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_9_4) {
this.action = new WrappedPacketPlayInUseEntity_1_9_4(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_10) {
this.action = new WrappedPacketPlayInUseEntity_1_10(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_11) {
this.action = new WrappedPacketPlayInUseEntity_1_11(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_12) {
this.action = new WrappedPacketPlayInUseEntity_1_12(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_13) {
this.action = new WrappedPacketPlayInUseEntity_1_13(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_13_2) {
this.action = new WrappedPacketPlayInUseEntity_1_13_2(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_14) {
this.action = new WrappedPacketPlayInUseEntity_1_14(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_15) {
this.action = new WrappedPacketPlayInUseEntity_1_15(packet).getEntityUseAction();
}
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_10;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_10 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_10(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_10_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_10_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_10_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_10_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_10_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_10_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_10_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_10_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_11;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_11 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_11(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_11_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_11_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_11_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_11_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_11_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_11_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_11_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_11_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_12;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_12 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_12(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_12_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_12_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_12_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_12_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_12_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_12_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_12_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_12_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_13;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_13_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_13_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_13 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_13(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_13_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_13_2;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.entity.Entity;
import net.minecraft.server.v1_13_R2.PacketPlayInUseEntity;
import net.minecraft.server.v1_13_R2.WorldServer;
public class WrappedPacketPlayInUseEntity_1_13_2 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_13_2(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (net.minecraft.server.v1_13_R2.PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_13_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_14;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_14_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_14 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_14(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_14_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_14_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_14_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_15;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_15_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_15_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_15 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_15(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_15_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
}
private void setupAction() {
net.minecraft.server.v1_8_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_3;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8_3 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8_3(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_8_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R2.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R2.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R2.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R2.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_8_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R2.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,27 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8;
import java.lang.Object;
public class PacketPlayInAbilities_1_8_8 {
private Object packet;
public PacketPlayInAbilities_1_8_8(Object packet) {
this.packet = packet;
setupFields();
}
private void setupA() {
}
private void setupFields() {
setupA();
}
public boolean a;
public boolean isFlying;
public boolean c;
public boolean d;
public float e;
public float f;
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8_8 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8_8(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_8_R3.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R3.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R3.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R3.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R3.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R3.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_8_R3.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R3.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_9;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_9 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_9(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_9_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_9_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_9_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_9_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_9_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_9_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_9_4;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_9_4 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_9_4(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_9_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R2.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_9_R2.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_9_R2.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_9_R2.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_9_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_9_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R2.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.example;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.handler.PacketHandler;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.*;
import me.purplex.packetevents.events.packetevent.packet.impl.in.WrappedPacketPlayInUseEntity;
import me.purplex.packetevents.packets.Packet;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class TestExample implements PacketListener {
/**
* How to register a packet listener?
* <p>
* PacketEvents.getPacketManager().registerPacketListener(new TestExample());
*/
private int tick;
private static ServerVersion serverVersion = ServerVersion.getVersion();
@PacketHandler
public void onPacketReceive(PacketReceiveEvent e) {
Player p = e.getPlayer();
//ONLY CLIENT PACKETS ALLOWED HERE!
//System.out.println(e.getPacket().getClass().getSimpleName());
if (e.getPacketName().equals(Packet.Client.USE_ENTITY)) {
WrappedPacketPlayInUseEntity packet = new WrappedPacketPlayInUseEntity(e.getPacket());
Entity entity = packet.getEntity();
if (packet.getEntityUseAction() == EntityUseAction.ATTACK) {
double dist = entity.getLocation().distanceSquared(p.getLocation());
//p.sendMessage("dist: " + dist);
}
}
}
@PacketHandler
public void onServerTick(ServerTickEvent e) {
//CALLED EVERY TICK
tick++;
if (tick % 20 == 0) {
/*for (Player p : Bukkit.getOnlinePlayers()) {
p.sendMessage("One second has passed!");
}*/
}
}
}
@@ -1,73 +0,0 @@
package me.purplex.packetevents.packets;
public abstract class Packet {
public static class Client {
private static final String CLIENT = "PacketPlayIn";
public static final String KEEP_ALIVE = CLIENT + "KeepAlive";
@Deprecated
public static final String FLYING = CLIENT + "Flying";
public static final String POSITION = CLIENT + "Position";
public static final String POSITION_LOOK = CLIENT + "PositionLook";
public static final String LOOK = CLIENT + "Look";
@Deprecated
public static final String LEGACY_POSITION = FLYING + "$" + CLIENT + "Position";
@Deprecated
public static final String LEGACY_POSITION_LOOK = FLYING + "$" + CLIENT + "PositionLook";
@Deprecated
public static final String LEGACY_LOOK = FLYING + "$" + CLIENT + "Look";
public static final String TRANSACTION = CLIENT + "Transaction";
public static final String BLOCK_DIG = CLIENT + "BlockDig";
public static final String ENTITY_ACTION = CLIENT + "EntityAction";
public static final String USE_ENTITY = CLIENT + "UseEntity";
public static final String WINDOW_CLICK = CLIENT + "WindowClick";
public static final String STEER_VEHICLE = CLIENT + "SteerVehicle";
public static final String CUSTOM_PAYLOAD = CLIENT + "CustomPayload";
public static final String ARM_ANIMATION = CLIENT + "ArmAnimation";
public static final String BLOCK_PLACE_1_9 = CLIENT + "BlockPlace1_9";
public static final String BLOCK_PLACE = CLIENT + "BlockPlace";
public static final String ABILITIES = CLIENT + "Abilities";
public static final String HELD_ITEM_SLOT = CLIENT + "HeldItemSlot";
public static final String CLOSE_WINDOW = CLIENT + "CloseWindow";
public static final String TAB_COMPLETE = CLIENT + "TabComplete";
public static final String CHAT = CLIENT + "Chat";
public static final String CREATIVE_SLOT = CLIENT + "SetCreativeSlot";
public static final String CLIENT_COMMAND = CLIENT + "ClientCommand";
}
public static class Server {
private static final String SERVER = "PacketPlayOut";
public static final String ANIMATION = SERVER + "Animation";
public static final String KEEP_ALIVE = SERVER + "KeepAlive";
public static final String CHAT = SERVER + "Chat";
public static final String POSITION = SERVER + "Position";
public static final String TRANSACTION = SERVER + "Transaction";
public static final String NAMED_ENTITY_SPAWN = SERVER + "NamedEntitySpawn";
public static final String SPAWN_ENTITY_LIVING = SERVER + "SpawnEntityLiving";
public static final String SPAWN_ENTITY = SERVER + "SpawnEntity";
public static final String CUSTOM_PAYLOAD = SERVER + "CustomPayload";
public static final String ABILITIES = SERVER + "Abilities";
public static final String ENTITY_METADATA = SERVER + "EntityMetadata";
public static final String ENTITY_VELOCITY = SERVER + "EntityVelocity";
public static final String ENTITY_DESTROY = SERVER + "EntityDestroy";
public static final String ENTITY_HEAD_ROTATION = SERVER + "EntityHeadRotation";
public static final String BLOCK_CHANGE = SERVER + "BlockChange";
public static final String CLOSE_WINDOW = SERVER + "CloseWindow";
public static final String HELD_ITEM = SERVER + "HeldItemSlot";
public static final String TAB_COMPLETE = SERVER + "TabComplete";
public static final String RESPAWN = SERVER + "Respawn";
public static final String WORLD_PARTICLE = SERVER + "WorldParticles";
public static final String COMMANDS = SERVER + "Commands";
public static final String OPEN_WINDOW = SERVER + "OpenWindow";
public static final String LOGIN = SERVER + "Login";
public static final String SERVER_DIFFICULTY = SERVER + "ServerDifficulty";
}
public static class Login {
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
public static final String PING = "PacketStatusInPing";
public static final String START = "PacketStatusInStart";
public static final String SUCCESS = "PacketLoginOutSuccess";
}
}
-4
View File
@@ -1,4 +0,0 @@
name: PacketEvents
version: ${project.version}
main: me.purplex.packetevents.Main
authors: [purplex]