Compare commits

..
60 Commits
Author SHA1 Message Date
purplexdev 50efff2819 Updated to 1.3.6
* Forgot to uninject on quit
2020-06-25 22:09:16 +02:00
purplexdev af325f9a62 Forgot to uninject onquit! 2020-06-25 22:08:41 +02:00
purplexdev fe29188e3f 1.3.5.2 Release, Bug fixed with position class & position look class and look class loading too late making them null! 2020-06-25 17:40:36 +02:00
purplexdev b753a98971 Issue with netty, receive and send event were mixed 2020-06-25 17:37:05 +02:00
purplexdev c73d88a7e2 Merge remote-tracking branch 'origin/master' 2020-06-25 15:13:32 +02:00
purplexdev bd872bc271 1.3.5.1
* Marked ProtocolSupport & ViaVersion as "provided" so they are not compiled into your plugin!
2020-06-25 15:13:03 +02:00
retrooper c0c03a0629 updated readme credit to release 1.3.5 2020-06-25 13:35:53 +02:00
purplexdev 18f3f135c8 Merge remote-tracking branch 'origin/master' 2020-06-25 13:16:04 +02:00
purplexdev 0304d0ac5a 1.3.5 Release STABLE!
* TinyProtocol removed
* API Size way smaller
* PlayerUninjectEvent is now called
* Version lookup methods re-added, but version lookup is only possible with ProtocolSupport or ViaVersion plugin avaialable on the server.
If you try looking up version and none of the listed plugins could be found, you will result with ClientVersion.ACCESS_FAILURE

* WrappedPacketOutAbilities sendable wrapper added
* PostPlayerInjectEvent has been deprecated, please use PlayerInjectEvent
* PlayerUninjectEvent now cancellable
* PlayerInjectEvent or PlayerUninjectEvent cancelling, will cancel the action.
* pom.xml version updated to 1.3.5
* Packet class has been deprecated, please use PacketType instead!
* Packet.isInstanceOfFlyingPacket(nmsPacket) -> PacketType.Util.isInstanceOfFlyingPacket(nmsPacket), and more instanceof functions are added in the PacketType.Util class too!
* PacketReceiveEvent#getPacket() is deprecated, please use PacketReceiveEvent#getNMSPacket()
* PacketSendEvent#getPacket() is deprecated, please use PacketSendEvent#getNMSPacket()
* PacketEvents.setShouldKickOnRestart(boolean) removed
2020-06-25 13:15:34 +02:00
retrooper 643fa1ad18 updated credits to fit latest commit 2020-06-22 22:43:50 +02:00
retrooper 5c65874749 remove plugin.yml 2020-06-22 22:36:27 +02:00
purplexdev 5a4db46427 1.3.4.1 UNTESTED!
Completely removed TinyProtocol, please test it, I will be able to fix any bugs tomorrow!
2020-06-22 22:31:14 +02:00
purplexdev 305d376128 1.3.4 RELEASE, This is probably one of my most important releases, this is the last release using TinyProtocol!
Changelog:
* Clientbound Abilities wrapper added and is sendable to clients

* Clientbound Health update wrapper added and is also sendable to clients

Info:
TinyProtocol helped us listen to some login and handshake packets!
But it also came with a lot of bugs and problems to deal with, even today there are still some bugs and many people using this API have complained about it.

I will now stop using TinyProtocol.

WHAT WILL THIS MEAN?

There will be lots of pro's and con's.

Pros:
* No more issues with reloading
* Smaller file size

Cons:
* Version lookup will now only be possible with dependencies like ViaVersion.
* Soft depend on via version as mentioned above. Soft depend meaning that if you want to lookup versions, ViaVersion api is required to be provided.

* All login wrappers and the login event will be removed!

It is very important that PacketEvents is stable and people shouldn't be constantly running into issues!
I am releasing this version with TinyProtocol for the users that will miss and still want TinyProtocol.
2020-06-22 21:07:34 +02:00
purplexdev 4308936c1a * Bukkit move event added
* In and Out going transaction packet wrapper added (request of Hades developer)
2020-06-22 19:27:12 +02:00
purplexdev 87b0ac9295 * Updated the default value of PacketEvent#timestamp to the non deprecated method PacketEvents#highlyPreciseMillis() 2020-06-21 17:18:32 +02:00
purplexdev 3dee3b2a0e Bug fixes!
* Blockplace_1_9 wrapper error fixed
* Blockplace 1_7 wrapper is now being used
* PacketEvents#currentCalculatedMS() now deprecated, please use PacketEvents#highlyPreciseMillis() or System#currentTimeMillis() depending on what you need, please read the documentation of PacketEvents#highlyPreciseMillis().
2020-06-21 16:48:41 +02:00
purplexdev c2f0e30511 Updated pom.xml version to 1.3.3.1 2020-06-18 16:19:12 +02:00
purplexdev a824a70cc6 Lots of code cleaned up, appended some code to the MainExample.java, added an option to kick all online players when the PacketEvents.stop() function is called( JavaPlugin#onDisable() ) 2020-06-18 15:44:53 +02:00
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
78 changed files with 2340 additions and 2965 deletions

No files matched your search

+17 -16
View File
@@ -1,29 +1,30 @@
# packetevents by retrooper
An asynchronous spigot packetListener coded by retrooper.
A lightweight spigot packetlistener & packetsender coded by retrooper.
Credit to TinyProtocol, 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 to support 1.7.10 & 1.8.
PacketEvents does some extra modifications to support the rest of the versions!
All I do is make the wrapper classes and useful utilities that support 1.7.10 -> 1.15.2!
This packetlistener is supported on spigot servers(Spigot, PaperSpigot, ...).
## Credit
PacketEvents uses [TinyProtocol](https://github.com/dmulloy2/ProtocolLib/blob/master/TinyProtocol)'s [Reflection](https://github.com/dmulloy2/ProtocolLib/blob/master/TinyProtocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java) util class.
[Find it here in our source](https://github.com/retrooper/packetevents/blob/master/src/main/java/io/github/retrooper/packetevents/reflectionutils/Reflection.java)
PacketEvents forked [Atlas](https://github.com/funkemunky/Atlas)' [Packet](https://github.com/funkemunky/Atlas/blob/master/AtlasParent/Atlas/src/main/java/cc/funkemunky/api/tinyprotocol/api/Packet.java) class.
[Find our forked version](https://github.com/retrooper/packetevents/blob/master/src/main/java/io/github/retrooper/packetevents/packet/PacketType.java)
## About
This packetlistener is **only** supported on spigot servers and has been tested to work on these spigot forks: PaperSpigot, Tuinity
* No dependencies
* Licensed with the GPL2 license.
* Licensed under the GPL2 license.
[![](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
How to use with **Gradle, Maven, sbt and leiningen**.
Click the link below.
Make sure to replace **Tag** with a proper release version or a valid commit hash(first 7 characters)
I recommend you to use the latest released version!
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
If clicking the badge doesn't work paste this link into your browser http://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)
+17 -100
View File
@@ -6,7 +6,7 @@
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.2.8</version>
<version>1.3.6</version>
<packaging>jar</packaging>
<name>packetevents</name>
<properties>
@@ -56,70 +56,20 @@
<id>funkemunky-releases</id>
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.14.1</artifactId>
<version>1.14.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.15.1</artifactId>
<version>1.15.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.14.3</artifactId>
<version>1.14.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.14.2</artifactId>
<version>1.14.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.15</artifactId>
<version>1.15</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.15.2</artifactId>
<version>1.15.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.13.2</artifactId>
<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>
<version>1.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.8.3</artifactId>
<version>1.8.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.8.8</artifactId>
@@ -127,57 +77,24 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.9</artifactId>
<version>1.9</version>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.9.4</artifactId>
<version>1.9.4</version>
<groupId>com.github.ProtocolSupport</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>4fdd683</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.10.2</artifactId>
<version>1.10.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.11.1</artifactId>
<version>1.11.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.11.2</artifactId>
<version>1.11.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.12.1</artifactId>
<version>1.12.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.12.2</artifactId>
<version>1.12.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.13</artifactId>
<version>1.13</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.14</artifactId>
<version>1.14</version>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.50.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -1,101 +1,258 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.annotations.NotNull;
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.impl.ServerTickEvent;
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.injector.PacketHandler;
import io.github.retrooper.packetevents.handler.NettyPacketHandler;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.InvocationTargetException;
public class PacketEvents{
import java.util.HashMap;
import java.util.UUID;
public final class PacketEvents implements PacketListener, Listener {
private static final ServerVersion version = ServerVersion.getVersion();
private static final EventManager eventManager = new EventManager();
private static boolean hasRegistered;
private static PacketEvents instance;
public static JavaPlugin plugin;
private static PacketHandler packetInjector;
private static EventManager eventManager = new EventManager();
private static int currentTick;
private static BukkitTask serverTickTask;
private static final HashMap<UUID, ClientVersion> clientVersionsMap = new HashMap<UUID, ClientVersion>();
public static EventManager getEventManager() {
return eventManager;
}
public static void setup(final JavaPlugin plugin, final boolean serverTickEventEnabled) {
PacketEvents.plugin = plugin;
packetInjector = new PacketHandler(plugin);
packetInjector.initTinyProtocol();
/**
* 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());
if (serverTickEventEnabled) {
final Runnable runnable = new Runnable() {
Bukkit.getPluginManager().registerEvents(getInstance(), plugin);
//Start the server tick task
final Runnable tickRunnable = new Runnable() {
@Override
public void run() {
getEventManager().callEvent(new ServerTickEvent(currentTick++, PacketEvents.currentTimeMS()));
getEventManager().callEvent(new ServerTickEvent(currentTick++, PacketEvents.highlyPreciseMillis()));
}
};
serverTickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, 0L, 1L);
serverTickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, tickRunnable, 0L, 1L);
hasRegistered = true;
}
}
public static void cleanup() {
/**
* Stop all tasks and unregisters all PacketEvents' 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;
}
public static boolean isServerTickTaskEnabled() {
return serverTickTask != null;
}
/**
* Get the server's recent TPS values
* TPS stands for ticks per second.
* See to learn more about TPS<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 e) {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
final int size = tpsArray.length;
for (int i = 0; i < size; i++) {
if (tpsArray[i] > 20.0) {
tpsArray[i] = 20.0;
}
}
return tpsArray;
}
/**
* Get the server's current TPS
* TPS stands for ticks per second.
* See to learn more about TPS <a href="https://apexminecrafthosting.com/what-is-minecraft-tps/">"https://apexminecrafthosting.com/what-is-minecraft-tps/"</a>
*
* @return {@link PacketEvents#getRecentServerTPS()[0]}
*/
public static double getCurrentServerTPS() {
return getRecentServerTPS()[0];
}
public static int getPing(final Player player) {
/**
* 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(@NotNull final Player player) {
return NMSUtils.getPlayerPing(player);
}
public static long currentTimeMS() {
return System.currentTimeMillis();
/**
* When to use this(nano / 1 million) over {@link System#currentTimeMillis()}
* This is preciser than System.currentTimeMillis(), System.currentTimeMillis() can be up to 50ms off on some operating systems, but using this isn't cheap.
* Java documentation recommend using nano time if you are measuring elapsed time.
* In this function nanoTime is divided by 1 million giving us milliseconds.
* It is also important to mention that using this method doesn't guarantee thread safety.
*
* @return nanoTime / 1 million
*/
public static long highlyPreciseMillis() {
return System.nanoTime() / 1000000;
}
/**
* This is deprecated, use {@link #highlyPreciseMillis()} as they do the same thing, I just renamed the method.
*/
@Deprecated
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(@NotNull final Player player) {
return getClientVersion(player.getUniqueId());
}
public static ClientVersion getClientVersion(@NotNull final UUID uuid) {
return clientVersionsMap.get(uuid);
}
/**
* Version independent player injection
*
* @param player
*/
public static void injectPlayer(final Player player) {
NettyPacketHandler.injectPlayer(player);
}
/**
* Version independant player injection
*
* @param player
*/
public static void uninjectPlayer(final Player player) {
NettyPacketHandler.uninjectPlayer(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);
}
/**
* 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) {
clientVersionsMap.put(e.getPlayer().getUniqueId(), e.getClientVersion());
}
@PacketHandler
public void onReceive(final PacketReceiveEvent e) {
}
/**
* Deprecated, please do not use this anymore
*
* @param e
*/
@PacketHandler
public void onPostInject(final PostPlayerInjectEvent e) {
}
@EventHandler
public void onJoin(final PlayerJoinEvent e) {
injectPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(final PlayerQuitEvent e) {
uninjectPlayer(e.getPlayer());
}
@EventHandler
public void onMove(final PlayerMoveEvent e) {
PacketEvents.getEventManager().callEvent(new BukkitMoveEvent(e));
}
}
@@ -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;
/**
* 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 io.github.retrooper.packetevents.event;
package io.github.retrooper.packetevents.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -0,0 +1,100 @@
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, ACCESS_FAILURE;
public static ClientVersion fromProtocolVersion(final int protocolVersion) {
int remainder = -1;
switch (protocolVersion) {
case -1:
return ACCESS_FAILURE;
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;
}
}
@@ -1,9 +1,7 @@
package io.github.retrooper.packetevents.enums;
public enum Direction {
DOWN, UP, NORTH, SOUTH, WEST, EAST
,NORTH_EAST,
DOWN, UP, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
NORTH_WEST, SOUTH_EAST,
SOUTH_WEST, WEST_NORTH_WEST,
NORTH_NORTH_WEST, NORTH_NORTH_EAST,
@@ -8,9 +8,9 @@ public enum EntityAnimationType {
}
public final int getIndex() {
for(int i = 0; i < values().length; i++) {
for (int i = 0; i < values().length; i++) {
final EntityAnimationType curType = values()[0];
if(curType == this) {
if (curType == this) {
return i;
}
}
@@ -2,5 +2,5 @@ package io.github.retrooper.packetevents.enums;
public enum Hand {
MAIN_HAND,
OFF_HAND;
OFF_HAND
}
@@ -5,10 +5,12 @@ 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,
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, v_1_16,
ERROR;
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static ServerVersion getVersion() {
ServerVersion[] vals = values();
ArrayUtils.reverse(vals);
@@ -21,8 +23,6 @@ public enum ServerVersion {
return ERROR;
}
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static String getNmsSuffix() {
return nmsVersionSuffix;
}
@@ -53,14 +53,13 @@ public enum ServerVersion {
* @return
*/
public boolean isLowerThan(final ServerVersion version) {
if(version == this) return false;
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) {
if (v == this) {
return true;
}
else if(v == version) {
} else if (v == version) {
return false;
}
}
@@ -9,11 +9,12 @@ import io.github.retrooper.packetevents.enums.ServerVersion;
* recommended to avoid non thread safe bukkit operations
*/
public class PacketEvent {
protected long timestamp = PacketEvents.currentTimeMS();
protected static ServerVersion version = PacketEvents.getServerVersion();
protected long timestamp = PacketEvents.highlyPreciseMillis();
/**
* Timestamp of the packet
*
* @return
*/
public long getTimestamp() {
@@ -1,4 +1,4 @@
package io.github.retrooper.packetevents.event;
public interface PacketListener {
public interface PacketListener {
}
@@ -0,0 +1,35 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent;
public final class BukkitMoveEvent extends PacketEvent {
private final Player player;
private final Location to, from;
public BukkitMoveEvent(final Player player, final Location to, final Location from) {
this.player = player;
this.to = to;
this.from = from;
}
public BukkitMoveEvent(final PlayerMoveEvent e) {
this.player = e.getPlayer();
this.to = e.getTo();
this.from = e.getFrom();
}
public Player getPlayer() {
return player;
}
public Location getFrom() {
return from;
}
public Location getTo() {
return to;
}
}
@@ -1,20 +0,0 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
public class PacketLoginEvent extends PacketEvent {
private final String name;
private final Object packet;
public PacketLoginEvent(final String packetName, final Object packet) {
this.name = packetName;
this.packet = packet;
}
public String getPacketName() {
return name;
}
public Object getPacket() {
return packet;
}
}
@@ -3,7 +3,7 @@ package io.github.retrooper.packetevents.event.impl;
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;
@@ -34,21 +34,17 @@ public class PacketReceiveEvent extends PacketEvent {
}
/**
* Get the raw packet object
* This is deprecated, please us {@link #getNMSPacket()}
*
* @return packet
*/
@Deprecated
public Object getPacket() {
return this.packet;
}
/**
* Cancel the packet
*
* @param cancelled
*/
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
public Object getNMSPacket() {
return this.packet;
}
/**
@@ -59,4 +55,13 @@ public class PacketReceiveEvent extends PacketEvent {
public boolean isCancelled() {
return cancelled;
}
/**
* Cancel the packet
*
* @param cancelled
*/
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
@@ -4,7 +4,7 @@ import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PacketSendEvent extends PacketEvent {
public final class PacketSendEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
@@ -27,233 +27,30 @@ public class PacketSendEvent extends PacketEvent {
}
/**
* Get the raw packet object
* This is deprecated, please us {@link #getNMSPacket()}
*
* @return nmsPacket
* @return packet
*/
@Deprecated
public Object getPacket() {
return this.packet;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
/**
* Get the raw packet object
*
* @return packet
*/
public Object getNMSPacket() {
return this.packet;
}
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;
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* 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,16 +1,37 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.enums.ClientVersion;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.utils.VersionLookupUtils;
import org.bukkit.entity.Player;
public class PlayerInjectEvent extends PacketEvent {
public final class PlayerInjectEvent extends PacketEvent {
private final Player player;
private boolean cancelled;
private final ClientVersion clientVersion;
public PlayerInjectEvent(final Player player) {
this.player = player;
this.clientVersion = ClientVersion.fromProtocolVersion(VersionLookupUtils.getProtocolVersion(player));
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public void cancel() {
setCancelled(true);
}
public ClientVersion getClientVersion() {
return clientVersion;
}
public Player getPlayer() {
return player;
}
}
@@ -3,11 +3,24 @@ package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PlayerUninjectEvent extends PacketEvent {
public final class PlayerUninjectEvent extends PacketEvent {
private final Player player;
private boolean cancelled;
public PlayerUninjectEvent(final Player player) {
this.player =player;
this.player = player;
}
public void setCancelled(final boolean val) {
this.cancelled = val;
}
public void cancel() {
setCancelled(true);
}
public boolean isCancelled() {
return this.cancelled;
}
public Player getPlayer() {
@@ -0,0 +1,20 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
/**
* Please use {@link PlayerInjectEvent}
*/
@Deprecated
public final class PostPlayerInjectEvent extends PacketEvent {
private final Player player;
public PostPlayerInjectEvent(final Player player) {
this.player = player;
}
public Player getPlayer() {
return player;
}
}
@@ -1,21 +0,0 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
//unfinished
public class ServerReloadEvent extends PacketEvent {
private final long currentTime;
public ServerReloadEvent(final long currentTime){
this.currentTime = currentTime;
}
public ServerReloadEvent() {
this.currentTime = PacketEvents.currentTimeMS();
}
public final long getCurrentTime() {
return currentTime;
}
}
@@ -3,9 +3,10 @@ package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
public class ServerTickEvent extends 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;
@@ -1,7 +1,7 @@
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.PacketHandler;
import io.github.retrooper.packetevents.event.PacketListener;
import java.lang.reflect.InvocationTargetException;
@@ -9,18 +9,22 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EventManager {
public final class EventManager {
private HashMap<PacketListener, List<Method>> registeredMethods = new HashMap<PacketListener, List<Method>>();
private static final ExecutorService executorService = Executors.newCachedThreadPool();
private final 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) {
if (method.getParameterTypes()[0].equals(PacketEvent.class)
|| method.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
final Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.equals(PacketEvent.class)
|| parameterType.isInstance(e)) {
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
@@ -31,15 +35,20 @@ public class EventManager {
}
}
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)) {
if (m.isAnnotationPresent(PacketHandler.class)
&& m.getParameterTypes().length == 1) {
methods.add(m);
}
}
registeredMethods.put(e, methods);
if (!methods.isEmpty()) {
registeredMethods.put(e, methods);
}
}
public void unregisterListener(final PacketListener e) {
@@ -50,4 +59,7 @@ public class EventManager {
registeredMethods.clear();
}
public boolean isRegistered(final PacketListener listener) {
return registeredMethods.containsKey(listener);
}
}
@@ -1,59 +0,0 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.Location;
import org.bukkit.entity.Player;
/**
* Example packetevent
* Make sure to initiate the super timestamp variable,
* if you want to use the getTimestamp() function
*/
public class CustomMoveEvent extends PacketEvent {
private final Player player;
private Location to, from;
private boolean cancelled;
public CustomMoveEvent(final Player player, final Location to, final Location from) {
this.player = player;
this.to = to;
this.from = from;
this.cancelled = false;
//Timestamp is initialized automatically, so you don't need to initiate it, but you may modify it if you like
//this.timestamp = PacketEvents.currentTimeMS();
}
@Override
public long getTimestamp() {
return super.getTimestamp();
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public boolean isCancelled() {
return this.cancelled;
}
public Player getPlayer() {
return player;
}
public Location getTo() {
return to;
}
public Location getFrom() {
return from;
}
public void setTo(final Location loc) {
this.to = loc;
}
public void setFrom(final Location loc) {
this.from = from;
}
}
@@ -3,35 +3,17 @@ package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin {
public class MainExample extends JavaPlugin {
@Override
public void onEnable() {
PacketEvents.start(this);
//Should the ServerTickEvent ever get called?
final boolean serverTickEventEnabled = true;
/**
* Starts the servertickevent repeating task (if enabled)
* and registers onJoin and onQuit events to inject and uninject players.
* The first argument is an instance to your Main Class,
* The second argument is a boolean whether the servertickevent should ever get called
*/
PacketEvents.setup(this, serverTickEventEnabled);
/**
* Register TestExample's PacketListener
*/
PacketEvents.getEventManager().registerListener(new RegisteredListener());
PacketEvents.getServerTickTask().cancel();
}
@Override
public void onDisable() {
/**
* Stops server tick event task if enabled and unregister all listeners
*/
PacketEvents.cleanup();
PacketEvents.stop();
}
}
}
@@ -1,169 +0,0 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.enums.*;
import io.github.retrooper.packetevents.event.PacketEvent;
import io.github.retrooper.packetevents.event.PacketHandler;
import io.github.retrooper.packetevents.event.PacketListener;
import io.github.retrooper.packetevents.event.impl.*;
import io.github.retrooper.packetevents.packet.Packet;
import io.github.retrooper.packetevents.packetwrappers.in.abilities.WrappedPacketInAbilities;
import io.github.retrooper.packetevents.packetwrappers.in.blockdig.WrappedPacketInBlockDig;
import io.github.retrooper.packetevents.packetwrappers.in.blockplace.WrappedPacketInBlockPlace;
import io.github.retrooper.packetevents.packetwrappers.in.chat.WrappedPacketInChat;
import io.github.retrooper.packetevents.packetwrappers.in.entityaction.WrappedPacketInEntityAction;
import io.github.retrooper.packetevents.packetwrappers.in.flying.WrappedPacketInFlying;
import io.github.retrooper.packetevents.packetwrappers.in.keepalive.WrappedPacketInKeepAlive;
import io.github.retrooper.packetevents.packetwrappers.in.useentity.WrappedPacketInUseEntity;
import io.github.retrooper.packetevents.packetwrappers.out.chat.WrappedPacketOutChat;
import io.github.retrooper.packetevents.packetwrappers.out.entityvelocity.WrappedPacketOutEntityVelocity;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* Implementing PacketListener to listen to packets and packetevents' custom events,
*/
public class RegisteredListener implements PacketListener {
/**
* Listen to PacketReceiveEvent
*
* @param e PacketReceiveEvent
*/
@PacketHandler
public void onPacketReceive(PacketReceiveEvent e) {
final Player p = e.getPlayer();
final long timestamp = e.getTimestamp();
switch (e.getPacketName()) {
case Packet.Client.USE_ENTITY:
final WrappedPacketInUseEntity useEntity = new WrappedPacketInUseEntity(e.getPacket());
final Entity entity = useEntity.getEntity();
final double distanceSquared = entity.getLocation().distanceSquared(p.getLocation());
final EntityUseAction useAction = useEntity.getAction();
break;
case Packet.Client.ABILITIES:
final WrappedPacketInAbilities abilities = new WrappedPacketInAbilities(e.getPacket());
final boolean isVulnerable = abilities.isVulnerable();
final boolean isFlying = abilities.isFlying();
final boolean canFly = abilities.canFly();
final boolean canInstantlyBuild = abilities.canInstantlyBuild();
final float flySpeed = abilities.getFlySpeed();
final float walkSpeed = abilities.getWalkSpeed();
// e.getPlayer().sendMessage("walkspeed: " + walkSpeed + ", flyspeed: " + flySpeed + ", canFly: " + canFly);
break;
case Packet.Client.BLOCK_DIG:
//Custom PlayerDigType enum
final WrappedPacketInBlockDig blockDig = new WrappedPacketInBlockDig(e.getPacket());
final PlayerDigType type = blockDig.getDigType();
final Direction direction = blockDig.getDirection();
break;
case Packet.Client.FLYING:
final WrappedPacketInFlying flying = new WrappedPacketInFlying(e.getPacket());
final float pitch = flying.getPitch();
final float yaw = flying.getYaw();
break;
case Packet.Client.POSITION:
final WrappedPacketInFlying.WrappedPacketInPosition position =
new WrappedPacketInFlying.WrappedPacketInPosition(e.getPacket());
final boolean isPos = position.isPosition(); //true
break;
case Packet.Client.POSITION_LOOK:
final WrappedPacketInFlying.WrappedPacketInPosition_Look position_look =
new WrappedPacketInFlying.WrappedPacketInPosition_Look(e.getPacket());
final boolean isLook = position_look.isLook(); //true
break;
case Packet.Client.CHAT:
final WrappedPacketInChat chat = new WrappedPacketInChat(e.getPacket());
final String message = chat.getMessage();
if(message.contains("jump")) {
//teleport them up in the air
// PacketEvents.sendPacket(e.getPlayer(), new WrappedPacketOutEntityVelocity(e.getPlayer(), 0, 3, 0));
}
else if(message.contains("swing arm")) {
//Swing the player's arm
// PacketEvents.sendPacket(e.getPlayer(), new WrappedPacketOutAnimation(e.getPlayer(), EntityAnimationType.SWING_MAIN_ARM));
}
break;
case Packet.Client.BLOCK_PLACE:
final WrappedPacketInBlockPlace blockPlace = new WrappedPacketInBlockPlace(e.getPlayer(), e.getPacket());
final Vector3i blockPosition = blockPlace.getBlockPosition();
final Hand h = blockPlace.getHand();
final ItemStack stack = blockPlace.getItemStack();
break;
case Packet.Client.KEEP_ALIVE:
final WrappedPacketInKeepAlive keepAlive = new WrappedPacketInKeepAlive(e.getPacket());
final long responseID = keepAlive.getId();
break;
case Packet.Client.ENTITY_ACTION:
final WrappedPacketInEntityAction entityAction = new WrappedPacketInEntityAction(e.getPacket());
final PlayerAction action = entityAction.getAction();
final int jumpBoost = entityAction.getJumpBoost();
break;
}
}
/**
* I recommend you use the player inject event
* to register your players instead of any other bukkit event,
* to avoid any issues.
* @param event
*/
@PacketHandler
public void onInject(PlayerInjectEvent event) {
}
/**
* I recommend you use the player uninject event,
* to unregister your players
*
* You can also call this event to "whitelist" a player,
* our API won't even notice the player exists, so you won't
* be able to listen to any packets from the player
* @param e
*/
@PacketHandler
public void onUninject(PlayerUninjectEvent e) {
}
/**
* Another way to listen to packets
*
* @param e PacketEvent
*/
@PacketHandler
public void onPacket(PacketEvent e) {
if (e instanceof PacketSendEvent) {
final PacketSendEvent p = (PacketSendEvent) e;
final Player targetPlayer = p.getPlayer();
final Object rawNMSPacket = p.getPacket();
final long timestamp = p.getTimestamp();
if(p.getPacketName().equals(Packet.Server.ENTITY_VELOCITY)) {
final WrappedPacketOutEntityVelocity vel = new WrappedPacketOutEntityVelocity(p.getPacket());
final double velocityX = vel.getVelocityX();
final double velocityY = vel.getVelocityY();
final double velocityZ = vel.getVelocityZ();
}
else if(p.getPacketName().equals(Packet.Server.CHAT)) {
final WrappedPacketOutChat chat = new WrappedPacketOutChat(p.getPacket());
}
} else if (e instanceof CustomMoveEvent) {
final CustomMoveEvent event = (CustomMoveEvent) e;
final Player player = event.getPlayer();
final Location to = event.getTo();
final Location from = event.getFrom();
} else if (e instanceof ServerTickEvent) {
final ServerTickEvent event = (ServerTickEvent) e;
final int currentTick = event.getCurrentTick();
// System.out.println(PacketEvents.getCurrentServerTPS() + " is tps");
}
}
}
@@ -0,0 +1,61 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.event.impl.*;
import org.bukkit.entity.Player;
import java.util.concurrent.Future;
public class NettyPacketHandler {
public static final String handlerName = "PacketListener";
private static final ServerVersion version = PacketEvents.getServerVersion();
public static void injectPlayer(final Player player) {
final PlayerInjectEvent injectEvent = new PlayerInjectEvent(player);
PacketEvents.getEventManager().callEvent(injectEvent);
if (!injectEvent.isCancelled()) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
NettyPacketHandler_7.injectPlayer(player);
} else {
NettyPacketHandler_8.injectPlayer(player);
}
PacketEvents.getEventManager().callEvent(new PostPlayerInjectEvent(player));
}
}
public static Future<?> uninjectPlayer(final Player player) {
final PlayerUninjectEvent uninjectEvent = new PlayerUninjectEvent(player);
PacketEvents.getEventManager().callEvent(uninjectEvent);
if (!uninjectEvent.isCancelled()) {
if (version.isLowerThan(ServerVersion.v_1_8)) {
return NettyPacketHandler_7.uninjectPlayer(player);
} else {
return NettyPacketHandler_8.uninjectPlayer(player);
}
}
return null;
}
public static Object read(final Player receiver, final 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;
}
public static Object write(final Player sender, final Object packet) {
final String packetName = packet.getClass().getSimpleName();
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
if (!packetReceiveEvent.isCancelled()) {
return packet;
}
return null;
}
}
@@ -0,0 +1,44 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.utils.NMSUtils;
import net.minecraft.util.io.netty.channel.*;
import org.bukkit.entity.Player;
import java.util.concurrent.Future;
final class NettyPacketHandler_7 {
public static void injectPlayer(final Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Object packet = NettyPacketHandler.read(player, msg);
if(packet == null) {
return;
}
super.channelRead(ctx, msg);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
Object packet = NettyPacketHandler.write(player, msg);
if(packet == null) {
return;
}
super.write(ctx, msg, promise);
}
};
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
pipeline.addBefore(NettyPacketHandler.handlerName, player.getName(), channelDuplexHandler);
}
public static Future<?> uninjectPlayer(final Player player) {
final Channel channel = (Channel) NMSUtils.getChannel(player);
return channel.eventLoop().submit(new Runnable() {
@Override
public void run() {
channel.pipeline().remove(player.getName());
}
});
}
}
@@ -0,0 +1,46 @@
package io.github.retrooper.packetevents.handler;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.utils.NMSUtils;
import io.netty.channel.*;
import org.bukkit.entity.Player;
import java.util.concurrent.Future;
final class NettyPacketHandler_8 {
private static final ServerVersion version = PacketEvents.getServerVersion();
public static void injectPlayer(final Player player) {
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Object packet = NettyPacketHandler.write(player, msg);
if(packet == null) {
return;
}
super.channelRead(ctx, msg);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
Object packet = NettyPacketHandler.read(player, msg);
if(packet == null) {
return;
}
super.write(ctx, msg, promise);
}
};
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
pipeline.addBefore(NettyPacketHandler.handlerName, player.getName(), channelDuplexHandler);
}
public static Future<?> uninjectPlayer(final Player player) {
final Channel channel = (Channel) NMSUtils.getChannel(player);
return channel.eventLoop().submit(new Runnable() {
@Override
public void run() {
channel.pipeline().remove(player.getName());
}
});
}
}
@@ -1,28 +0,0 @@
package io.github.retrooper.packetevents.injector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import org.bukkit.plugin.Plugin;
public class PacketHandler {
private static final ServerVersion version = PacketEvents.getServerVersion();
private final Plugin plugin;
public PacketHandler(final Plugin plugin) {
this.plugin = plugin;
}
public void initTinyProtocol() {
if(version.isLowerThan(ServerVersion.v_1_8)) {
new PacketHandler_1_7(getPlugin()).initTinyProtocol();
}
else {
new PacketHandler_1_8(getPlugin()).initTinyProtocol();
}
}
public final Plugin getPlugin() {
return plugin;
}
}
@@ -1,47 +0,0 @@
package io.github.retrooper.packetevents.injector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
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 class PacketHandler_1_7 {
private final Plugin plugin;
public PacketHandler_1_7(final Plugin plugin) {
this.plugin = plugin;
}
public void initTinyProtocol() {
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();
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
if (!packetReceiveEvent.isCancelled()) {
return packet;
}
return null;
}
};
}
public Plugin getPlugin() {
return plugin;
}
}
@@ -1,69 +0,0 @@
package io.github.retrooper.packetevents.injector;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
import io.github.retrooper.packetevents.tinyprotocol.TinyProtocol8;
import io.netty.channel.Channel;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class PacketHandler_1_8 {
private static final ServerVersion version = PacketEvents.getServerVersion();
private final Plugin plugin;
public PacketHandler_1_8(final Plugin plugin) {
this.plugin = plugin;
}
public void initTinyProtocol() {
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();
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,84 @@
package io.github.retrooper.packetevents.mojang;
import com.mojang.authlib.properties.PropertyMap;
import java.util.UUID;
public final 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 && name.isEmpty()) {
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 && !getName().isEmpty();
}
public boolean isLegacy() {
return this.legacy;
}
public boolean equals(com.mojang.authlib.GameProfile profile) {
if (profile != null) {
return profile.getId() != null && getId() != null && profile.getId() == getId()
&& profile.getName() != null && getName() != null && profile.getName().equals(getName());
}
return false;
}
@Override
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) {
return this.name.equals(that.name);
} else return that.name == null;
} else {
return false;
}
}
@Override
public int hashCode() {
int result = this.id != null ? this.id.hashCode() : 0;
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "id: " + id + ", name: " + name + ", legacy: " + legacy;
}
}
@@ -1,13 +1,68 @@
package io.github.retrooper.packetevents.packet;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.utils.NMSUtils;
@Deprecated
public final class Packet {
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+
}
try {
packetPlayInPosition = NMSUtils.getNMSClass(Client.POSITION);
packetPlayInPositionLook = NMSUtils.getNMSClass(Client.POSITION_LOOK);
packetPlayInLook = NMSUtils.getNMSClass(Client.LOOK);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 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);
}
}
/**
* Is this NMS Packet an instanceof the "PacketPlayInPosition" or "PacketPlayInPositionLook"
* @param nmsPacket
* @return
*/
public static boolean isInstanceOfPositionOrPositionLook(final Object nmsPacket) {
return packetPlayInPosition.isInstance(nmsPacket) || packetPlayInPositionLook.isInstance(nmsPacket);
}
public static boolean isInstanceOfLook(final Object nmsPacket) {
return packetPlayInLook.isInstance(nmsPacket);
}
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";
@@ -23,7 +78,11 @@ public abstract class Packet {
public static final String STEER_VEHICLE = c + "SteerVehicle";
public static final String CUSTOM_PAYLOAD = c + "CustomPayload";
public static final String ARM_ANIMATION = c + "ArmAnimation";
public static final String BLOCK_PLACE = c + "BlockPlace";
/**
* 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";
@@ -32,6 +91,7 @@ public abstract class Packet {
public static final String SET_CREATIVE_SLOT = c + "SetCreativeSlot";
public static final String KEEP_ALIVE = c + "KeepAlive";
}
public static class Server {
@@ -68,14 +128,10 @@ public abstract class Packet {
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 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);
public static final String[] LOGIN_PACKETS = new String[]{"PacketHandshakingInSetProtocol", "PacketLoginInStart", "PacketLoginInEncryptionBegin"};
}
}
@@ -0,0 +1,183 @@
package io.github.retrooper.packetevents.packet;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class PacketType {
private static final ServerVersion version = PacketEvents.getServerVersion();
public static final class Util {
/**
* Is this NMS packet an instance of the "PacketPlayInFlying" packet?
* 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 & 1.16 protocol!
*/
public static boolean isInstanceOfFlyingPacket(final Object nmsPacket) {
//1.7->1.8.8
if (packetPlayInFlying != null) {
return packetPlayInFlying.isInstance(nmsPacket);
} else {
//1.9->1.15.2
return isInstanceOfPositionOrPositionLook(nmsPacket) || isInstanceOfPositionLookPacket(nmsPacket);
}
}
/**
* Is this NMS packet an instance of the "PacketPlayInPosition" packet?
*
* @param nmsPacket
* @return nmsPacket instanceof PacketPlayInPosition
*/
public static boolean isInstanceOfPositionPacket(final Object nmsPacket) {
return packetPlayInPosition.isInstance(nmsPacket);
}
/**
* Is this NMS packet an instance of the "PacketPlayInPositionLook" packet?
*
* @param nmsPacket
* @return nmsPacket instanceof PacketPlayInPositionLook
*/
public static boolean isInstanceOfPositionLookPacket(final Object nmsPacket) {
return packetPlayInPositionLook.isInstance(nmsPacket);
}
/**
* Is this NMS Packet an instanceof the "PacketPlayInPosition" or "PacketPlayInPositionLook"
*
* @param nmsPacket
* @return nmsPacket instanceof PacketPlayInPosition || nmsPacket instanceof PacketPlayInPositionLook
*/
public static boolean isInstanceOfPositionOrPositionLook(final Object nmsPacket) {
return isInstanceOfPositionPacket(nmsPacket) || isInstanceOfPositionLookPacket(nmsPacket);
}
/**
* Is this NMS Packet an instance of the "PacketPlayInLook" packet?
*
* @param nmsPacket
* @return nmsPacket instanceof PacketPlayInLook
*/
public static boolean isInstanceOfLook(final Object nmsPacket) {
return packetPlayInLook.isInstance(nmsPacket);
}
public static boolean isInstanceOfUseEntity(final Object nmsPacket) {
return packetPlayInUseEntity.isInstance(nmsPacket);
}
private static Class<?> packetPlayInFlying, packetPlayInPosition, packetPlayInPositionLook, packetPlayInLook, packetPlayInUseEntity;
static {
try {
//Only exists in 1.7->1.8.8 & 1.16 protocol
packetPlayInFlying = NMSUtils.getNMSClass(Client.FLYING);
} catch (ClassNotFoundException e) {
//That is fine, they are on 1.9->1.15.2
}
try {
packetPlayInPosition = NMSUtils.getNMSClass(Client.POSITION);
packetPlayInPositionLook = NMSUtils.getNMSClass(Client.POSITION_LOOK);
packetPlayInLook = NMSUtils.getNMSClass(Client.LOOK);
} catch (ClassNotFoundException e) {
for (final Class<?> cls : packetPlayInFlying.getDeclaredClasses()) {
if (cls.getSimpleName().equals(Client.POSITION)) {
packetPlayInPosition = cls;
} else if (cls.getSimpleName().equals(Client.POSITION_LOOK)) {
packetPlayInPositionLook = cls;
} else if (cls.getSimpleName().equals(Client.LOOK)) {
packetPlayInLook = cls;
}
}
}
try {
packetPlayInUseEntity = NMSUtils.getNMSClass(Client.USE_ENTITY);
}
catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public static final 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 final 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 final 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";
}
}
@@ -1,5 +1,5 @@
package io.github.retrooper.packetevents.packetwrappers;
public interface Sendable {
public Object asNMSPacket();
Object asNMSPacket();
}
@@ -4,18 +4,13 @@ import io.github.retrooper.packetevents.enums.ServerVersion;
import org.bukkit.entity.Player;
public class WrappedPacket {
private final Player player;
protected Object packet;
protected static ServerVersion version = ServerVersion.getVersion();
private static final String err = "Your Version is unsupported, " +
"please contact explored " +
"through his discord server (http://discord.gg/2uZY5A4) " +
"and tell him what version your server is running on! " +
"Make sure you are using spigot!";
protected final Player player;
protected Object packet;
public WrappedPacket(final Object packet) {
this.player = null;
if(packet == null)return;
if (packet == null) return;
this.packet = packet;
try {
setup();
@@ -26,7 +21,7 @@ public class WrappedPacket {
public WrappedPacket(final Player player, final Object packet) {
this.player = player;
if(packet == null)return;
if (packet == null) return;
this.packet = packet;
try {
setup();
@@ -35,16 +30,8 @@ public class WrappedPacket {
}
}
protected void setup() {
protected void setup() {
}
protected void throwUnsupportedVersion() {
throw new IllegalStateException(err);
}
public final Player getPlayer() {
return player;
}
}
@@ -5,7 +5,37 @@ import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInAbilities extends WrappedPacket {
public final class WrappedPacketInAbilities extends WrappedPacket {
private static Class<?> abilitiesClass;
private static final 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);
}
}
}
private boolean isVulnerable;
private boolean isFlying;
private boolean allowFly;
@@ -39,6 +69,15 @@ public class WrappedPacketInAbilities extends WrappedPacket {
return isFlying;
}
public boolean isFlightAllowed() {
return allowFly;
}
/**
* Use {@link WrappedPacketInAbilities#isFlightAllowed()}
* @return
*/
@Deprecated
public boolean canFly() {
return allowFly;
}
@@ -54,35 +93,4 @@ public class WrappedPacketInAbilities extends WrappedPacket {
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);
}
}
}
}
@@ -4,86 +4,21 @@ 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.utils.BaseBlockUtils;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import java.lang.reflect.Field;
public 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].getInt(blockPosObj);
final int y = blockPosXYZ[1].getInt(blockPosObj);
final int z = blockPosXYZ[2].getInt(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;
}
public final class WrappedPacketInBlockDig extends WrappedPacket {
//ALL
private static Class<?> blockDigClass;
//1.8
private static Field[] fields = new Field[3];
private static final Field[] fields = new Field[3];
private static Class<?> blockPositionClass;
private static Field[] blockPosXYZ = new Field[3];
private static final Reflection.FieldAccessor<Integer>[] blockPosXYZ = new Reflection.FieldAccessor[3];
//1.7
private static Field face;
private static Field e;
static {
@@ -107,9 +42,9 @@ public class WrappedPacketInBlockDig extends WrappedPacket {
fields[2] = blockDigClass.getDeclaredField("c");
if (version != ServerVersion.v_1_7_10) {
blockPosXYZ[0] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosXFieldName());
blockPosXYZ[1] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosXFieldName());
blockPosXYZ[2] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosZFieldName());
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");
@@ -118,26 +53,77 @@ public class WrappedPacketInBlockDig extends WrappedPacket {
e.printStackTrace();
}
for(Field f : fields) {
if(f != null) {
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
for(Field f : blockPosXYZ) {
if(f != null) {
f.setAccessible(true);
}
}
if(e != null) {
if (e != null) {
e.setAccessible(true);
}
if(face != null) {
if (face != null) {
face.setAccessible(true);
}
}
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;
}
}
@@ -1,6 +1,5 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.enums.Hand;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
@@ -9,9 +8,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class WrappedPacketInBlockPlace extends WrappedPacket {
public final class WrappedPacketInBlockPlace extends WrappedPacket {
private Vector3i blockPosition;
private Hand hand;
private ItemStack itemStack;
public WrappedPacketInBlockPlace(final Player player, final Object packet) {
@@ -23,47 +21,46 @@ public class WrappedPacketInBlockPlace extends WrappedPacket {
//1.7.10
Vector3i position = null;
ItemStack itemStack = null;
Hand hand = 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());
hand = updatedBlockPlace.getHand();
itemStack = new ItemStack(block.getType());
// init direction
} else {
final WrappedPacketInBlockPlace_Legacy legacyBlockPlace = new WrappedPacketInBlockPlace_Legacy(packet);
position = legacyBlockPlace.getBlockPosition();
hand = legacyBlockPlace.getHand();
itemStack = legacyBlockPlace.getItemStack();
//init direction
} }
catch(IllegalArgumentException e) {
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
final WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
final Block block = blockPlace_1_9.getBlock();
position = new Vector3i(block.getX(), block.getY(), block.getZ());
itemStack = new ItemStack(block.getType());
} else if(version.isHigherThan(ServerVersion.v_1_7_10)){
final WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
position = blockPlace_1_8.getBlockPosition();
itemStack = blockPlace_1_8.getItemStack();
}
else {
final WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(getPlayer(), packet);
position = blockPlace_1_7_10.getBlockPosition();
this.itemStack = blockPlace_1_7_10.getItemStack();
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
this.blockPosition = position;
this.itemStack = itemStack;
this.hand = hand;
}
public Player getPlayer() {
return this.player;
}
public Vector3i getBlockPosition() {
return blockPosition;
}
public Hand getHand() {
return hand;
}
public ItemStack getItemStack() {
return itemStack;
}
static {
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
WrappedPacketInBlockPlace_1_9.setupStaticVars();
} else {
WrappedPacketInBlockPlace_Legacy.setupStaticVars();
WrappedPacketInBlockPlace_1_9.initStatic();
} else if (version.isHigherThan(ServerVersion.v_1_7_10)) {
WrappedPacketInBlockPlace_1_8.initStatic();
}
}
@@ -0,0 +1,42 @@
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,58 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.reflectionutils.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 static final Reflection.MethodInvoker[] blockPositionXYZInvoker = new Reflection.MethodInvoker[3];
private static Class<?> blockPlaceClass, blockPositionClass;
private static Reflection.FieldAccessor<?> blockPositionAccessor, itemStackFieldAccessor;
private Vector3i blockPosition;
private ItemStack itemStack;
WrappedPacketInBlockPlace_1_8(final Object packet) {
super(packet);
}
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");
}
@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;
}
}
@@ -1,65 +1,52 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.enums.Hand;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.BlockFinder;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
private Block block;
private Hand hand;
private static Method getTargetBlockMethod;
public WrappedPacketInBlockPlace_1_9(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
protected static void initStatic() {
try {
this.block = BlockFinder.getBlocksInDirection(getPlayer(), 10);
final Object enumHandObj = enumHandField.get(packet);
this.hand = Hand.valueOf(enumHandObj.toString());
} catch (IllegalAccessException e) {
getTargetBlockMethod = Player.class.getMethod("getTargetBlock", HashSet.class, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public Hand getHand() {
return hand;
@Override
protected void setup() {
try {
this.block = (Block) getTargetBlockMethod.invoke(getPlayer(), null, 3);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public Player getPlayer() {
return this.player;
}
public Block getBlock() {
return block;
}
private static Class<?> blockPlaceClass_1_9;
private static Field enumHandField;
protected static void setupStaticVars() {
try {
blockPlaceClass_1_9 = NMSUtils.getNMSClass("PacketPlayInBlockPlace");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
enumHandField = blockPlaceClass_1_9.getDeclaredField("a");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
if (!enumHandField.isAccessible()) {
enumHandField.setAccessible(true);
}
}
}
@@ -1,153 +0,0 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
import io.github.retrooper.packetevents.enums.Hand;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.BaseBlockUtils;
import io.github.retrooper.packetevents.utils.NMSUtils;
import io.github.retrooper.packetevents.utils.vector.Vector3i;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class WrappedPacketInBlockPlace_Legacy extends WrappedPacket {
private Vector3i blockPosition;
private ItemStack itemStack;
private Hand hand;
WrappedPacketInBlockPlace_Legacy(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
final Hand hand = Hand.MAIN_HAND;
final ItemStack itemStack;
final int x, y, z;
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
final Object nmsBlockPosObj = fields[0].get(packet);
x = blockPosXYZ[0].getInt(nmsBlockPosObj);
y = blockPosXYZ[1].getInt(nmsBlockPosObj);
z = blockPosXYZ[2].getInt(nmsBlockPosObj);
Object nmsItemStackObj = fields[1].get(packet);
Object craftItemStack = asBukkitCopyMethod.invoke(null, nmsItemStackObj);
itemStack = (ItemStack) craftItemStack;
}
//1.7.10
else {
x = fields_1_7[0].getInt(packet);
y = fields_1_7[1].getInt(packet);
z = fields_1_7[2].getInt(packet);
Object nmsItemStackObj = fields_1_7[3].get(packet);
Object craftItemStack = asBukkitCopyMethod.invoke(null, nmsItemStackObj);
itemStack = (ItemStack) craftItemStack;
}
this.hand = hand;
this.itemStack = itemStack;
this.blockPosition = new Vector3i(x, y, z);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
public Hand getHand() {
return hand;
}
public ItemStack getItemStack() {
return itemStack;
}
public Vector3i getBlockPosition() {
return blockPosition;
}
private static Class<?> blockPlaceClass;
private static Class<?> itemStackClass;
private static Class<?> craftItemStackClass;
private static Class<?> blockPositionClass;
private static Field[] fields = new Field[2];
private static Field[] fields_1_7 = new Field[4];
private static Field[] blockPosXYZ = new Field[3];
private static Method asBukkitCopyMethod;
protected static void setupStaticVars() {
try {
blockPlaceClass = NMSUtils.getNMSClass("PacketPlayInBlockPlace");
itemStackClass = NMSUtils.getNMSClass("ItemStack");
craftItemStackClass = NMSUtils.getOBCClass("inventory.CraftItemStack");
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
asBukkitCopyMethod = craftItemStackClass.getMethod("asBukkitCopy", itemStackClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
if (version.isLowerThan(ServerVersion.v_1_8)) {
//x
fields_1_7[0] = blockPlaceClass.getDeclaredField("a");
//y
fields_1_7[1] = blockPlaceClass.getDeclaredField("b");
//z
fields_1_7[2] = blockPlaceClass.getDeclaredField("c");
//itemstack
fields_1_7[3] = blockPlaceClass.getDeclaredField("e");
} else {
//block pos
fields[0] = blockPlaceClass.getDeclaredField("b");
//itemstack
fields[1] = blockPlaceClass.getDeclaredField("d");
blockPosXYZ[0] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosXFieldName());
blockPosXYZ[1] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosYFieldName());
blockPosXYZ[2] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosZFieldName());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
for (Field f : fields_1_7) {
if (f != null) {
f.setAccessible(true);
}
}
for (Field f : blockPosXYZ) {
if (f != null) {
f.setAccessible(true);
}
}
}
}
@@ -6,29 +6,8 @@ import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public 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;
}
public final class WrappedPacketInChat extends WrappedPacket {
private static Class<?> chatPacketClass;
private static Field field;
static {
@@ -48,10 +27,30 @@ public class WrappedPacketInChat extends WrappedPacket {
field.setAccessible(true);
}
private String message;
public WrappedPacketInChat(Object packet) {
super(packet);
}
private static String getChatFieldName() {
if (version == ServerVersion.v_1_7_10) {
return "message";
}
return "a";
}
@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;
}
}
@@ -1,15 +1,49 @@
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 javax.annotation.Nullable;
import java.lang.reflect.Field;
public class WrappedPacketInEntityAction extends WrappedPacket {
public final class WrappedPacketInEntityAction extends WrappedPacket {
private static Class<?> entityActionClass;
@Nullable
private static Class<?> enumPlayerActionClass;
private static final 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);
}
}
private Entity entity;
private int entityId;
private PlayerAction action;
@@ -71,41 +105,4 @@ public class WrappedPacketInEntityAction extends WrappedPacket {
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);
}
}
}
@@ -8,6 +8,37 @@ import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInFlying extends WrappedPacket {
private static Class<?> flyingClass;
private static final 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 double x;
private double y;
@@ -22,6 +53,13 @@ public class WrappedPacketInFlying extends WrappedPacket {
super(packet);
}
private static String getOnGroundFieldName() {
if (version == ServerVersion.v_1_7_10) {
return "g";
}
return "f";
}
@Override
protected void setup() {
try {
@@ -41,6 +79,38 @@ public class WrappedPacketInFlying extends WrappedPacket {
}
}
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;
}
public static class WrappedPacketInPosition extends WrappedPacketInFlying {
public WrappedPacketInPosition(Object packet) {
super(packet);
@@ -73,76 +143,4 @@ public class WrappedPacketInFlying extends WrappedPacket {
}
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public float getYaw() {
return yaw;
}
public float getPitch() {
return pitch;
}
public 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";
}
}
@@ -6,13 +6,32 @@ import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInKeepAlive extends WrappedPacket {
public WrappedPacketInKeepAlive(final Object packet) {
super(packet);
public final class WrappedPacketInKeepAlive extends WrappedPacket {
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();
}
}
private long id;
public WrappedPacketInKeepAlive(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
@@ -35,24 +54,4 @@ public class WrappedPacketInKeepAlive extends WrappedPacket {
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,51 @@
package io.github.retrooper.packetevents.packetwrappers.in.transaction;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
public final class WrappedPacketInTransaction extends WrappedPacket {
private int windowId;
private short actionNumber;
private boolean accepted;
public WrappedPacketInTransaction(final Object packet) {
super(packet);
}
@Override
protected void setup() {
this.windowId = windowIdAccessor.get(packet);
this.actionNumber = actionNumberAccessor.get(packet);
this.accepted = acceptedAccessor.get(packet);
}
public int getWindowId() {
return windowId;
}
public short getActionNumber() {
return actionNumber;
}
public boolean isAccepted() {
return accepted;
}
private static Class<?> packetClass;
private static final Reflection.FieldAccessor<Integer> windowIdAccessor;
private static final Reflection.FieldAccessor<Short> actionNumberAccessor;
private static final Reflection.FieldAccessor<Boolean> acceptedAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketPlayInTransaction");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
windowIdAccessor = Reflection.getField(packetClass, int.class, 0);
actionNumberAccessor = Reflection.getField(packetClass, short.class, 0);
acceptedAccessor= Reflection.getField(packetClass, boolean.class, 0);
}
}
@@ -7,47 +7,9 @@ import org.bukkit.entity.Entity;
import java.lang.reflect.Field;
public 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];
public final class WrappedPacketInUseEntity extends WrappedPacket {
private static Class<?> useEntityClass, entityClass;
private static final Field[] fields = new Field[2];
static {
@@ -75,4 +37,36 @@ public 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;
}
}
@@ -1,4 +0,0 @@
package io.github.retrooper.packetevents.packetwrappers.login;
public class WrappedPacketLoginHandshake {
}
@@ -0,0 +1,52 @@
package io.github.retrooper.packetevents.packetwrappers.out.abilities;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
final class PlayerAbilitiesUtils {
public static Class<?> playerAbilitiesClass;
public static Constructor<?> playerAbilitiesConstructor;
private static final Reflection.FieldAccessor<Boolean>[] booleanFieldAccessors = new Reflection.FieldAccessor[4];
private static final Reflection.FieldAccessor<Float>[] floatFieldAccessors = new Reflection.FieldAccessor[2];
public static Object getPlayerAbilities(final boolean isVulnerable, final boolean isFlying, final boolean allowFlight, final boolean canBuildInstantly,
final float flySpeed, final float walkSpeed) throws IllegalAccessException, InvocationTargetException, InstantiationException {
final Object instance = playerAbilitiesConstructor.newInstance();
booleanFieldAccessors[0].set(instance, isVulnerable);
booleanFieldAccessors[1].set(instance, isFlying);
booleanFieldAccessors[2].set(instance, allowFlight);
booleanFieldAccessors[3].set(instance, canBuildInstantly);
floatFieldAccessors[0].set(instance, flySpeed);
floatFieldAccessors[1].set(instance, walkSpeed);
return instance;
}
static {
try {
playerAbilitiesClass = NMSUtils.getNMSClass("PlayerAbilities");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
playerAbilitiesConstructor = playerAbilitiesClass.getConstructor();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
for (byte i = 0; i < booleanFieldAccessors.length; i++) {
booleanFieldAccessors[i] = Reflection.getField(playerAbilitiesClass, boolean.class, i);
}
for (byte i = 0; i < floatFieldAccessors.length; i++) {
floatFieldAccessors[i] = Reflection.getField(playerAbilitiesClass, float.class, i);
}
}
}
@@ -0,0 +1,103 @@
package io.github.retrooper.packetevents.packetwrappers.out.abilities;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketOutAbilities extends WrappedPacket implements Sendable {
private boolean vulnerable, flying, allowFlight, instantBuild;
private float flySpeed, walkSpeed;
public WrappedPacketOutAbilities(final Object packet) {
super(packet);
}
public WrappedPacketOutAbilities(final boolean isVulnerable, final boolean isFlying, final boolean allowFlight, final boolean canBuildInstantly,
final float flySpeed, final float walkSpeed) {
super(null);
this.vulnerable = isVulnerable;
this.flying = isFlying;
this.allowFlight = allowFlight;
this.instantBuild = canBuildInstantly;
this.flySpeed = flySpeed;
this.walkSpeed = walkSpeed;
}
@Override
protected void setup() {
this.vulnerable = booleanFieldAccessors[0].get(packet);
this.flying = booleanFieldAccessors[1].get(packet);
this.allowFlight = booleanFieldAccessors[2].get(packet);
this.instantBuild = booleanFieldAccessors[3].get(packet);
this.flySpeed = floatFieldAccessors[0].get(packet);
this.walkSpeed = floatFieldAccessors[1].get(packet);
}
public boolean isVulnerable() {
return vulnerable;
}
public boolean isFlying() {
return flying;
}
public boolean isFlightAllowed() {
return allowFlight;
}
public boolean canInstantlyBuild() {
return instantBuild;
}
public float getFlySpeed() {
return flySpeed;
}
public float getWalkSpeed() {
return walkSpeed;
}
private static Class<?> packetClass;
private static Constructor<?> packetConstructor;
private static final Reflection.FieldAccessor<Boolean>[] booleanFieldAccessors = new Reflection.FieldAccessor[4];
private static final Reflection.FieldAccessor<Float>[] floatFieldAccessors = new Reflection.FieldAccessor[2];
static {
try {
packetClass = NMSUtils.getNMSClass("PacketPlayOutAbilities");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
packetConstructor = packetClass.getConstructor(PlayerAbilitiesUtils.playerAbilitiesClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
for (byte i = 0; i < booleanFieldAccessors.length; i++) {
booleanFieldAccessors[i] = Reflection.getField(packetClass, boolean.class, i);
}
for (byte i = 0; i < floatFieldAccessors.length; i++) {
floatFieldAccessors[i] = Reflection.getField(packetClass, float.class, i);
}
}
@Override
public Object asNMSPacket() {
try {
return packetConstructor.newInstance(PlayerAbilitiesUtils.getPlayerAbilities(vulnerable, flying, allowFlight, instantBuild, flySpeed, walkSpeed));
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -10,7 +10,37 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class WrappedPacketOutAnimation extends WrappedPacket implements Sendable {
public final class WrappedPacketOutAnimation extends WrappedPacket implements Sendable {
private static Class<?> animationClass, nmsEntityClass;
private static Constructor<?> animationConstructor;
private static final 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);
}
}
private Entity entity;
private int entityID;
private EntityAnimationType type;
@@ -40,19 +70,18 @@ public class WrappedPacketOutAnimation extends WrappedPacket implements Sendable
}
public final Entity getEntity() {
public Entity getEntity() {
return this.entity;
}
public final int getEntityId() {
public int getEntityId() {
return this.entityID;
}
public final EntityAnimationType getAnimationType() {
public EntityAnimationType getAnimationType() {
return type;
}
@Override
public Object asNMSPacket() {
final Object nmsEntity = NMSUtils.getNMSEntity(this.entity);
@@ -64,35 +93,4 @@ public class WrappedPacketOutAnimation extends WrappedPacket implements Sendable
}
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);
}
}
}
@@ -6,70 +6,32 @@ 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 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 = message;
}
@Override
protected void setup() {
//all fields are IChatBaseComponents, and named 'a'
net.minecraft.server.v1_8_R3.PacketPlayOutChat c;
}
@Override
public Object asNMSPacket() {
Object iChatBaseComponentObj = null;
try {
iChatBaseComponentObj = serialize.invoke(null, this.message);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
try {
return chatClassConstructor.newInstance(iChatBaseComponentObj);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public String getMessage() {
return this.message;
}
private static Class<?> chatClass;
public final class WrappedPacketOutChat extends WrappedPacket implements Sendable {
private static Constructor<?> chatClassConstructor;
private static Class<?> iChatBaseComponentClass;
private static Class<?> chatSerializer;
private static Method serialize;
private static Class<?> chatClass, iChatBaseComponentClass, chatSerializerClass;
private static Field iChatBaseField;
private static Method serialize, getStringOfIChatBase;
static {
try {
chatClass = NMSUtils.getNMSClass("PacketPlayOutChat");
final String subClass = version.isHigherThan(ServerVersion.v_1_8) ? "IChatBaseComponent$" : "";
iChatBaseComponentClass = NMSUtils.getNMSClass("IChatBaseComponent");
chatSerializer = NMSUtils.getNMSClass(subClass + "ChatSerializer");
//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();
}
@@ -81,10 +43,86 @@ public class WrappedPacketOutChat extends WrappedPacket implements Sendable {
}
try {
serialize = chatSerializer.getMethod("a", String.class);
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 String message;
public WrappedPacketOutChat(final Object packet) {
super(packet);
}
public WrappedPacketOutChat(final String message) {
super(null);
this.message = "{\"text\": \"" + message + "\"}";
}
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;
}
private static String getTextMethodName() {
//1.7.10
if (version.isLowerThan(ServerVersion.v_1_8)) {
return "e"; //or c
} else {
return "getText";
}
}
@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 String getMessage() {
return this.message;
}
}
@@ -4,95 +4,16 @@ 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 net.minecraft.server.v1_15_R1.Vec3D;
import org.bukkit.entity.Entity;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public 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 {
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 final int getEntityId() {
return entityId;
}
public final Entity getEntity() {
return entity;
}
public final double getVelocityX() {
return velocityX;
}
public final double getVelocityY() {
return velocityY;
}
public final 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;
}
public final class WrappedPacketOutEntityVelocity extends WrappedPacket implements Sendable {
private static Constructor<?> velocityConstructor, vec3dConstructor;
private static Class<?> velocityClass, vec3dClass;
private static Field[] fields = new Field[4];
private static final Field[] fields = new Field[4];
/**
* Velocity Constructor parameter types:
@@ -100,8 +21,6 @@ public class WrappedPacketOutEntityVelocity extends WrappedPacket implements Sen
* 1.14+ use int, Vec3D style
*/
static {
Vec3D vec = new Vec3D(0, 0, 0);
try {
velocityClass = NMSUtils.getNMSClass("PacketPlayOutEntityVelocity");
@@ -144,4 +63,80 @@ public class WrappedPacketOutEntityVelocity extends WrappedPacket implements Sen
}
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;
}
}
@@ -0,0 +1,62 @@
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.reflectionutils.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 static final Reflection.FieldAccessor<?> iChatBaseComponentAccessor;
private static Class<?> packetClass, iChatBaseComponentClass;
private static Constructor<?> kickDisconnectConstructor;
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);
}
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;
}
}
@@ -0,0 +1,80 @@
package io.github.retrooper.packetevents.packetwrappers.out.transaction;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class WrappedPacketOutTransaction extends WrappedPacket implements Sendable {
private int windowId;
private short actionNumber;
private boolean accepted;
public WrappedPacketOutTransaction(final Object packet) {
super(packet);
}
public WrappedPacketOutTransaction(final int windowId, final short actionNumber, final boolean accepted) {
super(null);
this.windowId = windowId;
this.actionNumber = actionNumber;
this.accepted = accepted;
}
@Override
protected void setup() {
this.windowId = windowIdAccessor.get(packet);
this.actionNumber = actionNumberAccessor.get(packet);
this.accepted = acceptedAccessor.get(packet);
}
public int getWindowId() {
return windowId;
}
public short getActionNumber() {
return actionNumber;
}
public boolean isAccepted() {
return accepted;
}
@Override
public Object asNMSPacket() {
try {
return packetConstructor.newInstance(windowId, actionNumber, accepted);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> packetClass;
private static Constructor<?> packetConstructor;
private static final Reflection.FieldAccessor<Integer> windowIdAccessor;
private static final Reflection.FieldAccessor<Short> actionNumberAccessor;
private static final Reflection.FieldAccessor<Boolean> acceptedAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketPlayOutTransaction");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
packetConstructor = packetClass.getConstructor(int.class, short.class, boolean.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
windowIdAccessor = Reflection.getField(packetClass, int.class, 0);
actionNumberAccessor = Reflection.getField(packetClass, short.class, 0);
acceptedAccessor= Reflection.getField(packetClass, boolean.class, 0);
}
}
@@ -0,0 +1,85 @@
package io.github.retrooper.packetevents.packetwrappers.out.updatehealth;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.reflectionutils.Reflection;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public final class WrappedPacketOutUpdateHealth extends WrappedPacket implements Sendable {
private float health, foodSaturation;
private int food;
public WrappedPacketOutUpdateHealth(final Object packet) {
super(packet);
}
/**
* See https://wiki.vg/Protocol#Update_Health
* @param health
* @param food
* @param foodSaturation
*/
public WrappedPacketOutUpdateHealth(final float health, final int food, final float foodSaturation) {
super(null);
this.health= health;
this.food = food;
this.foodSaturation = foodSaturation;
}
@Override
protected void setup() {
this.health = healthAccessor.get(packet);
this.foodSaturation = foodSaturationAccessor.get(packet);
this.food = foodAccessor.get(packet);
}
public float getHealth() {
return health;
}
public float getFoodSaturation() {
return foodSaturation;
}
public int getFood() {
return food;
}
@Override
public Object asNMSPacket() {
try {
return packetConstructor.newInstance(health, food, foodSaturation);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> packetClass;
private static Constructor<?> packetConstructor;
private static final Reflection.FieldAccessor<Float> healthAccessor, foodSaturationAccessor;
private static final Reflection.FieldAccessor<Integer> foodAccessor;
static {
try {
packetClass = NMSUtils.getNMSClass("PacketPlayOutUpdateHealth");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
packetConstructor = packetClass.getConstructor(float.class, int.class, float.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
healthAccessor = Reflection.getField(packetClass, float.class, 0);
foodSaturationAccessor = Reflection.getField(packetClass, float.class, 1);
foodAccessor = Reflection.getField(packetClass, int.class, 0);
}
}
@@ -1,4 +1,4 @@
package io.github.retrooper.packetevents.tinyprotocol;
package io.github.retrooper.packetevents.reflectionutils;
import org.bukkit.Bukkit;
@@ -15,72 +15,12 @@ import java.util.regex.Pattern;
* @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(".", "");
private static final String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
private static final String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server");
private static final String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", "");
// Variable replacement
private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");
private static final Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");
private Reflection() {
// Seal class
}
@@ -88,8 +28,8 @@ public final class Reflection {
/**
* 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 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.
*/
@@ -101,7 +41,7 @@ public final class Reflection {
* 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 name - the name of the field, or NULL to ignore.
* @param fieldType - a compatible field type.
* @return The field accessor.
*/
@@ -112,9 +52,9 @@ public final class Reflection {
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param target - the target type.
* @param target - the target type.
* @param fieldType - a compatible field type.
* @param index - the number of compatible fields to skip.
* @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) {
@@ -126,7 +66,7 @@ public final class Reflection {
*
* @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.
* @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) {
@@ -180,9 +120,9 @@ public final class Reflection {
/**
* 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 className - lookup name of the class, see {@link #getClass(String)}.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
@@ -193,9 +133,9 @@ public final class Reflection {
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
@@ -206,10 +146,10 @@ public final class Reflection {
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @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.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
@@ -246,7 +186,7 @@ public final class Reflection {
* 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.
* @param params - the expected parameters.
* @return An object that invokes this constructor.
* @throws IllegalStateException If we cannot find this method.
*/
@@ -257,7 +197,7 @@ public final class Reflection {
/**
* Search for the first publically and privately defined constructor of the given name and parameter count.
*
* @param clazz - a class to start with.
* @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.
@@ -291,12 +231,12 @@ public final class Reflection {
* 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.
* @see {@link #getClass()} for more information.
*/
public static Class<Object> getUntypedClass(String lookupName) {
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({"rawtypes", "unchecked"})
Class<Object> clazz = (Class) getClass(lookupName);
return clazz;
}
@@ -400,4 +340,62 @@ public final class Reflection {
matcher.appendTail(output);
return output.toString();
}
/**
* 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);
}
}
@@ -1,560 +0,0 @@
/*
* This file is part of Hawk Anticheat.
* Copyright (C) 2018 Hawk Development Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.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 Class<?> PACKET_HANDSHAKING_IN_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol");
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
private static final FieldAccessor<Integer> protocolId = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, int.class, 0);
private static final FieldAccessor<Enum> protocolType = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, Enum.class, 0);
// Speedup channel/protocol lookup
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Map<Channel, Integer> protocolLookup = new MapMaker().weakKeys().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);
}
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) {
injectChannelInternal(getChannel(player)).player = player;
PacketEvents.getEventManager().callEvent(new PlayerInjectEvent(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;
}
public int getProtocolVersion(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 protocolLookup.get(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);
} else if (PACKET_HANDSHAKING_IN_SET_PROTOCOL.isInstance(packet)) {
if (protocolType.get(packet).name().equalsIgnoreCase("LOGIN")) {
protocolLookup.put(channel, protocolId.get(packet));
}
}
}
}
}
@@ -1,559 +0,0 @@
/*
* This file is part of Hawk Anticheat.
* Copyright (C) 2018 Hawk Development Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.retrooper.packetevents.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.injector.PacketHandler_1_8;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
import io.github.retrooper.packetevents.tinyprotocol.Reflection.MethodInvoker;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.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 MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
private static final FieldAccessor<Object> getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
private static final FieldAccessor<Channel> getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
// Looking up ServerConnection
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
private static final MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
// Packets we have to intercept
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
private static final Class<?> PACKET_HANDSHAKING_IN_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol");
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
private static final FieldAccessor<Integer> protocolId = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, int.class, 0);
private static final FieldAccessor<Enum> protocolType = Reflection.getField(PACKET_HANDSHAKING_IN_SET_PROTOCOL, Enum.class, 0);
// Speedup channel/protocol lookup
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
private Map<Channel, Integer> protocolLookup = new MapMaker().weakKeys().makeMap();
private Listener listener;
// Channels that have already been removed
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
// List of network markers
private List<Object> networkManagers;
// Injected channel handlers
private List<Channel> serverChannels = Lists.newArrayList();
private ChannelInboundHandlerAdapter serverChannelHandler;
private ChannelInitializer<Channel> beginInitProtocol;
private ChannelInitializer<Channel> endInitProtocol;
// Current handler name
private String handlerName;
protected volatile boolean closed;
protected Plugin plugin;
/**
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
* <p>
* You can construct multiple instances per plugin.
*
* @param plugin - the plugin.
*/
public TinyProtocol8(final Plugin plugin) {
this.plugin = plugin;
// Compute handler name
this.handlerName = getHandlerName();
// 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);
}
@SuppressWarnings("unchecked")
private void registerChannelHandler() throws NoSuchFieldException, IllegalAccessException {
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
Object serverConnection = getServerConnection.get(mcServer);
boolean looking = true;
// We need to synchronize against this list
final Field networkManagersField = serverConnection.getClass().getDeclaredField(PacketHandler_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);
}
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) {
injectChannelInternal(getChannel(player)).player = player;
PacketEvents.getEventManager().callEvent(new PlayerInjectEvent(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;
}
public int getProtocolVersion(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 protocolLookup.get(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);
} else if (PACKET_HANDSHAKING_IN_SET_PROTOCOL.isInstance(packet)) {
if (protocolType.get(packet).name().equalsIgnoreCase("LOGIN")) {
protocolLookup.put(channel, protocolId.get(packet));
}
}
}
}
}
@@ -1,33 +0,0 @@
package io.github.retrooper.packetevents.utils;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
public class BaseBlockUtils {
private static final ServerVersion version = PacketEvents.getServerVersion();
public static String getPosXFieldName() {
return "a";
}
public static String getPosYFieldName() {
if (version == ServerVersion.v_1_8) {
return "b";
} else if (version == ServerVersion.v_1_8_3
|| version == ServerVersion.v_1_8_8
|| version == ServerVersion.v_1_9) {
return "c";
}
//1.9.4 and higher
return "b";
}
public static String getPosZFieldName() {
if (version == ServerVersion.v_1_8) {
return "c";
} else if (version == ServerVersion.v_1_8_3 || version == ServerVersion.v_1_8_8 || version == ServerVersion.v_1_9) {
return "d";
}
return "c";
}
}
@@ -1,16 +0,0 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.BlockIterator;
public class BlockFinder {
public static Block getBlocksInDirection(final Player player, final int blockDistance) {
final BlockIterator it = new BlockIterator(player, blockDistance);
Block cur = null;
while(it.hasNext()) {
cur = it.next();
}
return cur;
}
}
@@ -1,43 +1,40 @@
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.reflectionutils.Reflection;
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 javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class NMSUtils {
public final class NMSUtils {
private static final ServerVersion version = ServerVersion.getVersion();
private static final String nettyPrefix = version == ServerVersion.v_1_7_10 ? "net.minecraft.util.io.netty" : "io.netty";
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;
private static Class<?> serverConnectionClass, craftEntityClass;
packetClass, entityPlayerClass, playerConnectionClass,
craftPlayerClass, serverConnectionClass, craftEntityClass,
craftItemStack, nmsItemStackClass, networkManagerClass, nettyChannelClass;
private static Method getServerMethod;
private static Method getCraftWorldHandleMethod;
private static Method entityMethod;
public static Method getServerConnection;
public static Method getCraftPlayerHandle;
public static Method getCraftEntityHandle;
private static Method sendPacketMethod;
private static Method getServerMethod, getCraftWorldHandleMethod, getServerConnection, getCraftPlayerHandle, getCraftEntityHandle, sendPacketMethod, asBukkitCopy;
private static Field recentTPSField;
private static Field entityPlayerPingField;
private static Field playerConnectionField;
private static Field recentTPSField, entityPlayerPingField, playerConnectionField;
public static final Reflection.FieldAccessor<?> networkManagerFieldAccesssor, channelFieldAccessor;
static {
try {
nettyChannelClass = getNettyClass("channel.Channel");
minecraftServerClass = getNMSClass("MinecraftServer");
craftWorldsClass = getOBCClass("CraftWorld");
craftPlayerClass = getOBCClass("entity.CraftPlayer");
@@ -46,6 +43,9 @@ public class NMSUtils {
playerConnectionClass = getNMSClass("PlayerConnection");
serverConnectionClass = getNMSClass("ServerConnection");
craftEntityClass = getOBCClass("entity.CraftEntity");
craftItemStack = getOBCClass("inventory.CraftItemStack");
nmsItemStackClass = getNMSClass("ItemStack");
networkManagerClass = getNMSClass("NetworkManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
@@ -58,6 +58,7 @@ public class NMSUtils {
getCraftEntityHandle = craftEntityClass.getMethod("getHandle");
sendPacketMethod = playerConnectionClass.getMethod("sendPacket", packetClass);
getServerConnection = minecraftServerClass.getMethod("getServerConnection");
asBukkitCopy = craftItemStack.getMethod("asBukkitCopy", nmsItemStackClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
@@ -71,7 +72,8 @@ public class NMSUtils {
e.printStackTrace();
}
networkManagerFieldAccesssor = Reflection.getField(playerConnectionClass, networkManagerClass, 0);
channelFieldAccessor = Reflection.getField(networkManagerClass, nettyChannelClass, 0);
}
public static Object getMinecraftServerInstance() throws InvocationTargetException, IllegalAccessException {
@@ -118,35 +120,45 @@ public class NMSUtils {
final Object craftEntity = craftEntityClass.cast(entity);
try {
return getCraftEntityHandle.invoke(craftEntity);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
} 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) {
Object entityPlayer = null;
try {
return getCraftPlayerHandle.invoke(craftPlayerClass.cast(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
return getCraftPlayerHandle.invoke(getCraftPlayer(player));
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static int getPlayerPing(final Player player) {
final Object craftPlayer = craftPlayerClass.cast(player);
Object entityPlayer = null;
public static Object getPlayerConnection(final Player player) {
try {
entityPlayer = getCraftPlayerHandle.invoke(craftPlayer);
return playerConnectionField.get( getEntityPlayer(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object getNetworkManager(final Player player) {
return networkManagerFieldAccesssor.get(getPlayerConnection(player));
}
public static Object getChannel(final Player player) {
return channelFieldAccessor.get(getNetworkManager(player));
}
public static int getPlayerPing(final Player player) {
Object entityPlayer = getEntityPlayer(player);
try {
return entityPlayerPingField.getInt(entityPlayer);
} catch (IllegalAccessException e) {
@@ -155,6 +167,17 @@ public class NMSUtils {
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);
@@ -165,15 +188,7 @@ public class NMSUtils {
}
public static void sendNMSPacket(final Player player, final Object nmsPacket) {
Object entityPlayer = null;
try {
entityPlayer = getCraftPlayerHandle.invoke(craftPlayerClass.cast(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Object entityPlayer = getEntityPlayer(player);
Object playerConnection = null;
try {
playerConnection = playerConnectionField.get(entityPlayer);
@@ -183,9 +198,7 @@ public class NMSUtils {
try {
sendPacketMethod.invoke(playerConnection, nmsPacket);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
@@ -0,0 +1,10 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
class ProtocolSupportAPIAccessor {
public static int getProtocolVersion(final Player player) {
return ProtocolSupportAPI.getProtocolVersion(player).getId();
}
}
@@ -0,0 +1,15 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportUtils {
public static boolean isProtocolSupportAvailable() {
return Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
}
public static int getProtocolVersion(final Player player) {
return ProtocolSupportAPI.getProtocolVersion(player).getId();
}
}
@@ -0,0 +1,14 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.entity.Player;
public class VersionLookupUtils {
public static int getProtocolVersion(final Player player) {
if (ViaUtils.isViaAPIAvaialable()) {
return ViaUtils.getProtocolVersion(player);
} else if (ProtocolSupportUtils.isProtocolSupportAvailable()) {
return ProtocolSupportUtils.getProtocolVersion(player);
}
return -1;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import java.util.UUID;
class ViaAPIAccessor {
public static int getProtocolVersion(final Player player) {
return getProtocolVersion(player.getUniqueId());
}
public static int getProtocolVersion(final UUID uuid) {
return Via.getAPI().getPlayerVersion(uuid);
}
}
@@ -0,0 +1,15 @@
package io.github.retrooper.packetevents.utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class ViaUtils {
public static int getProtocolVersion(final Player player) {
return ViaAPIAccessor.getProtocolVersion(player);
}
public static boolean isViaAPIAvaialable() {
return Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
}
}
@@ -1,66 +1,24 @@
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 javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class EntityFinderUtils {
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) {
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 final ServerVersion version = PacketEvents.getServerVersion();
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 {
@@ -81,6 +39,47 @@ public class EntityFinderUtils {
}
}
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;
}
public static String getEntityByNameMethodName() {
if (version.isHigherThan(ServerVersion.v_1_7_10) && version.isLowerThan(ServerVersion.v_1_9)) {
return "a";
@@ -1,15 +0,0 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector2d {
public double x, y;
public Vector2d(final double x, final double y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y;
}
}
@@ -1,14 +0,0 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector2f {
public float x, y;
public Vector2f(final float x, final float y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y;
}
}
@@ -1,15 +0,0 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector2i {
public int x, y;
public Vector2i(final int x, final int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y;
}
}
@@ -1,14 +1,14 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3d {
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;
@@ -1,6 +1,6 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3f {
public final class Vector3f {
public float x, y, z;
public Vector3f(final float x, final float y, final float z) {
@@ -1,6 +1,6 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3i {
public final class Vector3i {
public int x, y, z;
public Vector3i(final int x, final int y, final int z) {
-4
View File
@@ -1,4 +0,0 @@
name: packetevents
version: 1.2.8
main: io.github.retrooper.packetevents.example.MainExample
author: retrooper