Compare commits

..
85 Commits
Author SHA1 Message Date
purplexdev 691684c828 Merge remote-tracking branch 'origin/master' 2020-06-06 16:17:54 +02:00
purplexdev 06482124ce 1.2.8 Release!
1.14 & 1.15 bug fixes!(entity velocity error and api not starting up fixed)

Now fully works on 1.7.10->1.15.2

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

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

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

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

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

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

* WrappedPacketInEntityAction added as a couple of you suggested

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

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

* pom.xml updated to use new group id

* Registered listener example updated, more documented

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

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

Packets not received when relogging BUG FIXED!

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

No files matched your search

+19 -55
View File
@@ -1,65 +1,29 @@
# PacketEvents
Listen to minecraft packets and send minecraft packets.
# packetevents by retrooper
Credit to TinyProtocol
An asynchronous spigot packetListener coded by retrooper.
PacketEvents coded by purplex.
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, ...).
Coding help discord server: https://discord.gg/ZWTkg4v
* No dependencies
Examples can be found at
me/purplex/packetevents/example/TestExample.java
* Licensed with the GPL2 license.
# Gradle
[![](https://img.shields.io/badge/License-GPLv2-blue.svg)](https://www.gnu.org/licenses/gpl-2.0)
```gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.purplexdev:packetevents:1.0.9'
}
```
# Maven
```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.purplexdev</groupId>
<artifactId>packetevents</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
```
# sbt
```
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.purplexdev" % "packetevents" % "1.0.9"
```
# leiningen
```
:repositories [["jitpack" "https://jitpack.io"]]
:dependencies [[com.github.purplexdev/packetevents "1.0.9"]]
```
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
+9 -12
View File
@@ -4,11 +4,11 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.purplex</groupId>
<groupId>io.github.retrooper</groupId>
<artifactId>packetevents</artifactId>
<version>1.1.2</version>
<version>1.2.8</version>
<packaging>jar</packaging>
<name>PacketEvents</name>
<name>packetevents</name>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -56,7 +56,6 @@
<id>funkemunky-releases</id>
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
</repository>
</repositories>
@@ -103,6 +102,12 @@
<version>1.13.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.7.10</artifactId>
<version>1.7.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.8</artifactId>
@@ -175,13 +180,5 @@
<version>1.14</version>
<scope>provided</scope>
</dependency>
<!--Bukkit-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,101 @@
package io.github.retrooper.packetevents;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.event.impl.ServerTickEvent;
import io.github.retrooper.packetevents.event.manager.EventManager;
import io.github.retrooper.packetevents.injector.PacketHandler;
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.scheduler.BukkitTask;
import java.lang.reflect.InvocationTargetException;
public class PacketEvents{
private static final ServerVersion version = ServerVersion.getVersion();
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;
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();
if (serverTickEventEnabled) {
final Runnable runnable = new Runnable() {
@Override
public void run() {
getEventManager().callEvent(new ServerTickEvent(currentTick++, PacketEvents.currentTimeMS()));
}
};
serverTickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, 0L, 1L);
}
}
public static void cleanup() {
if (serverTickTask != null) {
serverTickTask.cancel();
}
getEventManager().unregisterAllListeners();
}
public static ServerVersion getServerVersion() {
return version;
}
public static PacketEvents getInstance() {
return instance == null ? instance = new PacketEvents() : instance;
}
public static boolean isServerTickTaskEnabled() {
return serverTickTask != null;
}
public static double[] getRecentServerTPS() {
double[] tpsArray = new double[0];
try {
tpsArray = NMSUtils.recentTPS();
} catch (IllegalAccessException 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;
}
public static double getCurrentServerTPS() {
return getRecentServerTPS()[0];
}
public static int getPing(final Player player) {
return NMSUtils.getPlayerPing(player);
}
public static long currentTimeMS() {
return System.currentTimeMillis();
}
public static void sendPacket(final Player player, final Sendable sendable) {
NMSUtils.sendSendableWrapper(player, sendable);
}
}
@@ -0,0 +1,17 @@
package io.github.retrooper.packetevents.enums;
public enum Direction {
DOWN, UP, NORTH, SOUTH, WEST, EAST
,NORTH_EAST,
NORTH_WEST, SOUTH_EAST,
SOUTH_WEST, WEST_NORTH_WEST,
NORTH_NORTH_WEST, NORTH_NORTH_EAST,
EAST_NORTH_EAST, EAST_SOUTH_EAST,
SOUTH_SOUTH_EAST, SOUTH_SOUTH_WEST,
WEST_SOUTH_WEST, SELF, NULL;
public static Direction get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,19 @@
package io.github.retrooper.packetevents.enums;
public enum EntityAnimationType {
SWING_MAIN_ARM, DAMAGE, LEAVE_BED, SWING_OFFHAND, CRITICAL_EFFECT, MAGIC_CRITICAL_EFFECT;
public static final EntityAnimationType get(final int i) {
return values()[i];
}
public final int getIndex() {
for(int i = 0; i < values().length; i++) {
final EntityAnimationType curType = values()[0];
if(curType == this) {
return i;
}
}
return -1;
}
}
@@ -0,0 +1,9 @@
package io.github.retrooper.packetevents.enums;
public enum EntityUseAction {
INTERACT, INTERACT_AT, ATTACK, INVALID;
public static EntityUseAction get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,6 @@
package io.github.retrooper.packetevents.enums;
public enum Hand {
MAIN_HAND,
OFF_HAND;
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.enums;
package io.github.retrooper.packetevents.enums;
public enum PlayerAction {
START_SNEAKING,
@@ -18,4 +18,8 @@ public enum PlayerAction {
OPEN_INVENTORY,
START_FALL_FLYING;
public static PlayerAction get(final byte i) {
return values()[i];
}
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.enums;
package io.github.retrooper.packetevents.enums;
public enum PlayerDigType {
@@ -18,6 +18,7 @@ public enum PlayerDigType {
WRONG_PACKET;
public static PlayerDigType get(final byte i) {
return values()[i];
}
}
@@ -0,0 +1,71 @@
package io.github.retrooper.packetevents.enums;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
public enum ServerVersion {
v_1_7_10, v_1_8, v_1_8_3, v_1_8_8, v_1_9, v_1_9_4, v_1_10, v_1_11, v_1_12, v_1_13, v_1_13_2, v_1_14, v_1_15,
ERROR;
public static ServerVersion getVersion() {
ServerVersion[] vals = values();
ArrayUtils.reverse(vals);
for (ServerVersion val : vals) {
String valName = val.name().substring(2).replace("_", ".");
if (Bukkit.getBukkitVersion().contains(valName)) {
return val;
}
}
return ERROR;
}
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static String getNmsSuffix() {
return nmsVersionSuffix;
}
public static String getNMSDirectory() {
return "net.minecraft.server." + nmsVersionSuffix;
}
public static String getOBCDirectory() {
return "org.bukkit.craftbukkit." + getNmsSuffix();
}
/**
* Returns if the current version is more up to date than the argument passed version
*
* @param version
* @return
*/
public boolean isHigherThan(final ServerVersion version) {
if (this == version) return false;
return !isLowerThan(version);
}
/**
* Returns if the current version is more outdated than the argument passed version
*
* @param version
* @return
*/
public boolean isLowerThan(final ServerVersion version) {
if(version == this) return false;
byte len = (byte) values().length;
for (byte i = 0; i < len; i++) {
final ServerVersion v = values()[i];
if(v == this) {
return true;
}
else if(v == version) {
return false;
}
}
return false;
}
}
@@ -0,0 +1,22 @@
package io.github.retrooper.packetevents.event;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.enums.ServerVersion;
/**
* Incoming and sent packets are called asynchronously,
* recommended to avoid non thread safe bukkit operations
*/
public class PacketEvent {
protected long timestamp = PacketEvents.currentTimeMS();
protected static ServerVersion version = PacketEvents.getServerVersion();
/**
* Timestamp of the packet
* @return
*/
public long getTimestamp() {
return timestamp;
}
}
@@ -1,4 +1,4 @@
package me.purplex.packetevents.events.handler;
package io.github.retrooper.packetevents.event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -7,6 +7,11 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
/**
* Just like Bukkit's @EventHandler, but for packets.
* Make sure your class implements the PacketListener interface, and is registered!
*/
public @interface PacketHandler {
}
@@ -0,0 +1,4 @@
package io.github.retrooper.packetevents.event;
public interface PacketListener {
}
@@ -0,0 +1,20 @@
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;
}
}
@@ -1,26 +1,18 @@
package me.purplex.packetevents.events.packetevent;
package io.github.retrooper.packetevents.event.impl;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.PacketEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PacketReceiveEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
private final long timestamp;
private boolean cancelled;
public final ServerVersion version;
public PacketReceiveEvent(Player player, String packetName, Object packet) {
this.version = PacketEvents.getServerVersion();
public PacketReceiveEvent(final Player player, final String packetName, final Object packet) {
this.player = player;
this.name = packetName;
this.packet = packet;
this.timestamp = (System.nanoTime() / 1000000);
this.cancelled = false;
}
/**
@@ -50,15 +42,6 @@ public class PacketReceiveEvent extends PacketEvent {
return this.packet;
}
/**
* The time the packet was received(ms)
*
* @return
*/
public long getTimestamp() {
return timestamp;
}
/**
* Cancel the packet
*
@@ -1,24 +1,19 @@
package me.purplex.packetevents.events.packetevent;
package io.github.retrooper.packetevents.event.impl;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.PacketEvent;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PacketSendEvent extends PacketEvent {
private final Player player;
private final String name;
private final Object packet;
private final long timestamp;
private boolean cancelled;
public final ServerVersion version;
public PacketSendEvent(Player player, String packetName, Object packet) {
this.version = PacketEvents.getServerVersion();
public PacketSendEvent(final Player player, final String packetName, final Object packet) {
this.player = player;
this.name = packetName;
this.packet = packet;
this.timestamp = (System.nanoTime() / 1000000);
this.cancelled = false;
}
@@ -41,12 +36,6 @@ public class PacketSendEvent extends PacketEvent {
}
public long getTimestamp() {
return timestamp;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PlayerInjectEvent extends PacketEvent {
private final Player player;
public PlayerInjectEvent(final Player player) {
this.player = player;
}
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.event.PacketEvent;
import org.bukkit.entity.Player;
public class PlayerUninjectEvent extends PacketEvent {
private final Player player;
public PlayerUninjectEvent(final Player player) {
this.player =player;
}
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,21 @@
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;
}
}
@@ -0,0 +1,32 @@
package io.github.retrooper.packetevents.event.impl;
import io.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.event.PacketEvent;
public class ServerTickEvent extends PacketEvent {
private final int tick;
private final double tps;
public ServerTickEvent(final int tick, final long timestamp) {
this.tick = tick;
this.timestamp = timestamp;
this.tps = PacketEvents.getCurrentServerTPS();
}
public ServerTickEvent(final int tick) {
this.tick = tick;
this.tps = PacketEvents.getCurrentServerTPS();
}
public long getTimestamp() {
return timestamp;
}
public int getCurrentTick() {
return tick;
}
public double getCurrentServerTPS() {
return tps;
}
}
@@ -0,0 +1,53 @@
package io.github.retrooper.packetevents.event.manager;
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;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class EventManager {
private HashMap<PacketListener, List<Method>> registeredMethods = new HashMap<PacketListener, List<Method>>();
public void callEvent(final PacketEvent e) {
for (final PacketListener listener : registeredMethods.keySet()) {
//Annotated methods
final List<Method> methods = registeredMethods.get(listener);
for (final Method method : methods) {
if (method.getParameterTypes()[0].equals(PacketEvent.class)
|| method.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
method.invoke(listener, e);
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
}
}
public void registerListener(final PacketListener e) {
final List<Method> methods = new ArrayList<Method>();
for (final Method m : e.getClass().getMethods()) {
if (m.isAnnotationPresent(PacketHandler.class)) {
methods.add(m);
}
}
registeredMethods.put(e, methods);
}
public void unregisterListener(final PacketListener e) {
registeredMethods.remove(e);
}
public void unregisterAllListeners() {
registeredMethods.clear();
}
}
@@ -0,0 +1,59 @@
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;
}
}
@@ -0,0 +1,37 @@
package io.github.retrooper.packetevents.example;
import io.github.retrooper.packetevents.PacketEvents;
import org.bukkit.plugin.java.JavaPlugin;
public class MainExample extends JavaPlugin {
@Override
public void onEnable() {
//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());
}
@Override
public void onDisable() {
/**
* Stops server tick event task if enabled and unregister all listeners
*/
PacketEvents.cleanup();
}
}
@@ -0,0 +1,169 @@
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,28 @@
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;
}
}
@@ -0,0 +1,47 @@
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;
}
}
@@ -0,0 +1,69 @@
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,81 @@
package io.github.retrooper.packetevents.packet;
public abstract class Packet {
public static class Client {
private static final String c = "PacketPlayIn";
@Deprecated
public static final String FLYING = c + "Flying";
public static final String POSITION = c + "Position";
public static final String POSITION_LOOK = c + "PositionLook";
public static final String LOOK = c + "Look";
public static final String CLIENT_COMMAND = c + "ClientCommand";
public static final String TRANSACTION = c + "Transaction";
public static final String BLOCK_DIG = c + "BlockDig";
public static final String ENTITY_ACTION = c + "EntityAction";
public static final String USE_ENTITY = c + "UseEntity";
public static final String WINDOW_CLICK = c + "WindowClick";
public static final String STEER_VEHICLE = c + "SteerVehicle";
public static final String CUSTOM_PAYLOAD = c + "CustomPayload";
public static final String ARM_ANIMATION = c + "ArmAnimation";
public static final String BLOCK_PLACE = c + "BlockPlace";
public static final String ABILITIES = c + "Abilities";
public static final String HELD_ITEM_SLOT = c + "HeldItemSlot";
public static final String CLOSE_WINDOW = c + "CloseWindow";
public static final String TAB_COMPLETE = c + "TabComplete";
public static final String CHAT = c + "Chat";
public static final String SET_CREATIVE_SLOT = c + "SetCreativeSlot";
public static final String KEEP_ALIVE = c + "KeepAlive";
}
public static class Server {
private static final String s = "PacketPlayOut";
public static final String ANIMATION = s + "Animation";
public static final String KEEP_ALIVE = s + "KeepAlive";
public static final String CHAT = s + "Chat";
public static final String POSITION = s + "Position";
public static final String TRANSACTION = s + "Transaction";
public static final String NAMED_ENTITY_SPAWN = s + "NamedEntitySpawn";
public static final String SPAWN_ENTITY_LIVING = s + "SpawnEntityLiving";
public static final String SPAWN_ENTITY = s + "SpawnEntity";
public static final String CUSTOM_PAYLOAD = s + "CustomPayload";
public static final String ABILITIES = s + "Abilities";
public static final String ENTITY_METADATA = s + "EntityMetadata";
public static final String ENTITY_VELOCITY = s + "EntityVelocity";
public static final String ENTITY_DESTROY = s + "EntityDestroy";
public static final String ENTITY_HEAD_ROTATION = s + "EntityHeadRotation";
public static final String BLOCK_CHANGE = s + "BlockChange";
public static final String CLOSE_WINDOW = s + "CloseWindow";
public static final String HELD_ITEM_SLOT = s + "HeldItemSlot";
public static final String TAB_COMPLETE = s + "TabComplete";
public static final String RESPAWN = s + "Respawn";
public static final String WORLD_PARTICLES = s + "WorldParticles";
public static final String COMMANDS = s + "Commands";
public static final String OPEN_WINDOW = s + "OpenWindow";
public static final String LOGIN = s + "Login";
public static final String SERVER_DIFFICULTY = s + "ServerDifficulty";
}
public static class Login {
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
public static final String PING = "PacketStatusInPing";
public static final String START = "PacketStatusInStart";
public static final String SUCCESS = "PacketLoginOutSuccess";
}
public static 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);
}
}
@@ -0,0 +1,5 @@
package io.github.retrooper.packetevents.packetwrappers;
public interface Sendable {
public Object asNMSPacket();
}
@@ -0,0 +1,50 @@
package io.github.retrooper.packetevents.packetwrappers.api;
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!";
public WrappedPacket(final Object packet) {
this.player = null;
if(packet == null)return;
this.packet = packet;
try {
setup();
} catch (final Exception e) {
e.printStackTrace();
}
}
public WrappedPacket(final Player player, final Object packet) {
this.player = player;
if(packet == null)return;
this.packet = packet;
try {
setup();
} catch (final Exception e) {
e.printStackTrace();
}
}
protected void setup() {
}
protected void throwUnsupportedVersion() {
throw new IllegalStateException(err);
}
public final Player getPlayer() {
return player;
}
}
@@ -0,0 +1,88 @@
package io.github.retrooper.packetevents.packetwrappers.in.abilities;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInAbilities extends WrappedPacket {
private boolean isVulnerable;
private boolean isFlying;
private boolean allowFly;
private boolean instantBuild;
private float flySpeed;
private float walkSpeed;
public WrappedPacketInAbilities(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.isVulnerable = fields[0].getBoolean(packet);
this.isFlying = fields[1].getBoolean(packet);
this.allowFly = fields[2].getBoolean(packet);
this.instantBuild = fields[3].getBoolean(packet);
this.flySpeed = fields[4].getFloat(packet);
this.walkSpeed = fields[5].getFloat(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public boolean isVulnerable() {
return isVulnerable;
}
public boolean isFlying() {
return isFlying;
}
public boolean canFly() {
return allowFly;
}
public boolean canInstantlyBuild() {
return instantBuild;
}
public float getFlySpeed() {
return flySpeed;
}
public float getWalkSpeed() {
return walkSpeed;
}
private static Class<?> abilitiesClass;
private static Field[] fields = new Field[6];
static {
try {
abilitiesClass = NMSUtils.getNMSClass("PacketPlayInAbilities");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
fields[0] = abilitiesClass.getDeclaredField("a");
fields[1] = abilitiesClass.getDeclaredField("b");
fields[2] = abilitiesClass.getDeclaredField("c");
fields[3] = abilitiesClass.getDeclaredField("d");
fields[4] = abilitiesClass.getDeclaredField("e");
fields[5] = abilitiesClass.getDeclaredField("f");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
}
}
@@ -0,0 +1,143 @@
package io.github.retrooper.packetevents.packetwrappers.in.blockdig;
import io.github.retrooper.packetevents.enums.Direction;
import io.github.retrooper.packetevents.enums.PlayerDigType;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.BaseBlockUtils;
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;
}
//ALL
private static Class<?> blockDigClass;
//1.8
private static Field[] fields = new Field[3];
private static Class<?> blockPositionClass;
private static Field[] blockPosXYZ = new Field[3];
//1.7
private static Field face;
private static Field e;
static {
try {
blockDigClass = NMSUtils.getNMSClass("PacketPlayInBlockDig");
if (version != ServerVersion.v_1_7_10) {
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//blockpos
fields[0] = blockDigClass.getDeclaredField("a");
//direction
fields[1] = blockDigClass.getDeclaredField("b");
//digtype
fields[2] = blockDigClass.getDeclaredField("c");
if (version != ServerVersion.v_1_7_10) {
blockPosXYZ[0] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosXFieldName());
blockPosXYZ[1] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosXFieldName());
blockPosXYZ[2] = blockPositionClass.getSuperclass().getDeclaredField(BaseBlockUtils.getPosZFieldName());
} else {
face = blockDigClass.getDeclaredField("face");
e = blockDigClass.getDeclaredField("e");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for(Field f : fields) {
if(f != null) {
f.setAccessible(true);
}
}
for(Field f : blockPosXYZ) {
if(f != null) {
f.setAccessible(true);
}
}
if(e != null) {
e.setAccessible(true);
}
if(face != null) {
face.setAccessible(true);
}
}
}
@@ -0,0 +1,70 @@
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;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class WrappedPacketInBlockPlace extends WrappedPacket {
private Vector3i blockPosition;
private Hand hand;
private ItemStack itemStack;
public WrappedPacketInBlockPlace(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
//1.7.10
Vector3i position = null;
ItemStack itemStack = null;
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) {
e.printStackTrace();
}
this.blockPosition = position;
this.itemStack = itemStack;
this.hand = hand;
}
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();
}
}
}
@@ -0,0 +1,65 @@
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.block.Block;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
private Block block;
private Hand hand;
public WrappedPacketInBlockPlace_1_9(final Player player, final Object packet) {
super(player, packet);
}
@Override
protected void setup() {
try {
this.block = BlockFinder.getBlocksInDirection(getPlayer(), 10);
final Object enumHandObj = enumHandField.get(packet);
this.hand = Hand.valueOf(enumHandObj.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Hand getHand() {
return hand;
}
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);
}
}
}
@@ -0,0 +1,153 @@
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);
}
}
}
}
@@ -0,0 +1,57 @@
package io.github.retrooper.packetevents.packetwrappers.in.chat;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInChat extends WrappedPacket {
private String message;
public WrappedPacketInChat(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
final Object obj = field.get(packet);
this.message = obj.toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public String getMessage() {
return message;
}
private static Class<?> chatPacketClass;
private static Field field;
static {
try {
chatPacketClass = NMSUtils.getNMSClass("PacketPlayInChat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
field = chatPacketClass.getDeclaredField(getChatFieldName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
}
private static String getChatFieldName() {
if (version == ServerVersion.v_1_7_10) {
return "message";
}
return "a";
}
}
@@ -0,0 +1,111 @@
package io.github.retrooper.packetevents.packetwrappers.in.entityaction;
import io.github.retrooper.packetevents.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 {
private Entity entity;
private int entityId;
private PlayerAction action;
private int jumpBoost;
public WrappedPacketInEntityAction(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
final int entityId = fields[0].getInt(packet);
final int jumpBoost = fields[2].getInt(packet);
int animationIndex = -1;
//1.7.10
if (version.isLowerThan(ServerVersion.v_1_8)) {
animationIndex = fields[1].getInt(packet);
} else {
final Object enumObj = fields[1].get(packet);
final Object[] enumValues = enumPlayerActionConstants;
final int len = enumValues.length;
for (int i = 0; i < len; i++) {
final Object val = enumValues[i];
if (val.toString().equals(enumObj.toString())) {
animationIndex = i;
break;
}
}
}
this.entityId = entityId;
this.action = action;
this.jumpBoost = jumpBoost;
this.action = PlayerAction.get((byte) animationIndex);
this.entity = NMSUtils.getEntityById(this.entityId);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Entity getEntity() {
return entity;
}
public int getEntityId() {
return entityId;
}
public PlayerAction getAction() {
return action;
}
public int getJumpBoost() {
return jumpBoost;
}
private static Class<?> entityActionClass;
@Nullable
private static Class<?> enumPlayerActionClass;
private static Field[] fields = new Field[3];
@Nullable
private static Object[] enumPlayerActionConstants;
static {
try {
entityActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction");
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
enumPlayerActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction$EnumPlayerAction");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//ints in 1.7.10, EnumPlayerAction in 1.8+
fields[0] = entityActionClass.getDeclaredField("a");
fields[1] = entityActionClass.getDeclaredField("animation");
fields[2] = entityActionClass.getDeclaredField("c");
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
enumPlayerActionConstants = enumPlayerActionClass.getEnumConstants();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,148 @@
package io.github.retrooper.packetevents.packetwrappers.in.flying;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInFlying extends WrappedPacket {
private double x;
private double y;
private double z;
private float yaw;
private float pitch;
private boolean onGround;
private boolean isPosition;
private boolean isLook;
public WrappedPacketInFlying(Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.x = fields[0].getDouble(packet);
this.y = fields[1].getDouble(packet);
this.z = fields[2].getDouble(packet);
this.yaw = fields[3].getFloat(packet);
this.pitch = fields[4].getFloat(packet);
this.onGround = fields[5].getBoolean(packet);
this.isPosition = fields[6].getBoolean(packet);
this.isLook = fields[7].getBoolean(packet);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static class WrappedPacketInPosition extends WrappedPacketInFlying {
public WrappedPacketInPosition(Object packet) {
super(packet);
}
@Override
public boolean isPosition() {
return true;
}
@Override
public boolean isLook() {
return false;
}
}
public static class WrappedPacketInPosition_Look extends WrappedPacketInFlying {
public WrappedPacketInPosition_Look(Object packet) {
super(packet);
}
@Override
public boolean isLook() {
return true;
}
@Override
public boolean isPosition() {
return false;
}
}
public 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";
}
}
@@ -0,0 +1,58 @@
package io.github.retrooper.packetevents.packetwrappers.in.keepalive;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Field;
public class WrappedPacketInKeepAlive extends WrappedPacket {
public WrappedPacketInKeepAlive(final Object packet) {
super(packet);
}
private long id;
@Override
protected void setup() {
try {
if (version.isHigherThan(ServerVersion.v_1_12)) {
this.id = idField.getLong(packet);
} else {
this.id = idField.getInt(packet);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* Cast this long to an integer if you are using 1.7.10->1.12.2!
* In 1.13.2->1.15.2 a long is sent
*
* @return
*/
public long getId() {
return id;
}
private static Class<?> keepAliveClass;
//1.7.10->1.12.2 has int field "a", rest as long field "a"
private static Field idField;
static {
try {
keepAliveClass = NMSUtils.getNMSClass("PacketPlayInKeepAlive");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
idField = keepAliveClass.getDeclaredField("a");
idField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,78 @@
package io.github.retrooper.packetevents.packetwrappers.in.useentity;
import io.github.retrooper.packetevents.enums.EntityUseAction;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Field;
public class WrappedPacketInUseEntity extends WrappedPacket {
private int entityId;
private Entity entity;
private EntityUseAction action;
public WrappedPacketInUseEntity(final Object packet) {
super(packet);
}
@Override
protected void setup() {
try {
this.entityId = fields[0].getInt(packet);
this.entity = NMSUtils.getEntityById(this.entityId);
final Object useActionEnum = fields[1].get(packet);
this.action = EntityUseAction.valueOf(useActionEnum.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public Entity getEntity() {
return entity;
}
public int getEntityId() {
return entityId;
}
public EntityUseAction getAction() {
return action;
}
private static Class<?> useEntityClass;
private static Class<?> entityClass;
private static Field[] fields = new Field[2];
static {
try {
useEntityClass = NMSUtils.getNMSClass("PacketPlayInUseEntity");
entityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
fields[0] = useEntityClass.getDeclaredField("a");
fields[1] = useEntityClass.getDeclaredField("action");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (Field f : fields) {
if (f != null) {
f.setAccessible(true);
}
}
}
}
@@ -0,0 +1,4 @@
package io.github.retrooper.packetevents.packetwrappers.login;
public class WrappedPacketLoginHandshake {
}
@@ -0,0 +1,98 @@
package io.github.retrooper.packetevents.packetwrappers.out.animation;
import io.github.retrooper.packetevents.enums.EntityAnimationType;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import org.bukkit.entity.Entity;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class WrappedPacketOutAnimation extends WrappedPacket implements Sendable {
private Entity entity;
private int entityID;
private EntityAnimationType type;
public WrappedPacketOutAnimation(final Object packet) {
super(packet);
}
public WrappedPacketOutAnimation(final Entity target, final EntityAnimationType type) {
super(null);
this.entityID = target.getEntityId();
this.entity = target;
this.type = type;
}
@Override
protected void setup() {
try {
//a - ID
//b - TYPE
this.entityID = fields[0].getInt(packet);
this.entity = NMSUtils.getEntityById(this.entityID);
this.type = EntityAnimationType.get(fields[1].getInt(packet));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public final Entity getEntity() {
return this.entity;
}
public final int getEntityId() {
return this.entityID;
}
public final EntityAnimationType getAnimationType() {
return type;
}
@Override
public Object asNMSPacket() {
final Object nmsEntity = NMSUtils.getNMSEntity(this.entity);
final int index = type.getIndex();
try {
return animationConstructor.newInstance(nmsEntity, index);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static Class<?> animationClass, nmsEntityClass;
private static Constructor<?> animationConstructor;
private static Field[] fields = new Field[2];
static {
try {
animationClass = NMSUtils.getNMSClass("PacketPlayOutAnimation");
nmsEntityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
animationConstructor = animationClass.getConstructor(nmsEntityClass, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
fields[0] = animationClass.getDeclaredField("a");
fields[1] = animationClass.getDeclaredField("b");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,90 @@
package io.github.retrooper.packetevents.packetwrappers.out.chat;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.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;
private static Constructor<?> chatClassConstructor;
private static Class<?> iChatBaseComponentClass;
private static Class<?> chatSerializer;
private static Method serialize;
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");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
chatClassConstructor = chatClass.getConstructor(iChatBaseComponentClass);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
serialize = chatSerializer.getMethod("a", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,147 @@
package io.github.retrooper.packetevents.packetwrappers.out.entityvelocity;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
import io.github.retrooper.packetevents.utils.NMSUtils;
import 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;
}
private static Constructor<?> velocityConstructor, vec3dConstructor;
private static Class<?> velocityClass, vec3dClass;
private static Field[] fields = new Field[4];
/**
* Velocity Constructor parameter types:
* 1.7.10->1.13.2 use int, double, double, double style,
* 1.14+ use int, Vec3D style
*/
static {
Vec3D vec = new Vec3D(0, 0, 0);
try {
velocityClass = NMSUtils.getNMSClass("PacketPlayOutEntityVelocity");
if (version.isHigherThan(ServerVersion.v_1_13_2)) {
vec3dClass = NMSUtils.getNMSClass("Vec3D");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
if (version.isHigherThan(ServerVersion.v_1_13_2)) {
velocityConstructor = velocityClass.getConstructor(int.class, vec3dClass);
//vec3d constructor
vec3dConstructor = vec3dClass.getConstructor(double.class, double.class, double.class);
} else {
velocityConstructor = velocityClass.getConstructor(int.class, double.class, double.class, double.class);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
//entity id
fields[0] = velocityClass.getDeclaredField("a");
//x
fields[1] = velocityClass.getDeclaredField("b");
//y
fields[2] = velocityClass.getDeclaredField("c");
//z
fields[3] = velocityClass.getDeclaredField("d");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
for (final Field f : fields) {
f.setAccessible(true);
}
}
}
@@ -0,0 +1,403 @@
package io.github.retrooper.packetevents.tinyprotocol;
import org.bukkit.Bukkit;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* An utility class that simplifies reflection in Bukkit plugins.
*
* @author Kristian
*/
public final class Reflection {
/**
* An interface for invoking a specific constructor.
*/
public interface ConstructorInvoker {
/**
* Invoke a constructor for a specific class.
*
* @param arguments - the arguments to pass to the constructor.
* @return The constructed object.
*/
Object invoke(Object... arguments);
}
/**
* An interface for invoking a specific method.
*/
public interface MethodInvoker {
/**
* Invoke a method on a specific target object.
*
* @param target - the target object, or NULL for a static method.
* @param arguments - the arguments to pass to the method.
* @return The return value, or NULL if is void.
*/
Object invoke(Object target, Object... arguments);
}
/**
* An interface for retrieving the field content.
*
* @param <T> - field type.
*/
public interface FieldAccessor<T> {
/**
* Retrieve the content of a field.
*
* @param target - the target object, or NULL for a static field.
* @return The value of the field.
*/
T get(Object target);
/**
* Set the content of a field.
*
* @param target - the target object, or NULL for a static field.
* @param value - the new value of the field.
*/
void set(Object target, Object value);
/**
* Determine if the given object has this field.
*
* @param target - the object to test.
* @return TRUE if it does, FALSE otherwise.
*/
boolean hasField(Object target);
}
// Deduce the net.minecraft.server.v* package
private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server");
private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", "");
// Variable replacement
private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");
private Reflection() {
// Seal class
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param target - the target type.
* @param name - the name of the field, or NULL to ignore.
* @param fieldType - a compatible field type.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType) {
return getField(target, name, fieldType, 0);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param name - the name of the field, or NULL to ignore.
* @param fieldType - a compatible field type.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(String className, String name, Class<T> fieldType) {
return getField(getClass(className), name, fieldType, 0);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param target - the target type.
* @param fieldType - a compatible field type.
* @param index - the number of compatible fields to skip.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(Class<?> target, Class<T> fieldType, int index) {
return getField(target, null, fieldType, index);
}
/**
* Retrieve a field accessor for a specific field type and name.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param fieldType - a compatible field type.
* @param index - the number of compatible fields to skip.
* @return The field accessor.
*/
public static <T> FieldAccessor<T> getField(String className, Class<T> fieldType, int index) {
return getField(getClass(className), fieldType, index);
}
// Common method
private static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType, int index) {
for (final Field field : target.getDeclaredFields()) {
if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) {
field.setAccessible(true);
// A function for retrieving a specific field value
return new FieldAccessor<T>() {
@Override
@SuppressWarnings("unchecked")
public T get(Object target) {
try {
return (T) field.get(target);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access reflection.", e);
}
}
@Override
public void set(Object target, Object value) {
try {
field.set(target, value);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access reflection.", e);
}
}
@Override
public boolean hasField(Object target) {
// target instanceof DeclaringClass
return field.getDeclaringClass().isAssignableFrom(target.getClass());
}
};
}
}
// Search in parent classes
if (target.getSuperclass() != null)
return getField(target.getSuperclass(), name, fieldType, index);
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getMethod(String className, String methodName, Class<?>... params) {
return getTypedMethod(getClass(className), methodName, null, params);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getMethod(Class<?> clazz, String methodName, Class<?>... params) {
return getTypedMethod(clazz, methodName, null, params);
}
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param returnType - the expected return type, or NULL to ignore.
* @param params - the expected parameters.
* @return An object that invokes this specific method.
* @throws IllegalStateException If we cannot find this method.
*/
public static MethodInvoker getTypedMethod(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... params) {
for (final Method method : clazz.getDeclaredMethods()) {
if ((methodName == null || method.getName().equals(methodName))
&& (returnType == null || method.getReturnType().equals(returnType))
&& Arrays.equals(method.getParameterTypes(), params)) {
method.setAccessible(true);
return new MethodInvoker() {
@Override
public Object invoke(Object target, Object... arguments) {
try {
return method.invoke(target, arguments);
} catch (Exception e) {
throw new RuntimeException("Cannot invoke method " + method, e);
}
}
};
}
}
// Search in every superclass
if (clazz.getSuperclass() != null)
return getMethod(clazz.getSuperclass(), methodName, params);
throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params)));
}
/**
* Search for the first publically and privately defined constructor of the given name and parameter count.
*
* @param className - lookup name of the class, see {@link #getClass(String)}.
* @param params - the expected parameters.
* @return An object that invokes this constructor.
* @throws IllegalStateException If we cannot find this method.
*/
public static ConstructorInvoker getConstructor(String className, Class<?>... params) {
return getConstructor(getClass(className), params);
}
/**
* Search for the first publically and privately defined constructor of the given name and parameter count.
*
* @param clazz - a class to start with.
* @param params - the expected parameters.
* @return An object that invokes this constructor.
* @throws IllegalStateException If we cannot find this method.
*/
public static ConstructorInvoker getConstructor(Class<?> clazz, Class<?>... params) {
for (final Constructor<?> constructor : clazz.getDeclaredConstructors()) {
if (Arrays.equals(constructor.getParameterTypes(), params)) {
constructor.setAccessible(true);
return new ConstructorInvoker() {
@Override
public Object invoke(Object... arguments) {
try {
return constructor.newInstance(arguments);
} catch (Exception e) {
throw new RuntimeException("Cannot invoke constructor " + constructor, e);
}
}
};
}
}
throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params)));
}
/**
* Retrieve a class from its full name, without knowing its type on compile time.
* <p>
* This is useful when looking up fields by a NMS or OBC type.
* <p>
*
* @see {@link #getClass()} for more information.
* @param lookupName - the class name with variables.
* @return The class.
*/
public static Class<Object> getUntypedClass(String lookupName) {
@SuppressWarnings({ "rawtypes", "unchecked" })
Class<Object> clazz = (Class) getClass(lookupName);
return clazz;
}
/**
* Retrieve a class from its full name.
* <p>
* Strings enclosed with curly brackets - such as {TEXT} - will be replaced according to the following table:
* <p>
* <table border="1">
* <tr>
* <th>Variable</th>
* <th>Content</th>
* </tr>
* <tr>
* <td>{nms}</td>
* <td>Actual package name of net.minecraft.server.VERSION</td>
* </tr>
* <tr>
* <td>{obc}</td>
* <td>Actual pacakge name of org.bukkit.craftbukkit.VERSION</td>
* </tr>
* <tr>
* <td>{version}</td>
* <td>The current Minecraft package VERSION, if any.</td>
* </tr>
* </table>
*
* @param lookupName - the class name with variables.
* @return The looked up class.
* @throws IllegalArgumentException If a variable or class could not be found.
*/
public static Class<?> getClass(String lookupName) {
return getCanonicalClass(expandVariables(lookupName));
}
/**
* Retrieve a class in the net.minecraft.server.VERSION.* package.
*
* @param name - the name of the class, excluding the package.
* @throws IllegalArgumentException If the class doesn't exist.
*/
public static Class<?> getMinecraftClass(String name) {
return getCanonicalClass(NMS_PREFIX + "." + name);
}
/**
* Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package.
*
* @param name - the name of the class, excluding the package.
* @throws IllegalArgumentException If the class doesn't exist.
*/
public static Class<?> getCraftBukkitClass(String name) {
return getCanonicalClass(OBC_PREFIX + "." + name);
}
/**
* Retrieve a class by its canonical name.
*
* @param canonicalName - the canonical name.
* @return The class.
*/
private static Class<?> getCanonicalClass(String canonicalName) {
try {
return Class.forName(canonicalName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Cannot find " + canonicalName, e);
}
}
/**
* Expand variables such as "{nms}" and "{obc}" to their corresponding packages.
*
* @param name - the full name of the class.
* @return The expanded string.
*/
private static String expandVariables(String name) {
StringBuffer output = new StringBuffer();
Matcher matcher = MATCH_VARIABLE.matcher(name);
while (matcher.find()) {
String variable = matcher.group(1);
String replacement = "";
// Expand all detected variables
if ("nms".equalsIgnoreCase(variable))
replacement = NMS_PREFIX;
else if ("obc".equalsIgnoreCase(variable))
replacement = OBC_PREFIX;
else if ("version".equalsIgnoreCase(variable))
replacement = VERSION;
else
throw new IllegalArgumentException("Unknown variable: " + variable);
// Assume the expanded variables are all packages, and append a dot
if (replacement.length() > 0 && matcher.end() < name.length() && name.charAt(matcher.end()) != '.')
replacement += ".";
matcher.appendReplacement(output, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(output);
return output.toString();
}
}
@@ -0,0 +1,560 @@
/*
* 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));
}
}
}
}
}
@@ -0,0 +1,559 @@
/*
* 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));
}
}
}
}
}
@@ -0,0 +1,33 @@
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";
}
}
@@ -0,0 +1,16 @@
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;
}
}
@@ -0,0 +1,197 @@
package io.github.retrooper.packetevents.utils;
import io.github.retrooper.packetevents.enums.ServerVersion;
import io.github.retrooper.packetevents.packetwrappers.Sendable;
import io.github.retrooper.packetevents.utils.nms_entityfinder.EntityFinderUtils;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public 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";
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;
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 Field recentTPSField;
private static Field entityPlayerPingField;
private static Field playerConnectionField;
static {
try {
minecraftServerClass = getNMSClass("MinecraftServer");
craftWorldsClass = getOBCClass("CraftWorld");
craftPlayerClass = getOBCClass("entity.CraftPlayer");
entityPlayerClass = getNMSClass("EntityPlayer");
packetClass = getNMSClass("Packet");
playerConnectionClass = getNMSClass("PlayerConnection");
serverConnectionClass = getNMSClass("ServerConnection");
craftEntityClass = getOBCClass("entity.CraftEntity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//METHODS
try {
getServerMethod = minecraftServerClass.getMethod("getServer");
getCraftWorldHandleMethod = craftWorldsClass.getMethod("getHandle");
getCraftPlayerHandle = craftPlayerClass.getMethod("getHandle");
getCraftEntityHandle = craftEntityClass.getMethod("getHandle");
sendPacketMethod = playerConnectionClass.getMethod("sendPacket", packetClass);
getServerConnection = minecraftServerClass.getMethod("getServerConnection");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
recentTPSField = minecraftServerClass.getField("recentTps");
entityPlayerPingField = entityPlayerClass.getField("ping");
playerConnectionField = entityPlayerClass.getField("playerConnection");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public static Object getMinecraftServerInstance() throws InvocationTargetException, IllegalAccessException {
return getServerMethod.invoke(null);
}
public static double[] recentTPS() throws IllegalAccessException, InvocationTargetException {
final Object minecraftServerObj = getMinecraftServerInstance();
double[] recentTPS = (double[]) recentTPSField.get(minecraftServerObj);
return recentTPS;
}
public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
return Class.forName(nmsDir + "." + name);
}
public static Class<?> getOBCClass(String name) throws ClassNotFoundException {
return Class.forName(obcDir + "." + name);
}
public static Class<?> getNettyClass(String name) throws ClassNotFoundException {
return Class.forName(nettyPrefix + "." + name);
}
public static final String getChannelFutureListFieldName() {
if (version.isLowerThan(ServerVersion.v_1_8))
return "e";
if (version.isLowerThan(ServerVersion.v_1_13))
return "g";
return "f";
}
@Nullable
public static Entity getEntityById(final int id) {
return EntityFinderUtils.getEntityById(id);
}
@Nullable
public static Entity getEntityByIdWithWorld(final World world, final int id) {
return EntityFinderUtils.getEntityByIdWithWorld(world, id);
}
public static Object getNMSEntity(final Entity entity) {
final Object craftEntity = craftEntityClass.cast(entity);
try {
return getCraftEntityHandle.invoke(craftEntity);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object getEntityPlayer(final Player player) {
try {
return getCraftPlayerHandle.invoke(craftPlayerClass.cast(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static int getPlayerPing(final Player player) {
final Object craftPlayer = craftPlayerClass.cast(player);
Object entityPlayer = null;
try {
entityPlayer = getCraftPlayerHandle.invoke(craftPlayer);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
try {
return entityPlayerPingField.getInt(entityPlayer);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}
public static boolean is_1_8() {
return version.isHigherThan(ServerVersion.v_1_7_10)
&& version.isLowerThan(ServerVersion.v_1_9);
}
public static void sendSendableWrapper(final Player player, final Sendable sendable) {
sendNMSPacket(player, sendable.asNMSPacket());
}
public static void sendNMSPacket(final Player player, final Object nmsPacket) {
Object entityPlayer = null;
try {
entityPlayer = getCraftPlayerHandle.invoke(craftPlayerClass.cast(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Object playerConnection = null;
try {
playerConnection = playerConnectionField.get(entityPlayer);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
sendPacketMethod.invoke(playerConnection, nmsPacket);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static String getServerConnectionFieldName() {
return "p";
}
}
@@ -0,0 +1,90 @@
package io.github.retrooper.packetevents.utils.nms_entityfinder;
import io.github.retrooper.packetevents.PacketEvents;
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 {
@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 Class<?> worldServerClass;
private static Class<?> craftWorldClass;
private static Class<?> entityClass;
private static Method getEntityByIdMethod;
private static Method craftWorldGetHandle;
private static Method getBukkitEntity;
static {
try {
worldServerClass = NMSUtils.getNMSClass("WorldServer");
craftWorldClass = NMSUtils.getOBCClass("CraftWorld");
entityClass = NMSUtils.getNMSClass("Entity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
getEntityByIdMethod = worldServerClass.getMethod(getEntityByNameMethodName(), int.class);
craftWorldGetHandle = craftWorldClass.getMethod("getHandle");
getBukkitEntity = entityClass.getMethod("getBukkitEntity");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static String getEntityByNameMethodName() {
if (version.isHigherThan(ServerVersion.v_1_7_10) && version.isLowerThan(ServerVersion.v_1_9)) {
return "a";
}
return "getEntity";
}
}
@@ -0,0 +1,15 @@
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;
}
}
@@ -0,0 +1,14 @@
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;
}
}
@@ -0,0 +1,15 @@
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;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3d {
public double x, y, z;
public Vector3d(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3f {
public float x, y, z;
public Vector3f(final float x, final float y, final float z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -0,0 +1,16 @@
package io.github.retrooper.packetevents.utils.vector;
public class Vector3i {
public int x, y, z;
public Vector3i(final int x, final int y, final int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "X: " + x + ", Y: " + y + ", Z: " + z;
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents;
import me.purplex.packetevents.customlistener.injector.PacketInjector;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.example.TestExample;
import org.bukkit.Bukkit;
import org.bukkit.event.*;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin implements Listener {
private static Main instance;
private static PacketInjector packetInjector;
@Override
public void onEnable() {
instance = this;
Bukkit.getPluginManager().registerEvents(this, this);
packetInjector = new PacketInjector();
PacketEvents.getPacketManager().registerPacketListener(new TestExample());
Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, new Runnable() {
@Override
public void run() {
long now = System.currentTimeMillis();
PacketEvents.getPacketManager().callServerTickEvent(new ServerTickEvent(now));
}
}, 0L, 1L);
}
@Override
public void onDisable() {
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
packetInjector.injectPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
packetInjector.uninjectPlayer(e.getPlayer());
}
public static Main getInstance() {
return instance;
}
}
@@ -1,20 +0,0 @@
package me.purplex.packetevents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.manager.PacketManager;
public class PacketEvents {
private static PacketManager packetManager;
public static ServerVersion getServerVersion() {
return ServerVersion.getVersion();
}
public static PacketManager getPacketManager() {
if (packetManager == null) {
packetManager = new PacketManager();
}
return packetManager;
}
}
@@ -1,118 +0,0 @@
package me.purplex.packetevents.customlistener.injector;
import io.netty.channel.*;
import me.purplex.packetevents.PacketEvents;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.*;
import org.bukkit.entity.Player;
public class PacketInjector {
private final static ServerVersion version = ServerVersion.getVersion();
public void injectPlayer(Player player) {
ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
String packetName = packet.getClass().getSimpleName();
PacketReceiveEvent e = new PacketReceiveEvent(player, packetName, packet);
PacketEvents.getPacketManager().callPacketReceiveEvent(e);
if(e.isCancelled()) {
return;
}
try {
super.channelRead(ctx, packet);
} catch (Exception exception) {
exception.printStackTrace();
}
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) {
String packetName = packet.getClass().getSimpleName();
PacketSendEvent e = new PacketSendEvent(player, packetName, packet);
PacketEvents.getPacketManager().callPacketSendEvent(e);
if(e.isCancelled()) {
return;
}
try {
super.write(ctx, packet, promise);
} catch (Exception exception) {
exception.printStackTrace();
}
}
};
Channel channel = getChannel(player);
ChannelPipeline pipeline = channel.pipeline();
pipeline.addBefore("packet_handler", player.getName(), channelDuplexHandler);
}
public void uninjectPlayer(Player player) {
Channel channel = getChannel(player);
channel.eventLoop().submit(()->{
channel.pipeline().remove(player.getName());
return null;
});
}
public Channel getChannel(Player player) {
Channel channel = null;
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
try {
channel = (Channel) networkManager.getClass().getField("i").get(networkManager);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
else if(version == ServerVersion.v_1_8_3) {
net.minecraft.server.v1_8_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.k;
}
else if(version == ServerVersion.v_1_8_8) {
net.minecraft.server.v1_8_R3.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_9) {
net.minecraft.server.v1_9_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_9_4) {
net.minecraft.server.v1_9_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_10) {
net.minecraft.server.v1_10_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_11) {
net.minecraft.server.v1_11_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_12) {
net.minecraft.server.v1_12_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_13) {
net.minecraft.server.v1_13_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_13_2) {
net.minecraft.server.v1_13_R2.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_14) {
net.minecraft.server.v1_14_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else if(version == ServerVersion.v_1_15) {
net.minecraft.server.v1_15_R1.NetworkManager networkManager = ((org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer) player).getHandle().playerConnection.networkManager;
channel = networkManager.channel;
}
else {
System.err.println("Version unsupported, please contact purplex#0001 and tell him what version your server is running on! Make sure you are using paperspigot or spigot.");
}
return channel;
}
}
@@ -1,5 +0,0 @@
package me.purplex.packetevents.enums;
public enum EntityUseAction {
INTERACT, INTERACT_AT, ATTACK, INVALID;
}
@@ -1,24 +0,0 @@
package me.purplex.packetevents.enums;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
public enum ServerVersion
{
v_1_8, v_1_8_3, v_1_8_8, v_1_9, v_1_9_4, v_1_10, v_1_11, v_1_12, v_1_13, v_1_13_2, v_1_14, v_1_15,
ERROR;
public static ServerVersion getVersion() {
ServerVersion[] vals = values();
ArrayUtils.reverse(vals);
for(ServerVersion val : vals) {
String valName = val.name().substring(2).replace("_", ".");
if(Bukkit.getBukkitVersion().contains(valName)) {
return val;
}
}
return ERROR;
}
}
@@ -1,6 +0,0 @@
package me.purplex.packetevents.events;
public class PacketEvent {
}
@@ -1,20 +0,0 @@
package me.purplex.packetevents.events.eventmanager;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.PacketReceiveEvent;
import me.purplex.packetevents.events.packetevent.PacketSendEvent;
import java.util.LinkedList;
public interface PacketEventManager {
public LinkedList<PacketListener> packetListeners = new LinkedList<>();
public void callPacketReceiveEvent(PacketReceiveEvent e);
public void callPacketSendEvent(PacketSendEvent e);
public void registerPacketListener(PacketListener e);
public void unregisterPacketListener(PacketListener e);
public void callServerTickEvent(ServerTickEvent e);
}
@@ -1,4 +0,0 @@
package me.purplex.packetevents.events.listener;
public interface PacketListener {
}
@@ -1,77 +0,0 @@
package me.purplex.packetevents.events.manager;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.eventmanager.PacketEventManager;
import me.purplex.packetevents.events.handler.PacketHandler;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.PacketReceiveEvent;
import me.purplex.packetevents.events.packetevent.PacketSendEvent;
import java.lang.reflect.Method;
public class PacketManager implements PacketEventManager {
@Override
public void callPacketReceiveEvent(PacketReceiveEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
@Override
public void callPacketSendEvent(PacketSendEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
@Override
public void registerPacketListener(PacketListener e) {
this.packetListeners.add(e);
}
@Override
public void unregisterPacketListener(PacketListener e) {
this.packetListeners.remove(e);
}
@Override
public void callServerTickEvent(ServerTickEvent e) {
for (PacketListener listener : this.packetListeners) {
Method[] methods = listener.getClass().getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(PacketHandler.class)) {
if (m.getParameterTypes()[0].getSimpleName().equals(e.getClass().getSimpleName())) {
try {
m.invoke(listener, e);
} catch (Exception ex) {
}
}
}
}
}
}
}
@@ -1,19 +0,0 @@
package me.purplex.packetevents.events.packetevent;
import me.purplex.packetevents.events.PacketEvent;
public class ServerTickEvent extends PacketEvent {
private long timestamp;
public ServerTickEvent(long timestamp) {
this.timestamp = timestamp;
}
public long getTimestamp() {
return timestamp;
}
}
@@ -1,99 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_10.WrappedPacketPlayInUseEntity_1_10;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_11.WrappedPacketPlayInUseEntity_1_11;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_12.WrappedPacketPlayInUseEntity_1_12;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_13.WrappedPacketPlayInUseEntity_1_13;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_13_2.WrappedPacketPlayInUseEntity_1_13_2;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_14.WrappedPacketPlayInUseEntity_1_14;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_15.WrappedPacketPlayInUseEntity_1_15;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8.WrappedPacketPlayInUseEntity_1_8;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_3.WrappedPacketPlayInUseEntity_1_8_3;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8.WrappedPacketPlayInUseEntity_1_8_8;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_9.WrappedPacketPlayInUseEntity_1_9;
import me.purplex.packetevents.events.packetevent.packet.impl.in._1_9_4.WrappedPacketPlayInUseEntity_1_9_4;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
if (version == ServerVersion.v_1_8) {
this.entity = new WrappedPacketPlayInUseEntity_1_8(packet).getEntity();
} else if (version == ServerVersion.v_1_8_3) {
this.entity = new WrappedPacketPlayInUseEntity_1_8_3(packet).getEntity();
} else if (version == ServerVersion.v_1_8_8) {
this.entity = new WrappedPacketPlayInUseEntity_1_8_8(packet).getEntity();
} else if (version == ServerVersion.v_1_9) {
this.entity = new WrappedPacketPlayInUseEntity_1_9(packet).getEntity();
} else if (version == ServerVersion.v_1_9_4) {
this.entity = new WrappedPacketPlayInUseEntity_1_9_4(packet).getEntity();
} else if (version == ServerVersion.v_1_10) {
this.entity = new WrappedPacketPlayInUseEntity_1_10(packet).getEntity();
} else if (version == ServerVersion.v_1_11) {
this.entity = new WrappedPacketPlayInUseEntity_1_11(packet).getEntity();
} else if (version == ServerVersion.v_1_12) {
this.entity = new WrappedPacketPlayInUseEntity_1_12(packet).getEntity();
} else if (version == ServerVersion.v_1_13) {
this.entity = new WrappedPacketPlayInUseEntity_1_13(packet).getEntity();
} else if (version == ServerVersion.v_1_13_2) {
this.entity = new WrappedPacketPlayInUseEntity_1_13_2(packet).getEntity();
} else if (version == ServerVersion.v_1_14) {
this.entity = new WrappedPacketPlayInUseEntity_1_14(packet).getEntity();
} else if (version == ServerVersion.v_1_15) {
this.entity = new WrappedPacketPlayInUseEntity_1_15(packet).getEntity();
}
}
private void setupAction() {
if (version == ServerVersion.v_1_8) {
this.action = new WrappedPacketPlayInUseEntity_1_8(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_8_3) {
this.action = new WrappedPacketPlayInUseEntity_1_8_3(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_8_8) {
this.action = new WrappedPacketPlayInUseEntity_1_8_8(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_9) {
this.action = new WrappedPacketPlayInUseEntity_1_9(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_9_4) {
this.action = new WrappedPacketPlayInUseEntity_1_9_4(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_10) {
this.action = new WrappedPacketPlayInUseEntity_1_10(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_11) {
this.action = new WrappedPacketPlayInUseEntity_1_11(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_12) {
this.action = new WrappedPacketPlayInUseEntity_1_12(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_13) {
this.action = new WrappedPacketPlayInUseEntity_1_13(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_13_2) {
this.action = new WrappedPacketPlayInUseEntity_1_13_2(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_14) {
this.action = new WrappedPacketPlayInUseEntity_1_14(packet).getEntityUseAction();
} else if (version == ServerVersion.v_1_15) {
this.action = new WrappedPacketPlayInUseEntity_1_15(packet).getEntityUseAction();
}
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_10;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_10 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_10(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_10_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_10_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_10_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_10_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_10_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_10_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_10_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_10_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_11;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_11 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_11(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_11_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_11_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_11_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_11_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_11_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_11_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_11_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_11_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_12;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_12 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_12(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_12_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_12_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_12_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_12_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_12_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_12_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_12_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_12_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_13;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_13_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_13_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_13 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_13(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_13_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_13_2;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.entity.Entity;
import net.minecraft.server.v1_13_R2.PacketPlayInUseEntity;
import net.minecraft.server.v1_13_R2.WorldServer;
public class WrappedPacketPlayInUseEntity_1_13_2 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_13_2(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (net.minecraft.server.v1_13_R2.PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_13_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_14;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_14_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_14 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_14(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_14_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_14_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_14_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_15;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import net.minecraft.server.v1_15_R1.PacketPlayInUseEntity;
import net.minecraft.server.v1_15_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_15 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_15(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
CraftWorld craftWorld = (CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_15_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
PacketPlayInUseEntity packet = (PacketPlayInUseEntity) getRawPacket();
String name = packet.b().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,57 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_8_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
}
private void setupAction() {
net.minecraft.server.v1_8_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_3;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8_3 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8_3(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_8_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R2.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R2.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R2.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R2.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_8_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R2.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,27 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8;
import java.lang.Object;
public class PacketPlayInAbilities_1_8_8 {
private Object packet;
public PacketPlayInAbilities_1_8_8(Object packet) {
this.packet = packet;
setupFields();
}
private void setupA() {
}
private void setupFields() {
setupA();
}
public boolean a;
public boolean isFlying;
public boolean c;
public boolean d;
public float e;
public float f;
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_8_8;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_8_8 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_8_8(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_8_R3.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R3.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_8_R3.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_8_R3.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_8_R3.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_8_R3.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_8_R3.PacketPlayInUseEntity packet = (net.minecraft.server.v1_8_R3.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,56 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_9;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_9 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_9(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_9_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R1.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_9_R1.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_9_R1.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_9_R1.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_9_R1.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
if (version == ServerVersion.v_1_8) {
net.minecraft.server.v1_9_R1.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R1.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.events.packetevent.packet.impl.in._1_9_4;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
public class WrappedPacketPlayInUseEntity_1_9_4 {
private final ServerVersion version;
private Entity entity;
private EntityUseAction action;
private final Object packet;
public WrappedPacketPlayInUseEntity_1_9_4(Object packet) {
this.version = ServerVersion.getVersion();
this.packet = packet;
setupEntity();
setupAction();
}
private Object getRawPacket() {
return this.packet;
}
public Entity getEntity() {
return entity;
}
public EntityUseAction getEntityUseAction() {
return action;
}
private void setupEntity() {
net.minecraft.server.v1_9_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R2.PacketPlayInUseEntity) getRawPacket();
net.minecraft.server.v1_9_R2.WorldServer worldServer = null;
for (World bukkitWorld : Bukkit.getWorlds()) {
org.bukkit.craftbukkit.v1_9_R2.CraftWorld craftWorld = (org.bukkit.craftbukkit.v1_9_R2.CraftWorld) bukkitWorld;
worldServer = craftWorld.getHandle();
if (packet.a(worldServer) != null) {
break;
}
}
net.minecraft.server.v1_9_R2.Entity entity = packet.a(worldServer);
this.entity = entity.getBukkitEntity();
}
private void setupAction() {
net.minecraft.server.v1_9_R2.PacketPlayInUseEntity packet = (net.minecraft.server.v1_9_R2.PacketPlayInUseEntity) getRawPacket();
String name = packet.a().name();
this.action = EntityUseAction.valueOf(name);
}
}
@@ -1,54 +0,0 @@
package me.purplex.packetevents.example;
import me.purplex.packetevents.enums.EntityUseAction;
import me.purplex.packetevents.enums.ServerVersion;
import me.purplex.packetevents.events.packetevent.ServerTickEvent;
import me.purplex.packetevents.events.handler.PacketHandler;
import me.purplex.packetevents.events.listener.PacketListener;
import me.purplex.packetevents.events.packetevent.*;
import me.purplex.packetevents.events.packetevent.packet.impl.in.WrappedPacketPlayInUseEntity;
import me.purplex.packetevents.packets.Packet;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class TestExample implements PacketListener {
/**
* How to register a packet listener?
* <p>
* PacketEvents.getPacketManager().registerPacketListener(new TestExample());
*/
private int tick;
private static ServerVersion serverVersion = ServerVersion.getVersion();
@PacketHandler
public void onPacketReceive(PacketReceiveEvent e) {
Player p = e.getPlayer();
//ONLY CLIENT PACKETS ALLOWED HERE!
//System.out.println(e.getPacket().getClass().getSimpleName());
if (e.getPacketName().equals(Packet.Client.USE_ENTITY)) {
WrappedPacketPlayInUseEntity packet = new WrappedPacketPlayInUseEntity(e.getPacket());
Entity entity = packet.getEntity();
if (packet.getEntityUseAction() == EntityUseAction.ATTACK) {
double dist = entity.getLocation().distanceSquared(p.getLocation());
//p.sendMessage("dist: " + dist);
}
}
}
@PacketHandler
public void onServerTick(ServerTickEvent e) {
//CALLED EVERY TICK
tick++;
if (tick % 20 == 0) {
/*for (Player p : Bukkit.getOnlinePlayers()) {
p.sendMessage("One second has passed!");
}*/
}
}
}
@@ -1,73 +0,0 @@
package me.purplex.packetevents.packets;
public abstract class Packet {
public static class Client {
private static final String CLIENT = "PacketPlayIn";
public static final String KEEP_ALIVE = CLIENT + "KeepAlive";
@Deprecated
public static final String FLYING = CLIENT + "Flying";
public static final String POSITION = CLIENT + "Position";
public static final String POSITION_LOOK = CLIENT + "PositionLook";
public static final String LOOK = CLIENT + "Look";
@Deprecated
public static final String LEGACY_POSITION = FLYING + "$" + CLIENT + "Position";
@Deprecated
public static final String LEGACY_POSITION_LOOK = FLYING + "$" + CLIENT + "PositionLook";
@Deprecated
public static final String LEGACY_LOOK = FLYING + "$" + CLIENT + "Look";
public static final String TRANSACTION = CLIENT + "Transaction";
public static final String BLOCK_DIG = CLIENT + "BlockDig";
public static final String ENTITY_ACTION = CLIENT + "EntityAction";
public static final String USE_ENTITY = CLIENT + "UseEntity";
public static final String WINDOW_CLICK = CLIENT + "WindowClick";
public static final String STEER_VEHICLE = CLIENT + "SteerVehicle";
public static final String CUSTOM_PAYLOAD = CLIENT + "CustomPayload";
public static final String ARM_ANIMATION = CLIENT + "ArmAnimation";
public static final String BLOCK_PLACE_1_9 = CLIENT + "BlockPlace1_9";
public static final String BLOCK_PLACE = CLIENT + "BlockPlace";
public static final String ABILITIES = CLIENT + "Abilities";
public static final String HELD_ITEM_SLOT = CLIENT + "HeldItemSlot";
public static final String CLOSE_WINDOW = CLIENT + "CloseWindow";
public static final String TAB_COMPLETE = CLIENT + "TabComplete";
public static final String CHAT = CLIENT + "Chat";
public static final String CREATIVE_SLOT = CLIENT + "SetCreativeSlot";
public static final String CLIENT_COMMAND = CLIENT + "ClientCommand";
}
public static class Server {
private static final String SERVER = "PacketPlayOut";
public static final String ANIMATION = SERVER + "Animation";
public static final String KEEP_ALIVE = SERVER + "KeepAlive";
public static final String CHAT = SERVER + "Chat";
public static final String POSITION = SERVER + "Position";
public static final String TRANSACTION = SERVER + "Transaction";
public static final String NAMED_ENTITY_SPAWN = SERVER + "NamedEntitySpawn";
public static final String SPAWN_ENTITY_LIVING = SERVER + "SpawnEntityLiving";
public static final String SPAWN_ENTITY = SERVER + "SpawnEntity";
public static final String CUSTOM_PAYLOAD = SERVER + "CustomPayload";
public static final String ABILITIES = SERVER + "Abilities";
public static final String ENTITY_METADATA = SERVER + "EntityMetadata";
public static final String ENTITY_VELOCITY = SERVER + "EntityVelocity";
public static final String ENTITY_DESTROY = SERVER + "EntityDestroy";
public static final String ENTITY_HEAD_ROTATION = SERVER + "EntityHeadRotation";
public static final String BLOCK_CHANGE = SERVER + "BlockChange";
public static final String CLOSE_WINDOW = SERVER + "CloseWindow";
public static final String HELD_ITEM = SERVER + "HeldItemSlot";
public static final String TAB_COMPLETE = SERVER + "TabComplete";
public static final String RESPAWN = SERVER + "Respawn";
public static final String WORLD_PARTICLE = SERVER + "WorldParticles";
public static final String COMMANDS = SERVER + "Commands";
public static final String OPEN_WINDOW = SERVER + "OpenWindow";
public static final String LOGIN = SERVER + "Login";
public static final String SERVER_DIFFICULTY = SERVER + "ServerDifficulty";
}
public static class Login {
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
public static final String PING = "PacketStatusInPing";
public static final String START = "PacketStatusInStart";
public static final String SUCCESS = "PacketLoginOutSuccess";
}
}
+4 -4
View File
@@ -1,4 +1,4 @@
name: PacketEvents
version: ${project.version}
main: me.purplex.packetevents.Main
authors: [purplex]
name: packetevents
version: 1.2.8
main: io.github.retrooper.packetevents.example.MainExample
author: retrooper