Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66a6c2d8f9 | ||
|
|
b2654e11a3 | ||
|
|
e2cfdda9cf | ||
|
|
b5085a8959 | ||
|
|
dccf01220c | ||
|
|
12dc5b69c0 | ||
|
|
0423b5f335 | ||
|
|
a4c37da10e | ||
|
|
de49279aab | ||
|
|
f651ffddf5 | ||
|
|
ee959b68dc | ||
|
|
b1d1201083 | ||
|
|
faff8fadc8 | ||
|
|
85a0f55b20 | ||
|
|
cf2e571d80 | ||
|
|
68596469eb | ||
|
|
181eda6ae4 | ||
|
|
31ed9c0e4c | ||
|
|
2916fb7112 | ||
|
|
1ca1a960b5 | ||
|
|
6c6a1c9465 | ||
|
|
0be7a21bab | ||
|
|
ca51988694 | ||
|
|
9184d54cb7 | ||
|
|
ca43582e4f | ||
|
|
a1552990bf | ||
|
|
99c9f50dfb | ||
|
|
565e14ecf3 | ||
|
|
521a8e0777 | ||
|
|
0141db4a64 | ||
|
|
9ed9db88b7 | ||
|
|
f52a05b477 | ||
|
|
8936204849 | ||
|
|
50efff2819 | ||
|
|
af325f9a62 | ||
|
|
fe29188e3f | ||
|
|
b753a98971 | ||
|
|
c73d88a7e2 | ||
|
|
bd872bc271 | ||
|
|
c0c03a0629 | ||
|
|
18f3f135c8 | ||
|
|
0304d0ac5a | ||
|
|
643fa1ad18 | ||
|
|
5c65874749 | ||
|
|
5a4db46427 | ||
|
|
305d376128 | ||
|
|
4308936c1a | ||
|
|
87b0ac9295 | ||
|
|
3dee3b2a0e | ||
|
|
c2f0e30511 |
No files matched your search
@@ -2,13 +2,11 @@
|
||||
|
||||
A lightweight spigot packetlistener & packetsender coded by retrooper.
|
||||
|
||||
## Credit:
|
||||
## Credit
|
||||
|
||||
PacketEvents uses a modified version of [TinyProtocol](http://github.com/dmulloy2/ProtocolLib/blob/master/TinyProtocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java) by [@DeprecatedLuke](https://github.com/DeprecatedLuke) to support 1.7.10 & 1.8.
|
||||
I modified DeprecatedLuke's version of TinyProtocol and added support for 1.9+ versions.
|
||||
|
||||
PacketEvents also took Atlas' Packet class.(all the packet names)
|
||||
PacketEvents forked [Atlas](https://github.com/funkemunky/Atlas)' [Packet](https://github.com/funkemunky/Atlas/blob/master/AtlasParent/Atlas/src/main/java/cc/funkemunky/api/tinyprotocol/api/Packet.java) class.
|
||||
|
||||
[Find our forked version](https://github.com/retrooper/packetevents/blob/master/src/main/java/io/github/retrooper/packetevents/packet/PacketType.java)
|
||||
## About
|
||||
|
||||
This packetlistener is **only** supported on spigot servers and has been tested to work on these spigot forks: PaperSpigot, Tuinity
|
||||
@@ -23,6 +21,8 @@ Join my discord server(to talk to me): https://discord.gg/ZWTkg4v
|
||||
|
||||
[](https://jitpack.io/#retrooper/packetevents)
|
||||
|
||||
[](https://jitci.com/gh/retrooper/packetevents)
|
||||
|
||||
To learn how to setup this API please click on the link below
|
||||
[Setup Guide](https://github.com/retrooper/packetevents/wiki/PacketEvents-Setup-Guide)
|
||||
(or just paste this into your browser: https://github.com/retrooper/packetevents/wiki/PacketEvents-Setup-Guide)
|
||||
@@ -6,14 +6,13 @@
|
||||
|
||||
<groupId>io.github.retrooper</groupId>
|
||||
<artifactId>packetevents</artifactId>
|
||||
<version>1.3.3</version>
|
||||
<version>1.4</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>packetevents</name>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<plugins>
|
||||
@@ -56,128 +55,52 @@
|
||||
<id>funkemunky-releases</id>
|
||||
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>viaversion-repo</id>
|
||||
<url>https://repo.viaversion.com</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.14.1</artifactId>
|
||||
<version>1.14.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.15.1</artifactId>
|
||||
<version>1.15.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.14.3</artifactId>
|
||||
<version>1.14.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.14.2</artifactId>
|
||||
<version>1.14.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.15</artifactId>
|
||||
<version>1.15</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.15.2</artifactId>
|
||||
<version>1.15.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.13.2</artifactId>
|
||||
<version>1.13.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.7.10</artifactId>
|
||||
<version>1.7.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.8</artifactId>
|
||||
<version>1.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.8.3</artifactId>
|
||||
<version>1.8.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.8.8</artifactId>
|
||||
<version>1.8.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- ProtocolLib API-->
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.9</artifactId>
|
||||
<version>1.9</version>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.5.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- ViaVersion API-->
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.9.4</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- ProtocolSupport API-->
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.10.2</artifactId>
|
||||
<version>1.10.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.11.1</artifactId>
|
||||
<version>1.11.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.11.2</artifactId>
|
||||
<version>1.11.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.12.1</artifactId>
|
||||
<version>1.12.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.12.2</artifactId>
|
||||
<version>1.12.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.13</artifactId>
|
||||
<version>1.13</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.github.spigot</groupId>
|
||||
<artifactId>1.14</artifactId>
|
||||
<version>1.14</version>
|
||||
<groupId>com.github.ProtocolSupport</groupId>
|
||||
<artifactId>ProtocolSupport</artifactId>
|
||||
<version>4fdd683</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -1,69 +1,63 @@
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.annotations.NotNull;
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.annotations.PacketHandler;
|
||||
import io.github.retrooper.packetevents.enums.ClientVersion;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListener;
|
||||
import io.github.retrooper.packetevents.event.impl.*;
|
||||
import io.github.retrooper.packetevents.event.manager.EventManager;
|
||||
import io.github.retrooper.packetevents.handler.TinyProtocolHandler;
|
||||
import io.github.retrooper.packetevents.packet.Packet;
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.login.WrappedPacketLoginHandshake;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import io.github.retrooper.packetevents.event.impl.BukkitMoveEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.ServerTickEvent;
|
||||
import io.github.retrooper.packetevents.packet.PacketType;
|
||||
import io.github.retrooper.packetevents.packet.PacketTypeClasses;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
|
||||
public final class PacketEvents implements PacketListener, Listener {
|
||||
|
||||
private static final ServerVersion version = ServerVersion.getVersion();
|
||||
private static final EventManager eventManager = new EventManager();
|
||||
private static final HashMap<Object, ClientVersion> clientVersionLookup = new HashMap<Object, ClientVersion>();
|
||||
private static final PacketEventsAPI packetEventsAPI = new PacketEventsAPI();
|
||||
private static final PacketEvents instance = new PacketEvents();
|
||||
private static boolean hasRegistered;
|
||||
private static PacketEvents instance;
|
||||
private static int currentTick;
|
||||
private static BukkitTask serverTickTask;
|
||||
private static boolean kickOnRestart;
|
||||
|
||||
public static EventManager getEventManager() {
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
private static Plugin plugin;
|
||||
private static boolean hasLoaded;
|
||||
|
||||
/**
|
||||
* Starts the server tick task and initiates the TinyProtocolHandler
|
||||
* Call this before start(), this is also very heavy
|
||||
*/
|
||||
public static void load() {
|
||||
PacketTypeClasses.Client.load();
|
||||
PacketTypeClasses.Server.load();
|
||||
hasLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the server tick task and registers what is needed to be registered
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public static void start(final Plugin plugin) {
|
||||
if (!hasLoaded) {
|
||||
load();
|
||||
}
|
||||
if (!hasRegistered) {
|
||||
//Register Bukkit and PacketListener
|
||||
getEventManager().registerListener(getInstance());
|
||||
getAPI().getEventManager().registerListener(getInstance());
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(getInstance(), plugin);
|
||||
//Initialize the TinyProtocolHandler
|
||||
TinyProtocolHandler.initTinyProtocol(plugin);
|
||||
|
||||
//Start the server tick task
|
||||
final Runnable tickRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getEventManager().callEvent(new ServerTickEvent(currentTick++, highlyPreciseMillis()));
|
||||
getAPI().getEventManager().callEvent(new ServerTickEvent(currentTick++, PacketEvents.getAPI().currentMillis()));
|
||||
}
|
||||
};
|
||||
serverTickTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, tickRunnable, 0L, 1L);
|
||||
getAPI().setServerTickTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, tickRunnable, 0L, 1L));
|
||||
hasRegistered = true;
|
||||
PacketEvents.plugin = plugin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,198 +65,31 @@ public final class PacketEvents implements PacketListener, Listener {
|
||||
* Stop all tasks and unregisters all PacketEvents' listeners
|
||||
*/
|
||||
public static void stop() {
|
||||
if (serverTickTask != null) {
|
||||
if (!serverTickTask.isCancelled()) {
|
||||
serverTickTask.cancel();
|
||||
}
|
||||
}
|
||||
getEventManager().unregisterAllListeners();
|
||||
if (shouldKickOnStop()) {
|
||||
for (final Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p != null) {
|
||||
p.kickPlayer("Please wait till the server finishes reloading/restarting.");
|
||||
}
|
||||
}
|
||||
if (getAPI().getServerTickTask() != null) {
|
||||
getAPI().getServerTickTask().cancel();
|
||||
}
|
||||
getAPI().getEventManager().unregisterAllListeners();
|
||||
|
||||
PacketType.Client.packetIds.clear();
|
||||
PacketType.Server.packetIds.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server's version
|
||||
*
|
||||
* @return version
|
||||
*/
|
||||
public static ServerVersion getServerVersion() {
|
||||
return version;
|
||||
public static PacketEventsAPI getAPI() {
|
||||
return packetEventsAPI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server tick task, you may cancel it if you wish.
|
||||
* To cancel it do PacketEvents.getServerTickTask().cancel();
|
||||
* <p>
|
||||
* This bukkit task runs asynchronously every tick and is started in the start(plugin) function
|
||||
*
|
||||
* @return serverTickTask
|
||||
*/
|
||||
public static BukkitTask getServerTickTask() {
|
||||
return serverTickTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the PacketEvents API class
|
||||
*
|
||||
* @return instance
|
||||
*/
|
||||
public static PacketEvents getInstance() {
|
||||
return instance == null ? instance = new PacketEvents() : instance;
|
||||
private static PacketEvents getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the server's recent TPS values
|
||||
* TPS stands for ticks per second.
|
||||
* Learn more about ticks <a href="https://apexminecrafthosting.com/what-is-minecraft-tps/">"https://apexminecrafthosting.com/what-is-minecraft-tps/"</a>
|
||||
*
|
||||
* @return recentTPS[]
|
||||
*/
|
||||
public static double[] getRecentServerTPS() {
|
||||
double[] tpsArray = new double[0];
|
||||
try {
|
||||
tpsArray = NMSUtils.recentTPS();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tpsArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server's current TPS
|
||||
* TPS stands for ticks per second.
|
||||
* Learn more about ticks <a href="https://apexminecrafthosting.com/what-is-minecraft-tps/">"https://apexminecrafthosting.com/what-is-minecraft-tps/"</a>
|
||||
*
|
||||
* @return currentTPS / recentTPS[0]
|
||||
*/
|
||||
public static double getCurrentServerTPS() {
|
||||
return getRecentServerTPS()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's ping.
|
||||
* Learn more about ping <a href="https://en.wikipedia.org/wiki/Ping_(networking_utility)">https://en.wikipedia.org/wiki/Ping_(networking_utility)</a>
|
||||
*
|
||||
* @param player
|
||||
* @return ping
|
||||
*/
|
||||
public static int getPing(@NotNull final Player player) {
|
||||
return NMSUtils.getPlayerPing(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* When to use this(nano / 1 million) over {@link System#currentTimeMillis()}
|
||||
* This is preciser than System.currentTimeMillis(), System.currentTimeMillis() can be up to 50ms off on some operating systems, but using this isn't cheap.
|
||||
* Java documentation recommend using nano time if you are measuring elapsed time.
|
||||
* In this function nanoTime is divided by 1 million giving us milliseconds.
|
||||
* It is also important to mention that using this method doesn't guarantee thread safety.
|
||||
* @return nanoTime / 1 million
|
||||
*/
|
||||
public static long highlyPreciseMillis() {
|
||||
return System.nanoTime() / 1000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is deprecated, use {@link #highlyPreciseMillis()} as they do the same thing, this is basically just a method rename.
|
||||
*/
|
||||
public static long currentCalculatedMS() {
|
||||
return System.nanoTime() / 1000000;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the player's version.
|
||||
* Do not call this method in the PlayerInjectEvent, it is safe to call it in the PostPlayerInjectEvent.
|
||||
* The EntityPlayer object is null at that time, resulting in the version lookup to fail.
|
||||
*
|
||||
* @param player
|
||||
* @return ClientVersion
|
||||
*/
|
||||
@Nullable
|
||||
public static ClientVersion getClientVersion(@NotNull final Player player) {
|
||||
final Object channel = TinyProtocolHandler.getPlayerChannel(player);
|
||||
return clientVersionLookup.get(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the players' client version
|
||||
* Do not call this method in the PlayerInjectEvent, it is safe to call it in the PostPlayerInjectEvent.
|
||||
* The EntityPlayer object is null at that time, resulting in the version lookup to fail.
|
||||
*
|
||||
* @param channel
|
||||
* @return ClientVersion
|
||||
*/
|
||||
@Nullable
|
||||
public static ClientVersion getClientVersion(@NotNull final Object channel) {
|
||||
return clientVersionLookup.get(channel);
|
||||
}
|
||||
|
||||
public static boolean shouldKickOnStop() {
|
||||
return kickOnRestart;
|
||||
}
|
||||
|
||||
public static void setShouldKickOnRestart(final boolean val) {
|
||||
kickOnRestart = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version independent player injection
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public static void injectPlayer(final Player player) {
|
||||
TinyProtocolHandler.inject(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version independant player injection
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public static void uninjectPlayer(final Player player) {
|
||||
TinyProtocolHandler.uninject(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we have injected the player
|
||||
*
|
||||
* @param player
|
||||
* @return hasInjected
|
||||
*/
|
||||
public static boolean hasInjected(final Player player) {
|
||||
return TinyProtocolHandler.hasInjected(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a wrapped sendable packet to a player
|
||||
*
|
||||
* @param player
|
||||
* @param sendable
|
||||
*/
|
||||
public static void sendPacket(final Player player, final Sendable sendable) {
|
||||
NMSUtils.sendSendableWrapper(player, sendable);
|
||||
}
|
||||
|
||||
@PacketHandler
|
||||
public void onLogin(final PacketLoginEvent e) {
|
||||
if (e.getPacketName().equals(Packet.Login.HANDSHAKE)) {
|
||||
final WrappedPacketLoginHandshake handshake = new WrappedPacketLoginHandshake(e.getPacket());
|
||||
final ClientVersion clientVersion = ClientVersion.fromProtocolVersion(handshake.getProtocolVersion());
|
||||
clientVersionLookup.put(e.getNettyChannel(), clientVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@PacketHandler
|
||||
public void onPacket(final PacketEvent e) {
|
||||
if (e instanceof PacketReceiveEvent) {
|
||||
// System.out.println("RECEIVED");
|
||||
}
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,24 +101,25 @@ public final class PacketEvents implements PacketListener, Listener {
|
||||
*/
|
||||
@PacketHandler
|
||||
public void onInject(final PlayerInjectEvent e) {
|
||||
final String username = e.getPlayer().getName();
|
||||
getAPI().getPlayerUtilities().clientVersionsMap.put(e.getPlayer().getUniqueId(), e.getClientVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the PlayerJoinEvent ONLY if the player has been injected!
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@PacketHandler
|
||||
public void onPostInject(final PostPlayerInjectEvent e) {
|
||||
//It is safe to get his client version in here.
|
||||
final ClientVersion clientVersion = PacketEvents.getClientVersion(e.getPlayer());
|
||||
public void onReceive(final PacketReceiveEvent e) {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (hasInjected(e.getPlayer())) {
|
||||
PacketEvents.getEventManager().callEvent(new PostPlayerInjectEvent(e.getPlayer()));
|
||||
}
|
||||
public void onJoin(final PlayerJoinEvent e) {
|
||||
getAPI().getPlayerUtilities().injectPlayer(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(final PlayerQuitEvent e) {
|
||||
getAPI().getPlayerUtilities().uninjectPlayer(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onMove(final PlayerMoveEvent e) {
|
||||
getAPI().getEventManager().callEvent(new BukkitMoveEvent(e));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.event.manager.EventManager;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public final class PacketEventsAPI {
|
||||
private final EventManager eventManager = new EventManager();
|
||||
private final PlayerUtils playerUtils = new PlayerUtils();
|
||||
private final ServerUtils serverUtils = new ServerUtils();
|
||||
|
||||
private BukkitTask serverTickTask;
|
||||
|
||||
/**
|
||||
* Not thread safe
|
||||
* Preciser than #currentMillis()
|
||||
* Expensive
|
||||
* Returns crazy values when you change system time
|
||||
*
|
||||
* @return {@link System#nanoTime()} / 1000000(1 million)
|
||||
*/
|
||||
public long currentPreciseMillis() {
|
||||
return System.nanoTime() / 1000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread safe
|
||||
* Less precise compared to #currentPreciseMillis()
|
||||
* Cheap
|
||||
* Doesn't break when system time is changed
|
||||
*
|
||||
* @return {@link System#currentTimeMillis()}
|
||||
*/
|
||||
public long currentMillis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all utilities to do with the player
|
||||
*
|
||||
* @return Player Utilities
|
||||
*/
|
||||
public PlayerUtils getPlayerUtilities() {
|
||||
return playerUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all utilities to do with the server
|
||||
*
|
||||
* @return Server Utilities
|
||||
*/
|
||||
public ServerUtils getServerUtilities() {
|
||||
return serverUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event manager
|
||||
* Used to call events, register and unregister listeners
|
||||
*
|
||||
* @return PacketEvents' event manager
|
||||
*/
|
||||
public EventManager getEventManager() {
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server tick task, called **asynchronously** every tick
|
||||
*
|
||||
* @return server tick task
|
||||
*/
|
||||
public BukkitTask getServerTickTask() {
|
||||
return serverTickTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the server tick task object
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
public void setServerTickTask(final BukkitTask task) {
|
||||
this.serverTickTask = task;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.enums.ClientVersion;
|
||||
import io.github.retrooper.packetevents.handler.NettyPacketHandler;
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerUtils {
|
||||
protected final HashMap<UUID, ClientVersion> clientVersionsMap = new HashMap<UUID, ClientVersion>();
|
||||
|
||||
public int getPlayerPing(final Player player) {
|
||||
return NMSUtils.getPlayerPing(player);
|
||||
}
|
||||
|
||||
public ClientVersion getClientVersion(final UUID uuid) {
|
||||
return clientVersionsMap.get(uuid);
|
||||
}
|
||||
|
||||
public ClientVersion getClientVersion(final Player player) {
|
||||
return getClientVersion(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void injectPlayer(final Player player) {
|
||||
NettyPacketHandler.injectPlayer(player);
|
||||
}
|
||||
|
||||
public void uninjectPlayer(final Player player) {
|
||||
NettyPacketHandler.uninjectPlayer(player);
|
||||
}
|
||||
|
||||
public void sendPacket(final Player player, final Sendable sendable) {
|
||||
NMSUtils.sendSendableWrapper(player, sendable);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.github.retrooper.packetevents;
|
||||
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.enums.SystemOS;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class ServerUtils {
|
||||
public ServerVersion getServerVersion() {
|
||||
return ServerVersion.getVersion();
|
||||
}
|
||||
|
||||
public double[] getRecentServerTPS() {
|
||||
double[] tpsArray = new double[0];
|
||||
try {
|
||||
tpsArray = NMSUtils.recentTPS();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tpsArray;
|
||||
}
|
||||
|
||||
public double getCurrentServerTPS() {
|
||||
return getRecentServerTPS()[0];
|
||||
}
|
||||
|
||||
public SystemOS getPlatform() {
|
||||
return SystemOS.getOperatingSystem();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.github.retrooper.packetevents.annotations;
|
||||
|
||||
import io.github.retrooper.packetevents.annotations.data.EventSynchronization;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -8,10 +10,9 @@ 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!
|
||||
* Just like Bukkit's @EventHandler, but for PacketEvents' custom event system.
|
||||
* Make sure your class implements the PacketListener interface, and is registered when annotating your method with this annotation!
|
||||
*/
|
||||
public @interface PacketHandler {
|
||||
|
||||
|
||||
EventSynchronization synchronization() default EventSynchronization.NORMAL;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package io.github.retrooper.packetevents.annotations.data;
|
||||
|
||||
public enum EventSynchronization {
|
||||
FORCE_SYNC, FORCE_ASYNC, NORMAL
|
||||
}
|
||||
@@ -2,11 +2,13 @@ package io.github.retrooper.packetevents.enums;
|
||||
|
||||
public enum ClientVersion {
|
||||
LESS_THAN_V_1_7_10, v_1_7_10, v_1_8, v_1_9, v_1_9_1, v_1_9_2, v_1_9_3, v_1_10, v_1_11, v_1_11_1, v_1_12, v_1_12_1, v_1_12_2,
|
||||
v_1_13, v_1_13_1, v_1_13_2, v_1_14, v_1_14_1, v_1_14_2, v_1_14_3, v_1_14_4, v_1_15, v_1_15_1, v_1_15_2, HIGHER_THAN_V_1_15_2, INVALID;
|
||||
v_1_13, v_1_13_1, v_1_13_2, v_1_14, v_1_14_1, v_1_14_2, v_1_14_3, v_1_14_4, v_1_15, v_1_15_1, v_1_15_2, v_1_16, v_1_16_1, HIGHER_THAN_V_1_16_1, INVALID, ACCESS_FAILURE;
|
||||
|
||||
public static ClientVersion fromProtocolVersion(final int protocolVersion) {
|
||||
int remainder = -1;
|
||||
switch (protocolVersion) {
|
||||
case -1:
|
||||
return ACCESS_FAILURE;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
@@ -56,11 +58,15 @@ public enum ClientVersion {
|
||||
return v_1_15_1;
|
||||
case 578:
|
||||
return v_1_15_2;
|
||||
case 735:
|
||||
return v_1_16;
|
||||
case 736:
|
||||
return v_1_16_1;
|
||||
default:
|
||||
remainder = protocolVersion;
|
||||
}
|
||||
if (remainder > 578) {
|
||||
return HIGHER_THAN_V_1_15_2;
|
||||
return HIGHER_THAN_V_1_16_1;
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
@@ -84,7 +90,7 @@ public enum ClientVersion {
|
||||
*/
|
||||
public boolean isLowerThan(final ClientVersion version) {
|
||||
if (version == this) return false;
|
||||
byte len = (byte) values().length;
|
||||
final int len = values().length;
|
||||
for (byte i = 0; i < len; i++) {
|
||||
final ClientVersion v = values()[i];
|
||||
if (v == this) {
|
||||
|
||||
@@ -9,7 +9,7 @@ public enum Direction {
|
||||
SOUTH_SOUTH_EAST, SOUTH_SOUTH_WEST,
|
||||
WEST_SOUTH_WEST, SELF, NULL;
|
||||
|
||||
public static Direction get(final byte i) {
|
||||
public static Direction get(final int i) {
|
||||
return values()[i];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
|
||||
public enum Hand {
|
||||
MAIN_HAND,
|
||||
OFF_HAND
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
|
||||
public enum PlayerAction {
|
||||
START_SNEAKING,
|
||||
|
||||
STOP_SNEAKING,
|
||||
|
||||
STOP_SLEEPING,
|
||||
|
||||
START_SPRINTING,
|
||||
|
||||
STOP_SPRINTING,
|
||||
|
||||
START_RIDING_JUMP,
|
||||
|
||||
STOP_RIDING_JUMP,
|
||||
|
||||
OPEN_INVENTORY,
|
||||
|
||||
START_FALL_FLYING;
|
||||
|
||||
public static PlayerAction get(final byte i) {
|
||||
return values()[i];
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,24 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
|
||||
/**
|
||||
* @author retrooper
|
||||
*/
|
||||
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;
|
||||
|
||||
v_1_7_10, v_1_8, v_1_8_3, v_1_8_8, v_1_9, v_1_9_4, v_1_10, v_1_11, v_1_12, v_1_13, v_1_13_2, v_1_14, v_1_15, v_1_16_1,
|
||||
ERROR, EMPTY;
|
||||
|
||||
private static final ServerVersion[] reversedValues;
|
||||
private static final String nmsVersionSuffix = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
|
||||
private static ServerVersion cachedVersion;
|
||||
|
||||
public static ServerVersion getVersion() {
|
||||
ServerVersion[] vals = values();
|
||||
ArrayUtils.reverse(vals);
|
||||
for (ServerVersion val : vals) {
|
||||
static {
|
||||
reversedValues = reverse(values());
|
||||
}
|
||||
|
||||
private static ServerVersion getVers() {
|
||||
for (final ServerVersion val : reversedValues) {
|
||||
String valName = val.name().substring(2).replace("_", ".");
|
||||
if (Bukkit.getBukkitVersion().contains(valName)) {
|
||||
return val;
|
||||
@@ -23,6 +27,31 @@ public enum ServerVersion {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
public static ServerVersion getVersion() {
|
||||
if (cachedVersion == null) {
|
||||
cachedVersion = getVers();
|
||||
}
|
||||
return cachedVersion;
|
||||
}
|
||||
|
||||
private static ServerVersion[] reverse(final ServerVersion[] arr) {
|
||||
ServerVersion[] array = arr.clone();
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
int i = 0;
|
||||
int j = array.length - 1;
|
||||
ServerVersion tmp;
|
||||
while (j > i) {
|
||||
tmp = array[j];
|
||||
array[j] = array[i];
|
||||
array[i] = tmp;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static String getNmsSuffix() {
|
||||
return nmsVersionSuffix;
|
||||
}
|
||||
@@ -54,7 +83,7 @@ public enum ServerVersion {
|
||||
*/
|
||||
public boolean isLowerThan(final ServerVersion version) {
|
||||
if (version == this) return false;
|
||||
byte len = (byte) values().length;
|
||||
final int len = values().length;
|
||||
for (byte i = 0; i < len; i++) {
|
||||
final ServerVersion v = values()[i];
|
||||
if (v == this) {
|
||||
@@ -67,4 +96,3 @@ public enum ServerVersion {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
|
||||
public enum SystemOS {
|
||||
WINDOWS, MACOS, LINUX, OTHER;
|
||||
|
||||
private static SystemOS value;
|
||||
|
||||
private static SystemOS getOS() {
|
||||
final String os = System.getProperty("os.name");
|
||||
for (final String osName : getOperatingSystemNames()) {
|
||||
if (os.toLowerCase().contains(osName.toLowerCase())) {
|
||||
return SystemOS.valueOf(osName);
|
||||
}
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
public static SystemOS getOperatingSystem() {
|
||||
if (value == null) {
|
||||
value = getOS();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String[] getOperatingSystemNames() {
|
||||
final String[] arr = new String[values().length - 1];
|
||||
for (int i = 0; i < values().length - 1; i++) {
|
||||
arr[i] = values()[i].name();
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
package io.github.retrooper.packetevents.enums.minecraft;
|
||||
|
||||
public enum EntityAnimationType {
|
||||
SWING_MAIN_ARM, DAMAGE, LEAVE_BED, SWING_OFFHAND, CRITICAL_EFFECT, MAGIC_CRITICAL_EFFECT;
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
package io.github.retrooper.packetevents.enums.minecraft;
|
||||
|
||||
public enum EntityUseAction {
|
||||
INTERACT, INTERACT_AT, ATTACK, INVALID;
|
||||
|
||||
public static EntityUseAction get(final byte i) {
|
||||
public static EntityUseAction get(final int i) {
|
||||
return values()[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package io.github.retrooper.packetevents.enums.minecraft;
|
||||
|
||||
public enum Hand {
|
||||
MAIN_HAND,
|
||||
OFF_HAND
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package io.github.retrooper.packetevents.enums.minecraft;
|
||||
|
||||
public enum PlayerAction {
|
||||
START_SNEAKING,
|
||||
|
||||
STOP_SNEAKING,
|
||||
|
||||
STOP_SLEEPING,
|
||||
|
||||
START_SPRINTING,
|
||||
|
||||
STOP_SPRINTING,
|
||||
|
||||
START_RIDING_JUMP,
|
||||
|
||||
STOP_RIDING_JUMP,
|
||||
|
||||
OPEN_INVENTORY,
|
||||
|
||||
START_FALL_FLYING;
|
||||
|
||||
public static PlayerAction get(final int i) {
|
||||
return values()[i];
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
for (int i = 0; i < values().length; i++) {
|
||||
final PlayerAction action = values()[i];
|
||||
if (action == this) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public enum UpdatedPlayerAction {
|
||||
PRESS_SHIFT_KEY, RELEASE_SHIFT_KEY, STOP_SLEEPING, START_SPRINTING, STOP_SPRINTING, START_RIDING_JUMP, STOP_RIDING_JUMP, OPEN_INVENTORY, START_FALL_FLYING;
|
||||
|
||||
public static UpdatedPlayerAction get(final int index) {
|
||||
for (int i = 0; i < index + 1; i++) {
|
||||
final UpdatedPlayerAction action = values()[i];
|
||||
if (i == index) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
for (int i = 0; i < values().length; i++) {
|
||||
final UpdatedPlayerAction action = values()[i];
|
||||
if (action == this) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,4 +1,4 @@
|
||||
package io.github.retrooper.packetevents.enums;
|
||||
package io.github.retrooper.packetevents.enums.minecraft;
|
||||
|
||||
public enum PlayerDigType {
|
||||
|
||||
@@ -16,9 +16,11 @@ public enum PlayerDigType {
|
||||
|
||||
SWAP_HELD_ITEMS,
|
||||
|
||||
SWAP_ITEM_WITH_OFFHAND,
|
||||
|
||||
WRONG_PACKET;
|
||||
|
||||
public static PlayerDigType get(final byte i) {
|
||||
public static PlayerDigType get(final int i) {
|
||||
return values()[i];
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,9 @@ 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 static ServerVersion version = PacketEvents.getServerVersion();
|
||||
protected long timestamp = PacketEvents.currentCalculatedMS();
|
||||
protected static ServerVersion version = PacketEvents.getAPI().getServerUtilities().getServerVersion();
|
||||
private long timestamp = PacketEvents.getAPI().currentMillis();
|
||||
|
||||
/**
|
||||
* Timestamp of the packet
|
||||
@@ -20,4 +16,8 @@ public class PacketEvent {
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public final class BukkitMoveEvent extends PacketEvent {
|
||||
private final Player player;
|
||||
private final Location to, from;
|
||||
|
||||
public BukkitMoveEvent(final Player player, final Location to, final Location from) {
|
||||
this.player = player;
|
||||
this.to = to;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public BukkitMoveEvent(final PlayerMoveEvent e) {
|
||||
this.player = e.getPlayer();
|
||||
this.to = e.getTo();
|
||||
this.from = e.getFrom();
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Location getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public Location getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
|
||||
public final class PacketLoginEvent extends PacketEvent {
|
||||
private final Object channel;
|
||||
private final String name;
|
||||
private final Object packet;
|
||||
|
||||
public PacketLoginEvent(final Object channel, final String packetName, final Object packet) {
|
||||
this.channel = channel;
|
||||
this.name = packetName;
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public Object getNettyChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public String getPacketName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Object getPacket() {
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.packet.PacketType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class PacketReceiveEvent extends PacketEvent {
|
||||
@@ -34,14 +35,36 @@ public final class PacketReceiveEvent extends PacketEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw packet object
|
||||
* Get the NMS packet object
|
||||
*
|
||||
* @return packet
|
||||
* @return packet object
|
||||
*/
|
||||
public Object getPacket() {
|
||||
public Object getNMSPacket() {
|
||||
return this.packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class of the NMS packet object
|
||||
*
|
||||
* @return packet object class
|
||||
*/
|
||||
public Class<?> getNMSPacketClass() {
|
||||
return getNMSPacket().getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the packet
|
||||
*
|
||||
* @return packet id
|
||||
*/
|
||||
public int getPacketId() {
|
||||
Integer id = PacketType.Client.packetIds.get(getNMSPacketClass());
|
||||
if (id == null) {
|
||||
return -1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the packet has been cancelled
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.packet.PacketType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
@@ -27,14 +28,37 @@ public final class PacketSendEvent extends PacketEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw packet object
|
||||
* Get the ID of the packet
|
||||
*
|
||||
* @return nmsPacket
|
||||
* @return packet id
|
||||
*/
|
||||
public Object getPacket() {
|
||||
public int getPacketId() {
|
||||
Integer id =
|
||||
PacketType.Server.packetIds.get(getNMSPacketClass());
|
||||
if (id == null) {
|
||||
return -1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NMS packet object
|
||||
*
|
||||
* @return packet object
|
||||
*/
|
||||
public Object getNMSPacket() {
|
||||
return this.packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class of the NMS packet object
|
||||
*
|
||||
* @return packet object class
|
||||
*/
|
||||
public Class<?> getNMSPacketClass() {
|
||||
return getNMSPacket().getClass();
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.enums.ClientVersion;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.utils.api.VersionLookupUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class PlayerInjectEvent extends PacketEvent {
|
||||
private final Player player;
|
||||
private final ClientVersion clientVersion;
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerInjectEvent(final Player player) {
|
||||
this.player = player;
|
||||
this.clientVersion = ClientVersion.fromProtocolVersion(VersionLookupUtils.getProtocolVersion(player));
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
@@ -23,6 +27,10 @@ public final class PlayerInjectEvent extends PacketEvent {
|
||||
setCancelled(true);
|
||||
}
|
||||
|
||||
public ClientVersion getClientVersion() {
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,24 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public final class PlayerUninjectEvent extends PacketEvent {
|
||||
private final Player player;
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerUninjectEvent(final Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
setCancelled(true);
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
public void setCancelled(final boolean val) {
|
||||
this.cancelled = val;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.github.retrooper.packetevents.event.impl;
|
||||
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class PostPlayerInjectEvent extends PacketEvent {
|
||||
private final Player player;
|
||||
|
||||
public PostPlayerInjectEvent(final Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,16 @@ public final class ServerTickEvent extends PacketEvent {
|
||||
|
||||
public ServerTickEvent(final int tick, final long timestamp) {
|
||||
this.tick = tick;
|
||||
this.timestamp = timestamp;
|
||||
this.tps = PacketEvents.getCurrentServerTPS();
|
||||
setTimestamp(timestamp);
|
||||
this.tps = PacketEvents.getAPI().getServerUtilities().getCurrentServerTPS();
|
||||
}
|
||||
|
||||
public ServerTickEvent(final int tick) {
|
||||
this.tick = tick;
|
||||
this.tps = PacketEvents.getCurrentServerTPS();
|
||||
this.tps = PacketEvents.getAPI().getServerUtilities().getCurrentServerTPS();
|
||||
}
|
||||
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public int getCurrentTick() {
|
||||
return tick;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package io.github.retrooper.packetevents.event.manager;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.annotations.PacketHandler;
|
||||
import io.github.retrooper.packetevents.annotations.data.EventSynchronization;
|
||||
import io.github.retrooper.packetevents.event.PacketEvent;
|
||||
import io.github.retrooper.packetevents.event.PacketListener;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -13,11 +16,19 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public final class EventManager {
|
||||
|
||||
private static final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
private final ExecutorService executorService;
|
||||
private final HashMap<PacketListener, List<Method>> registeredMethods = new HashMap<PacketListener, List<Method>>();
|
||||
|
||||
public EventManager(final int threadCount) {
|
||||
executorService = Executors.newFixedThreadPool(threadCount);
|
||||
}
|
||||
|
||||
public EventManager() {
|
||||
this(Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
public void callEvent(final PacketEvent e) {
|
||||
Integer i = 0;
|
||||
for (final PacketListener listener : registeredMethods.keySet()) {
|
||||
//Annotated methods
|
||||
final List<Method> methods = registeredMethods.get(listener);
|
||||
@@ -25,10 +36,23 @@ public final class EventManager {
|
||||
final Class<?> parameterType = method.getParameterTypes()[0];
|
||||
if (parameterType.equals(PacketEvent.class)
|
||||
|| parameterType.isInstance(e)) {
|
||||
try {
|
||||
method.invoke(listener, e);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
ex.printStackTrace();
|
||||
final PacketHandler annotation = method.getAnnotation(PacketHandler.class);
|
||||
final Runnable invokeMethod = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
method.invoke(listener, e);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (annotation.synchronization() == EventSynchronization.FORCE_ASYNC) {
|
||||
executorService.execute(invokeMethod);
|
||||
} else if (annotation.synchronization() == EventSynchronization.FORCE_SYNC) {
|
||||
Bukkit.getScheduler().runTask(PacketEvents.getPlugin(), invokeMethod);
|
||||
} else {
|
||||
invokeMethod.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,9 +60,6 @@ public final class EventManager {
|
||||
}
|
||||
|
||||
public void registerListener(final PacketListener e) {
|
||||
if (registeredMethods.containsKey(e)) {
|
||||
return;
|
||||
}
|
||||
final List<Method> methods = new ArrayList<Method>();
|
||||
for (final Method m : e.getClass().getMethods()) {
|
||||
if (m.isAnnotationPresent(PacketHandler.class)
|
||||
|
||||
@@ -3,20 +3,23 @@ package io.github.retrooper.packetevents.example;
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import static io.github.retrooper.packetevents.PacketEvents.getAPI;
|
||||
|
||||
public class MainExample extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
PacketEvents.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
PacketEvents.start(this);
|
||||
|
||||
PacketEvents.getServerTickTask().cancel();
|
||||
|
||||
//To fix bugs it is recommend to set this to TRUE
|
||||
PacketEvents.setShouldKickOnRestart(true);
|
||||
getAPI().getServerTickTask().cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
PacketEvents.stop(); //it kicks when you call the stop() function
|
||||
PacketEvents.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
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.event.impl.PlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerUninjectEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class NettyPacketHandler {
|
||||
public static final String handlerName = "packet_handler";
|
||||
private static boolean v1_7_nettyMode = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("io.netty.channel.Channel");
|
||||
} catch (ClassNotFoundException e) {
|
||||
v1_7_nettyMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectPlayer(final Player player) {
|
||||
final PlayerInjectEvent injectEvent = new PlayerInjectEvent(player);
|
||||
PacketEvents.getAPI().getEventManager().callEvent(injectEvent);
|
||||
if (!injectEvent.isCancelled()) {
|
||||
if (v1_7_nettyMode) {
|
||||
NettyPacketHandler_7.injectPlayer(player);
|
||||
} else {
|
||||
NettyPacketHandler_8.injectPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Future<?> uninjectPlayer(final Player player) {
|
||||
final PlayerUninjectEvent uninjectEvent = new PlayerUninjectEvent(player);
|
||||
PacketEvents.getAPI().getEventManager().callEvent(uninjectEvent);
|
||||
if (!uninjectEvent.isCancelled()) {
|
||||
if (v1_7_nettyMode) {
|
||||
return NettyPacketHandler_7.uninjectPlayer(player);
|
||||
} else {
|
||||
return NettyPacketHandler_8.uninjectPlayer(player);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object write(final Player sender, final Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
final PacketSendEvent packetSendEvent = new PacketSendEvent(sender, packetName, packet);
|
||||
PacketEvents.getAPI().getEventManager().callEvent(packetSendEvent);
|
||||
if (!packetSendEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object read(final Player receiver, final Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(receiver, packetName, packet);
|
||||
PacketEvents.getAPI().getEventManager().callEvent(packetReceiveEvent);
|
||||
if (!packetReceiveEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import net.minecraft.util.io.netty.channel.*;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
final class NettyPacketHandler_7 {
|
||||
|
||||
public static void injectPlayer(final Player player) {
|
||||
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Object packet = NettyPacketHandler.read(player, msg);
|
||||
if (packet == null) {
|
||||
return;
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
Object packet = NettyPacketHandler.write(player, msg);
|
||||
if (packet == null) {
|
||||
return;
|
||||
}
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
};
|
||||
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
|
||||
pipeline.addBefore(NettyPacketHandler.handlerName, player.getName(), channelDuplexHandler);
|
||||
}
|
||||
|
||||
public static Future<?> uninjectPlayer(final Player player) {
|
||||
final Channel channel = (Channel) NMSUtils.getChannel(player);
|
||||
return channel.eventLoop().submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(player.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import io.netty.channel.*;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
final class NettyPacketHandler_8 {
|
||||
private static final ServerVersion version = PacketEvents.getAPI().getServerUtilities().getServerVersion();
|
||||
|
||||
public static void injectPlayer(final Player player) {
|
||||
final ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Object packet = NettyPacketHandler.read(player, msg);
|
||||
if (packet == null) {
|
||||
return;
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
Object packet = NettyPacketHandler.write(player, msg);
|
||||
if (packet == null) {
|
||||
return;
|
||||
}
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
};
|
||||
final ChannelPipeline pipeline = ((Channel) NMSUtils.getChannel(player)).pipeline();
|
||||
pipeline.addBefore(NettyPacketHandler.handlerName, player.getName(), channelDuplexHandler);
|
||||
}
|
||||
|
||||
public static Future<?> uninjectPlayer(final Player player) {
|
||||
final Channel channel = (Channel) NMSUtils.getChannel(player);
|
||||
return channel.eventLoop().submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(player.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public final class TinyProtocolHandler {
|
||||
private static final ServerVersion version = PacketEvents.getServerVersion();
|
||||
private static final FieldAccessor<?> playerConnectionAccessor, networkManagerAccessor, nettyChannelAccessor;
|
||||
private static Object tinyProtocol;
|
||||
private static Class<?> networkManagerClass;
|
||||
private static Class<?> channelClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
networkManagerClass = NMSUtils.getNMSClass("NetworkManager");
|
||||
channelClass = NMSUtils.getNettyClass("channel.Channel");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
playerConnectionAccessor = Reflection.getField(NMSUtils.entityPlayerClass, NMSUtils.playerConnectionClass, 0);
|
||||
networkManagerAccessor = Reflection.getField(NMSUtils.playerConnectionClass, networkManagerClass, 0);
|
||||
nettyChannelAccessor = Reflection.getField(networkManagerClass, channelClass, 0);
|
||||
}
|
||||
|
||||
public static void initTinyProtocol(final Plugin plugin) {
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
TinyProtocolHandler_1_7 tiny = new TinyProtocolHandler_1_7(plugin);
|
||||
tiny.initTinyProtocol();
|
||||
tinyProtocol = tiny;
|
||||
} else {
|
||||
TinyProtocolHandler_1_8 tiny = new TinyProtocolHandler_1_8(plugin);
|
||||
tiny.initTinyProtocol();
|
||||
tinyProtocol = tiny;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasInjected(final Player player) {
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
return tiny.tinyProtocol.hasInjected(player);
|
||||
} else {
|
||||
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
return tiny.tinyProtocol.hasInjected(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inject(final Player player) {
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
tiny.tinyProtocol.injectPlayer(player);
|
||||
} else {
|
||||
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
tiny.tinyProtocol.injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static void uninject(final Player player) {
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
TinyProtocolHandler_1_7 tiny = (TinyProtocolHandler_1_7) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
tiny.tinyProtocol.uninjectPlayer(player);
|
||||
} else {
|
||||
TinyProtocolHandler_1_8 tiny = (TinyProtocolHandler_1_8) tinyProtocol;
|
||||
assert tiny.tinyProtocol != null;
|
||||
tiny.tinyProtocol.uninjectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getPlayerChannel(final Player player) {
|
||||
final Object entityPlayer = NMSUtils.getEntityPlayer(player);
|
||||
final Object playerConnection = playerConnectionAccessor.get(entityPlayer);
|
||||
final Object networkManager = networkManagerAccessor.get(playerConnection);
|
||||
return nettyChannelAccessor.get(networkManager);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketLoginEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
|
||||
import io.github.retrooper.packetevents.packet.Packet;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.TinyProtocol7;
|
||||
import net.minecraft.util.io.netty.channel.Channel;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public final class TinyProtocolHandler_1_7 {
|
||||
private final Plugin plugin;
|
||||
@Nullable
|
||||
public TinyProtocol7 tinyProtocol;
|
||||
|
||||
public TinyProtocolHandler_1_7(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void initTinyProtocol() {
|
||||
tinyProtocol = new TinyProtocol7(getPlugin()) {
|
||||
@Override
|
||||
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
|
||||
PacketEvents.getEventManager().callEvent(packetSendEvent);
|
||||
if (!packetSendEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
for (final String loginPacket : Packet.Login.LOGIN_PACKETS) {
|
||||
if (packetName.equals(loginPacket)) {
|
||||
PacketEvents.getEventManager().callEvent(new PacketLoginEvent(channel, packetName, packet));
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
|
||||
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
|
||||
if (!packetReceiveEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package io.github.retrooper.packetevents.handler;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketLoginEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketReceiveEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
|
||||
import io.github.retrooper.packetevents.packet.Packet;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.TinyProtocol8;
|
||||
import io.netty.channel.Channel;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public final class TinyProtocolHandler_1_8 {
|
||||
private static final ServerVersion version = PacketEvents.getServerVersion();
|
||||
private final Plugin plugin;
|
||||
@Nullable
|
||||
public TinyProtocol8 tinyProtocol;
|
||||
|
||||
|
||||
public TinyProtocolHandler_1_8(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
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 void initTinyProtocol() {
|
||||
tinyProtocol = new TinyProtocol8(getPlugin()) {
|
||||
@Override
|
||||
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
|
||||
PacketEvents.getEventManager().callEvent(packetSendEvent);
|
||||
if (!packetSendEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
for (final String loginPacket : Packet.Login.LOGIN_PACKETS) {
|
||||
if (packetName.equals(loginPacket)) {
|
||||
PacketEvents.getEventManager().callEvent(new PacketLoginEvent(channel, packetName, packet));
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
final PacketReceiveEvent packetReceiveEvent = new PacketReceiveEvent(sender, packetName, packet);
|
||||
PacketEvents.getEventManager().callEvent(packetReceiveEvent);
|
||||
if (!packetReceiveEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package io.github.retrooper.packetevents.mojang;
|
||||
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.StringUtils;
|
||||
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameProfile {
|
||||
private final UUID id;
|
||||
private final String name;
|
||||
private final PropertyMap properties = new PropertyMap();
|
||||
private boolean legacy;
|
||||
|
||||
public GameProfile(UUID id, String name) {
|
||||
if (id == null && StringUtils.isBlank(name)) {
|
||||
throw new IllegalArgumentException("Name and ID cannot both be blank");
|
||||
} else {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public PropertyMap getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return this.id != null && StringUtils.isNotBlank(this.getName());
|
||||
}
|
||||
|
||||
public boolean equalsMojangGameProfile(com.mojang.authlib.GameProfile profile) {
|
||||
if (profile != null) {
|
||||
return profile.getId() != null && getId() != null && profile.getId() == getId()
|
||||
&& profile.getName() != null && getName() != null && profile.getName().equals(getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o != null && this.getClass() == o.getClass()) {
|
||||
GameProfile that = (GameProfile) o;
|
||||
if (this.id != null) {
|
||||
if (!this.id.equals(that.id)) {
|
||||
return false;
|
||||
}
|
||||
} else if (that.id != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.name != null) {
|
||||
return this.name.equals(that.name);
|
||||
} else return that.name == null;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result = this.id != null ? this.id.hashCode() : 0;
|
||||
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return (new ToStringBuilder(this)).append("id", this.id).append("name", this.name).append("properties", this.properties).append("legacy", this.legacy).toString();
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return this.legacy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package io.github.retrooper.packetevents.packet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PacketType {
|
||||
|
||||
|
||||
public static class Client {
|
||||
public static class Util {
|
||||
public static boolean isInstanceOfFlying(final int packetId) {
|
||||
return packetId == FLYING
|
||||
|| packetId == POSITION
|
||||
|| packetId == POSITION_LOOK
|
||||
|| packetId == LOOK;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Map<Class<?>, Integer> packetIds = new HashMap<Class<?>, Integer>();
|
||||
|
||||
public static final int TELEPORT_ACCEPT = 0,
|
||||
TILE_NBT_QUERY = 1, DIFFICULTY_CHANGE = 2, CHAT = 3, CLIENT_COMMAND = 4,
|
||||
SETTINGS = 5, TAB_COMPLETE = 6, TRANSACTION = 7, ENCHANT_ITEM = 8,
|
||||
WINDOW_CLICK = 9, CLOSE_WINDOW = 10, CUSTOM_PAYLOAD = 11, B_EDIT = 12,
|
||||
ENTITY_NBT_QUERY = 13, USE_ENTITY = 14, JIGSAW_GENERATE = 15, KEEP_ALIVE = 16,
|
||||
DIFFICULTY_LOCK = 17, POSITION = 18, POSITION_LOOK = 19, LOOK = 20,
|
||||
FLYING = 21, VEHICLE_MOVE = 22, BOAT_MOVE = 23, PICK_ITEM = 24,
|
||||
AUTO_RECIPE = 25, ABILITIES = 26, BLOCK_DIG = 27, ENTITY_ACTION = 28,
|
||||
STEER_VEHICLE = 29, RECIPE_DISPLAYED = 30, ITEM_NAME = 31, RESOURCE_PACK_STATUS = 32,
|
||||
ADVANCEMENTS = 33, TR_SEL = 34, BEACON = 35, HELD_ITEM_SLOT = 36,
|
||||
SET_COMMAND_BLOCK = 37, SET_COMMAND_MINECART = 38, SET_CREATIVE_SLOT = 39, SET_JIGSAW = 40,
|
||||
STRUCT = 41, UPDATE_SIGN = 42, ARM_ANIMATION = 43, SPECTATE = 44,
|
||||
USE_ITEM = 45, BLOCK_PLACE = 46;
|
||||
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Client.TELEPORT_ACCEPT, TELEPORT_ACCEPT);
|
||||
packetIds.put(PacketTypeClasses.Client.TILE_NBT_QUERY, TILE_NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Client.DIFFICULTY_CHANGE, DIFFICULTY_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Client.CHAT, CHAT);
|
||||
packetIds.put(PacketTypeClasses.Client.CLIENT_COMMAND, CLIENT_COMMAND);
|
||||
packetIds.put(PacketTypeClasses.Client.SETTINGS, SETTINGS);
|
||||
packetIds.put(PacketTypeClasses.Client.TAB_COMPLETE, TAB_COMPLETE);
|
||||
packetIds.put(PacketTypeClasses.Client.TRANSACTION, TRANSACTION);
|
||||
packetIds.put(PacketTypeClasses.Client.ENCHANT_ITEM, ENCHANT_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Client.WINDOW_CLICK, WINDOW_CLICK);
|
||||
packetIds.put(PacketTypeClasses.Client.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Client.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Client.B_EDIT, B_EDIT);
|
||||
packetIds.put(PacketTypeClasses.Client.ENTITY_NBT_QUERY, ENTITY_NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Client.USE_ENTITY, USE_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Client.JIGSAW_GENERATE, JIGSAW_GENERATE);
|
||||
packetIds.put(PacketTypeClasses.Client.KEEP_ALIVE, KEEP_ALIVE);
|
||||
packetIds.put(PacketTypeClasses.Client.DIFFICULTY_LOCK, DIFFICULTY_LOCK);
|
||||
packetIds.put(PacketTypeClasses.Client.POSITION, POSITION);
|
||||
packetIds.put(PacketTypeClasses.Client.POSITION_LOOK, POSITION_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Client.LOOK, LOOK);
|
||||
packetIds.put(PacketTypeClasses.Client.FLYING, FLYING);
|
||||
packetIds.put(PacketTypeClasses.Client.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Client.BOAT_MOVE, BOAT_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Client.PICK_ITEM, PICK_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Client.AUTO_RECIPE, AUTO_RECIPE);
|
||||
packetIds.put(PacketTypeClasses.Client.ABILITIES, ABILITIES);
|
||||
packetIds.put(PacketTypeClasses.Client.BLOCK_DIG, BLOCK_DIG);
|
||||
packetIds.put(PacketTypeClasses.Client.ENTITY_ACTION, ENTITY_ACTION);
|
||||
packetIds.put(PacketTypeClasses.Client.STEER_VEHICLE, STEER_VEHICLE);
|
||||
packetIds.put(PacketTypeClasses.Client.RECIPE_DISPLAYED, RECIPE_DISPLAYED);
|
||||
packetIds.put(PacketTypeClasses.Client.ITEM_NAME, ITEM_NAME);
|
||||
packetIds.put(PacketTypeClasses.Client.RESOURCE_PACK_STATUS, RESOURCE_PACK_STATUS);
|
||||
packetIds.put(PacketTypeClasses.Client.ADVANCEMENTS, ADVANCEMENTS);
|
||||
packetIds.put(PacketTypeClasses.Client.TR_SEL, TR_SEL);
|
||||
packetIds.put(PacketTypeClasses.Client.BEACON, BEACON);
|
||||
packetIds.put(PacketTypeClasses.Client.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Client.SET_COMMAND_BLOCK, SET_COMMAND_BLOCK);
|
||||
packetIds.put(PacketTypeClasses.Client.SET_COMMAND_MINECART, SET_COMMAND_MINECART);
|
||||
packetIds.put(PacketTypeClasses.Client.SET_CREATIVE_SLOT, SET_CREATIVE_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Client.SET_JIGSAW, SET_JIGSAW);
|
||||
packetIds.put(PacketTypeClasses.Client.STRUCT, STRUCT);
|
||||
packetIds.put(PacketTypeClasses.Client.UPDATE_SIGN, UPDATE_SIGN);
|
||||
packetIds.put(PacketTypeClasses.Client.ARM_ANIMATION, ARM_ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Client.SPECTATE, SPECTATE);
|
||||
packetIds.put(PacketTypeClasses.Client.USE_ITEM, USE_ITEM);
|
||||
packetIds.put(PacketTypeClasses.Client.BLOCK_PLACE, BLOCK_PLACE);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
public static final Map<Class<?>, Integer> packetIds = new HashMap<Class<?>, Integer>();
|
||||
public static int SPAWN_ENTITY = 0, SPAWN_ENTITY_EXPERIENCE_ORB = 1, SPAWN_ENTITY_WEATHER = 2, SPAWN_ENTITY_LIVING = 3,
|
||||
SPAWN_ENTITY_PAINTING = 4, SPAWN_ENTITY_SPAWN = 5, ANIMATION = 6, STATISTIC = 7,
|
||||
BLOCK_BREAK = 8, BLOCK_BREAK_ANIMATION = 9, TILE_ENTITY_DATA = 10, BLOCK_ACTION = 11,
|
||||
BLOCK_CHANGE = 12, BOSS = 13, SERVER_DIFFICULTY = 14, CHAT = 15, MULTI_BLOCK_CHANGE = 16,
|
||||
TAB_COMPLETE = 17, COMMANDS = 18, TRANSACTION = 19, CLOSE_WINDOW = 20,
|
||||
WINDOW_ITEMS = 21, WINDOW_DATA = 22, SET_SLOT = 23, SET_COOLDOWN = 24,
|
||||
CUSTOM_PAYLOAD = 25, CUSTOM_SOUND_EFFECT = 26, KICK_DISCONNECT = 27, ENTITY_STATUS = 28,
|
||||
EXPLOSION = 29, UNLOAD_CHUNK = 30, GAME_STATE_CHANGE = 31, OPEN_WINDOW_HORSE = 32,
|
||||
KEEP_ALIVE = 33, MAP_CHUNK = 34, WORLD_EVENT = 35, WORLD_PARTICLES = 36,
|
||||
LIGHT_UPDATE = 37, LOGIN = 38, MAP = 39, OPEN_WINDOW_MERCHANT = 40,
|
||||
REL_ENTITY_MOVE = 41, REL_ENTITY_MOVE_LOOK = 42, ENTITY_LOOK = 43, ENTITY = 44,
|
||||
VEHICLE_MOVE = 45, OPEN_BOOK = 46, OPEN_WINDOW = 47, OPEN_SIGN_EDITOR = 48,
|
||||
AUTO_RECIPE = 49, ABILITIES = 50, COMBAT_EVENT = 51, PLAYER_INFO = 52,
|
||||
LOOK_AT = 53, POSITION = 54, RECIPES = 55, ENTITY_DESTROY = 56,
|
||||
REMOVE_ENTITY_EFFECT = 57, RESOURCE_PACK_SEND = 58, RESPAWN = 59, ENTITY_HEAD_ROTATION = 60,
|
||||
SELECT_ADVANCEMENT_TAB = 61, WORLD_BORDER = 62, CAMERA = 63, HELD_ITEM_SLOT = 64,
|
||||
VIEW_CENTRE = 65, VIEW_DISTANCE = 66, SCOREBOARD_DISPLAY_OBJECTIVE = 67, ENTITY_METADATA = 68,
|
||||
ATTACH_ENTITY = 69, ENTITY_VELOCITY = 70, ENTITY_EQUIPMENT = 71, EXPERIENCE = 72,
|
||||
UPDATE_HEALTH = 73, SCOREBOARD_OBJECTIVE = 74, MOUNT = 75, SCOREBOARD_TEAM = 76,
|
||||
SCOREBOARD_SCORE = 77, SPAWN_POSITION = 78, UPDATE_TIME = 79, TITLE = 80,
|
||||
ENTITY_SOUND = 81, NAMED_SOUND_EFFECT = 82, STOP_SOUND = 83, PLAYER_LIST_HEADER_FOOTER = 84,
|
||||
NBT_QUERY = 85, COLLECT = 86, ENTITY_TELEPORT = 87, ADVANCEMENTS = 88, UPDATE_ATTRIBUTES = 89,
|
||||
ENTITY_EFFECT = 90, RECIPE_UPDATE = 91, TAGS = 92, MAP_CHUNK_BULK = 93;
|
||||
|
||||
public static void init() {
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_EXPERIENCE_ORB);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_WEATHER);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_LIVING, SPAWN_ENTITY_LIVING);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_PAINTING);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY_SPAWN, SPAWN_ENTITY_SPAWN);
|
||||
packetIds.put(PacketTypeClasses.Server.ANIMATION, ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Server.STATISTIC, STATISTIC);
|
||||
packetIds.put(PacketTypeClasses.Server.BLOCK_BREAK, BLOCK_BREAK);
|
||||
packetIds.put(PacketTypeClasses.Server.BLOCK_BREAK_ANIMATION, BLOCK_BREAK_ANIMATION);
|
||||
packetIds.put(PacketTypeClasses.Server.TILE_ENTITY_DATA, TILE_ENTITY_DATA);
|
||||
packetIds.put(PacketTypeClasses.Server.BLOCK_ACTION, BLOCK_ACTION);
|
||||
packetIds.put(PacketTypeClasses.Server.BLOCK_CHANGE, BLOCK_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Server.BOSS, BOSS);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_ENTITY, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Server.SERVER_DIFFICULTY, SERVER_DIFFICULTY);
|
||||
packetIds.put(PacketTypeClasses.Server.CHAT, CHAT);
|
||||
packetIds.put(PacketTypeClasses.Server.MULTI_BLOCK_CHANGE, MULTI_BLOCK_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Server.TAB_COMPLETE, TAB_COMPLETE);
|
||||
packetIds.put(PacketTypeClasses.Server.COMMANDS, COMMANDS);
|
||||
packetIds.put(PacketTypeClasses.Server.TRANSACTION, TRANSACTION);
|
||||
packetIds.put(PacketTypeClasses.Server.CLOSE_WINDOW, CLOSE_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Server.WINDOW_ITEMS, WINDOW_ITEMS);
|
||||
packetIds.put(PacketTypeClasses.Server.WINDOW_DATA, WINDOW_DATA);
|
||||
packetIds.put(PacketTypeClasses.Server.SET_SLOT, SET_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Server.CUSTOM_PAYLOAD, CUSTOM_PAYLOAD);
|
||||
packetIds.put(PacketTypeClasses.Server.CUSTOM_SOUND_EFFECT, CUSTOM_SOUND_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Server.KICK_DISCONNECT, KICK_DISCONNECT);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_STATUS, ENTITY_STATUS);
|
||||
packetIds.put(PacketTypeClasses.Server.EXPLOSION, EXPLOSION);
|
||||
packetIds.put(PacketTypeClasses.Server.UNLOAD_CHUNK, UNLOAD_CHUNK);
|
||||
packetIds.put(PacketTypeClasses.Server.GAME_STATE_CHANGE, GAME_STATE_CHANGE);
|
||||
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW_HORSE, OPEN_WINDOW_HORSE);
|
||||
packetIds.put(PacketTypeClasses.Server.KEEP_ALIVE, KEEP_ALIVE);
|
||||
packetIds.put(PacketTypeClasses.Server.MAP_CHUNK, MAP_CHUNK);
|
||||
packetIds.put(PacketTypeClasses.Server.WORLD_EVENT, SPAWN_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Server.WORLD_PARTICLES, WORLD_PARTICLES);
|
||||
packetIds.put(PacketTypeClasses.Server.LIGHT_UPDATE, LIGHT_UPDATE);
|
||||
packetIds.put(PacketTypeClasses.Server.LOGIN, LOGIN);
|
||||
packetIds.put(PacketTypeClasses.Server.MAP, MAP);
|
||||
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW_MERCHANT, OPEN_WINDOW_MERCHANT);
|
||||
packetIds.put(PacketTypeClasses.Server.REL_ENTITY_MOVE, REL_ENTITY_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Server.REL_ENTITY_MOVE_LOOK, REL_ENTITY_MOVE_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_LOOK, ENTITY_LOOK);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY, ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Server.VEHICLE_MOVE, VEHICLE_MOVE);
|
||||
packetIds.put(PacketTypeClasses.Server.OPEN_BOOK, OPEN_BOOK);
|
||||
packetIds.put(PacketTypeClasses.Server.OPEN_WINDOW, OPEN_WINDOW);
|
||||
packetIds.put(PacketTypeClasses.Server.OPEN_SIGN_EDITOR, OPEN_SIGN_EDITOR);
|
||||
packetIds.put(PacketTypeClasses.Server.AUTO_RECIPE, AUTO_RECIPE);
|
||||
packetIds.put(PacketTypeClasses.Server.ABILITIES, ABILITIES);
|
||||
packetIds.put(PacketTypeClasses.Server.COMBAT_EVENT, COMBAT_EVENT);
|
||||
packetIds.put(PacketTypeClasses.Server.PLAYER_INFO, PLAYER_INFO);
|
||||
packetIds.put(PacketTypeClasses.Server.LOOK_AT, LOOK_AT);
|
||||
packetIds.put(PacketTypeClasses.Server.POSITION, POSITION);
|
||||
packetIds.put(PacketTypeClasses.Server.RECIPES, RECIPES);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_DESTROY, ENTITY_DESTROY);
|
||||
packetIds.put(PacketTypeClasses.Server.REMOVE_ENTITY_EFFECT, REMOVE_ENTITY_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Server.RESOURCE_PACK_SEND, RESOURCE_PACK_SEND);
|
||||
packetIds.put(PacketTypeClasses.Server.RESPAWN, RESPAWN);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_HEAD_ROTATION, ENTITY_HEAD_ROTATION);
|
||||
packetIds.put(PacketTypeClasses.Server.SELECT_ADVANCEMENT_TAB, SELECT_ADVANCEMENT_TAB);
|
||||
packetIds.put(PacketTypeClasses.Server.WORLD_BORDER, WORLD_BORDER);
|
||||
packetIds.put(PacketTypeClasses.Server.CAMERA, CAMERA);
|
||||
packetIds.put(PacketTypeClasses.Server.HELD_ITEM_SLOT, HELD_ITEM_SLOT);
|
||||
packetIds.put(PacketTypeClasses.Server.VIEW_CENTRE, VIEW_CENTRE);
|
||||
packetIds.put(PacketTypeClasses.Server.VIEW_DISTANCE, VIEW_DISTANCE);
|
||||
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_DISPLAY_OBJECTIVE, SCOREBOARD_DISPLAY_OBJECTIVE);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_METADATA, ENTITY_METADATA);
|
||||
packetIds.put(PacketTypeClasses.Server.ATTACH_ENTITY, ATTACH_ENTITY);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_VELOCITY, ENTITY_VELOCITY);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_EQUIPMENT, ENTITY_EQUIPMENT);
|
||||
packetIds.put(PacketTypeClasses.Server.EXPERIENCE, EXPERIENCE);
|
||||
packetIds.put(PacketTypeClasses.Server.UPDATE_HEALTH, UPDATE_HEALTH);
|
||||
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_OBJECTIVE, SCOREBOARD_OBJECTIVE);
|
||||
packetIds.put(PacketTypeClasses.Server.MOUNT, MOUNT);
|
||||
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_TEAM, SCOREBOARD_TEAM);
|
||||
packetIds.put(PacketTypeClasses.Server.SCOREBOARD_SCORE, SCOREBOARD_SCORE);
|
||||
packetIds.put(PacketTypeClasses.Server.SPAWN_POSITION, SPAWN_POSITION);
|
||||
packetIds.put(PacketTypeClasses.Server.UPDATE_TIME, UPDATE_TIME);
|
||||
packetIds.put(PacketTypeClasses.Server.TITLE, TITLE);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_SOUND, ENTITY_SOUND);
|
||||
packetIds.put(PacketTypeClasses.Server.NAMED_SOUND_EFFECT, NAMED_SOUND_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Server.STOP_SOUND, STOP_SOUND);
|
||||
packetIds.put(PacketTypeClasses.Server.PLAYER_LIST_HEADER_FOOTER, PLAYER_LIST_HEADER_FOOTER);
|
||||
packetIds.put(PacketTypeClasses.Server.NBT_QUERY, NBT_QUERY);
|
||||
packetIds.put(PacketTypeClasses.Server.COLLECT, COLLECT);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_TELEPORT, ENTITY_TELEPORT);
|
||||
packetIds.put(PacketTypeClasses.Server.ADVANCEMENTS, ADVANCEMENTS);
|
||||
packetIds.put(PacketTypeClasses.Server.UPDATE_ATTRIBUTES, UPDATE_ATTRIBUTES);
|
||||
packetIds.put(PacketTypeClasses.Server.ENTITY_EFFECT, ENTITY_EFFECT);
|
||||
packetIds.put(PacketTypeClasses.Server.RECIPE_UPDATE, RECIPE_UPDATE);
|
||||
packetIds.put(PacketTypeClasses.Server.TAGS, TAGS);
|
||||
packetIds.put(PacketTypeClasses.Server.MAP_CHUNK_BULK, MAP_CHUNK_BULK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
package io.github.retrooper.packetevents.packet;
|
||||
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public class PacketTypeClasses {
|
||||
public static class Client {
|
||||
public static Class<?> POSITION, POSITION_LOOK, LOOK, CLIENT_COMMAND,
|
||||
TRANSACTION, BLOCK_DIG, ENTITY_ACTION, USE_ENTITY,
|
||||
WINDOW_CLICK, STEER_VEHICLE, CUSTOM_PAYLOAD, ARM_ANIMATION,
|
||||
BLOCK_PLACE, USE_ITEM, ABILITIES, HELD_ITEM_SLOT,
|
||||
CLOSE_WINDOW, TAB_COMPLETE, CHAT, SET_CREATIVE_SLOT,
|
||||
KEEP_ALIVE, SETTINGS, ENCHANT_ITEM, TELEPORT_ACCEPT,
|
||||
TILE_NBT_QUERY, DIFFICULTY_CHANGE, B_EDIT, ENTITY_NBT_QUERY,
|
||||
JIGSAW_GENERATE, DIFFICULTY_LOCK, VEHICLE_MOVE, BOAT_MOVE, PICK_ITEM,
|
||||
AUTO_RECIPE, RECIPE_DISPLAYED, ITEM_NAME, RESOURCE_PACK_STATUS,
|
||||
ADVANCEMENTS, TR_SEL, BEACON, SET_COMMAND_BLOCK,
|
||||
SET_COMMAND_MINECART, SET_JIGSAW, STRUCT, UPDATE_SIGN, SPECTATE;
|
||||
private static final String c = "PacketPlayIn";
|
||||
@Nullable
|
||||
public static final Class<?> FLYING = NMSUtils.getNMSClassWithoutException(c + "Flying");
|
||||
|
||||
public static void load() {
|
||||
try {
|
||||
POSITION = NMSUtils.getNMSClass(c + "Position");
|
||||
POSITION_LOOK = NMSUtils.getNMSClass(c + "PositionLook");
|
||||
LOOK = NMSUtils.getNMSClass(c + "Look");
|
||||
} catch (ClassNotFoundException e) {
|
||||
POSITION = Reflection.getSubClass(FLYING, c + "Position");
|
||||
POSITION_LOOK = Reflection.getSubClass(FLYING, c + "PositionLook");
|
||||
LOOK = Reflection.getSubClass(FLYING, c + "Look");
|
||||
}
|
||||
|
||||
try {
|
||||
SETTINGS = NMSUtils.getNMSClass(c + "Settings");
|
||||
ENCHANT_ITEM = NMSUtils.getNMSClass(c + "EnchantItem");
|
||||
|
||||
CLIENT_COMMAND = NMSUtils.getNMSClass(c + "ClientCommand");
|
||||
TRANSACTION = NMSUtils.getNMSClass(c + "Transaction");
|
||||
BLOCK_DIG = NMSUtils.getNMSClass(c + "BlockDig");
|
||||
ENTITY_ACTION = NMSUtils.getNMSClass(c + "EntityAction");
|
||||
USE_ENTITY = NMSUtils.getNMSClass(c + "UseEntity");
|
||||
WINDOW_CLICK = NMSUtils.getNMSClass(c + "WindowClick");
|
||||
STEER_VEHICLE = NMSUtils.getNMSClass(c + "SteerVehicle");
|
||||
CUSTOM_PAYLOAD = NMSUtils.getNMSClass(c + "CustomPayload");
|
||||
ARM_ANIMATION = NMSUtils.getNMSClass(c + "ArmAnimation");
|
||||
ABILITIES = NMSUtils.getNMSClass(c + "Abilities");
|
||||
HELD_ITEM_SLOT = NMSUtils.getNMSClass(c + "HeldItemSlot");
|
||||
CLOSE_WINDOW = NMSUtils.getNMSClass(c + "CloseWindow");
|
||||
TAB_COMPLETE = NMSUtils.getNMSClass(c + "TabComplete");
|
||||
CHAT = NMSUtils.getNMSClass(c + "Chat");
|
||||
SET_CREATIVE_SLOT = NMSUtils.getNMSClass(c + "SetCreativeSlot");
|
||||
KEEP_ALIVE = NMSUtils.getNMSClass(c + "KeepAlive");
|
||||
UPDATE_SIGN = NMSUtils.getNMSClassWithoutException(c + "UpdateSign");
|
||||
|
||||
TELEPORT_ACCEPT = NMSUtils.getNMSClassWithoutException(c + "TeleportAccept");
|
||||
TILE_NBT_QUERY = NMSUtils.getNMSClassWithoutException(c + "TileNBTQuery");
|
||||
DIFFICULTY_CHANGE = NMSUtils.getNMSClassWithoutException(c + "DifficultyChange");
|
||||
B_EDIT = NMSUtils.getNMSClassWithoutException(c + "BEdit");
|
||||
ENTITY_NBT_QUERY = NMSUtils.getNMSClassWithoutException(c + "EntityNBTQuery");
|
||||
JIGSAW_GENERATE = NMSUtils.getNMSClassWithoutException(c + "JigsawGenerate");
|
||||
DIFFICULTY_LOCK = NMSUtils.getNMSClassWithoutException(c + "DifficultyLock");
|
||||
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(c + "VehicleMove");
|
||||
BOAT_MOVE = NMSUtils.getNMSClassWithoutException(c + "BoatMove");
|
||||
PICK_ITEM = NMSUtils.getNMSClassWithoutException(c + "PickItem");
|
||||
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(c + "AutoRecipe");
|
||||
RECIPE_DISPLAYED = NMSUtils.getNMSClassWithoutException(c + "RecipeDisplayed");
|
||||
ITEM_NAME = NMSUtils.getNMSClassWithoutException(c + "ItemName");
|
||||
//1.8+
|
||||
RESOURCE_PACK_STATUS = NMSUtils.getNMSClassWithoutException(c + "ResourcePackStatus");
|
||||
|
||||
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(c + "Advancements");
|
||||
TR_SEL = NMSUtils.getNMSClassWithoutException(c + "TrSel");
|
||||
BEACON = NMSUtils.getNMSClassWithoutException(c + "Beacon");
|
||||
SET_COMMAND_BLOCK = NMSUtils.getNMSClassWithoutException(c + "SetCommandBlock");
|
||||
SET_COMMAND_MINECART = NMSUtils.getNMSClassWithoutException(c + "SetCommandMinecart");
|
||||
SET_JIGSAW = NMSUtils.getNMSClassWithoutException(c + "SetJigsaw");
|
||||
STRUCT = NMSUtils.getNMSClassWithoutException(c + "Struct");
|
||||
SPECTATE = NMSUtils.getNMSClassWithoutException(c + "Spectate");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Block place
|
||||
try {
|
||||
BLOCK_PLACE = NMSUtils.getNMSClass(c + "BlockPlace");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//They are just on a newer version
|
||||
try {
|
||||
USE_ITEM = NMSUtils.getNMSClass(c + "UseItem");
|
||||
} catch (ClassNotFoundException e2) {
|
||||
e.printStackTrace();
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PacketType.Client.init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
private static final String s = "PacketPlayOut";
|
||||
public static Class<?> SPAWN_ENTITY, SPAWN_ENTITY_EXPERIENCE_ORB, SPAWN_ENTITY_WEATHER, SPAWN_ENTITY_LIVING,
|
||||
SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_SPAWN, ANIMATION, STATISTIC,
|
||||
BLOCK_BREAK, BLOCK_BREAK_ANIMATION, TILE_ENTITY_DATA, BLOCK_ACTION,
|
||||
BLOCK_CHANGE, BOSS, SERVER_DIFFICULTY, CHAT, MULTI_BLOCK_CHANGE,
|
||||
TAB_COMPLETE, COMMANDS, TRANSACTION, CLOSE_WINDOW,
|
||||
WINDOW_ITEMS, WINDOW_DATA, SET_SLOT, SET_COOLDOWN,
|
||||
CUSTOM_PAYLOAD, CUSTOM_SOUND_EFFECT, KICK_DISCONNECT, ENTITY_STATUS,
|
||||
EXPLOSION, UNLOAD_CHUNK, GAME_STATE_CHANGE, OPEN_WINDOW_HORSE,
|
||||
KEEP_ALIVE, MAP_CHUNK, WORLD_EVENT, WORLD_PARTICLES,
|
||||
LIGHT_UPDATE, LOGIN, MAP, OPEN_WINDOW_MERCHANT,
|
||||
REL_ENTITY_MOVE, REL_ENTITY_MOVE_LOOK, ENTITY_LOOK, ENTITY,
|
||||
VEHICLE_MOVE, OPEN_BOOK, OPEN_WINDOW, OPEN_SIGN_EDITOR,
|
||||
AUTO_RECIPE, ABILITIES, COMBAT_EVENT, PLAYER_INFO,
|
||||
LOOK_AT, POSITION, RECIPES, ENTITY_DESTROY,
|
||||
REMOVE_ENTITY_EFFECT, RESOURCE_PACK_SEND, RESPAWN, ENTITY_HEAD_ROTATION,
|
||||
SELECT_ADVANCEMENT_TAB, WORLD_BORDER, CAMERA, HELD_ITEM_SLOT,
|
||||
VIEW_CENTRE, VIEW_DISTANCE, SCOREBOARD_DISPLAY_OBJECTIVE, ENTITY_METADATA,
|
||||
ATTACH_ENTITY, ENTITY_VELOCITY, ENTITY_EQUIPMENT, EXPERIENCE,
|
||||
UPDATE_HEALTH, SCOREBOARD_OBJECTIVE, MOUNT, SCOREBOARD_TEAM,
|
||||
SCOREBOARD_SCORE, SPAWN_POSITION, UPDATE_TIME, TITLE,
|
||||
ENTITY_SOUND, NAMED_SOUND_EFFECT, STOP_SOUND, PLAYER_LIST_HEADER_FOOTER,
|
||||
NBT_QUERY, COLLECT, ENTITY_TELEPORT, ADVANCEMENTS, UPDATE_ATTRIBUTES,
|
||||
ENTITY_EFFECT, RECIPE_UPDATE, TAGS, MAP_CHUNK_BULK;
|
||||
|
||||
public static void load() {
|
||||
SPAWN_ENTITY = NMSUtils.getNMSClassWithoutException(s + "SpawnEntity");
|
||||
SPAWN_ENTITY_EXPERIENCE_ORB = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityExperienceOrb");
|
||||
SPAWN_ENTITY_WEATHER = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityWeather");
|
||||
SPAWN_ENTITY_LIVING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityLiving");
|
||||
SPAWN_ENTITY_PAINTING = NMSUtils.getNMSClassWithoutException(s + "SpawnEntityPainting");
|
||||
SPAWN_ENTITY_SPAWN = NMSUtils.getNMSClassWithoutException(s + "SpawnEntitySpawn");
|
||||
ANIMATION = NMSUtils.getNMSClassWithoutException(s + "Animation");
|
||||
STATISTIC = NMSUtils.getNMSClassWithoutException(s + "Statistic");
|
||||
BLOCK_BREAK = NMSUtils.getNMSClassWithoutException(s + "BlockBreak");
|
||||
BLOCK_BREAK_ANIMATION = NMSUtils.getNMSClassWithoutException(s + "BlockBreakAnimation");
|
||||
TILE_ENTITY_DATA = NMSUtils.getNMSClassWithoutException(s + "TileEntityData");
|
||||
BLOCK_ACTION = NMSUtils.getNMSClassWithoutException(s + "BlockAction");
|
||||
BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "BlockChange");
|
||||
BOSS = NMSUtils.getNMSClassWithoutException(s + "Boss");
|
||||
SERVER_DIFFICULTY = NMSUtils.getNMSClassWithoutException(s + "ServerDifficulty");
|
||||
CHAT = NMSUtils.getNMSClassWithoutException(s + "Chat");
|
||||
MULTI_BLOCK_CHANGE = NMSUtils.getNMSClassWithoutException(s + "MultiBlockChange");
|
||||
TAB_COMPLETE = NMSUtils.getNMSClassWithoutException(s + "TabComplete");
|
||||
COMMANDS = NMSUtils.getNMSClassWithoutException(s + "Commands");
|
||||
TRANSACTION = NMSUtils.getNMSClassWithoutException(s + "Transaction");
|
||||
CLOSE_WINDOW = NMSUtils.getNMSClassWithoutException(s + "CloseWindow");
|
||||
WINDOW_ITEMS = NMSUtils.getNMSClassWithoutException(s + "WindowItems");
|
||||
WINDOW_DATA = NMSUtils.getNMSClassWithoutException(s + "WindowData");
|
||||
SET_SLOT = NMSUtils.getNMSClassWithoutException(s + "SetSlot");
|
||||
SET_COOLDOWN = NMSUtils.getNMSClassWithoutException(s + "SetCooldown");
|
||||
CUSTOM_PAYLOAD = NMSUtils.getNMSClassWithoutException(s + "CustomPayload");
|
||||
CUSTOM_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "CustomSoundEffect");
|
||||
KICK_DISCONNECT = NMSUtils.getNMSClassWithoutException(s + "KickDisconnect");
|
||||
ENTITY_STATUS = NMSUtils.getNMSClassWithoutException(s + "EntityStatus");
|
||||
EXPLOSION = NMSUtils.getNMSClassWithoutException(s + "Explosion");
|
||||
UNLOAD_CHUNK = NMSUtils.getNMSClassWithoutException(s + "UnloadChunk");
|
||||
GAME_STATE_CHANGE = NMSUtils.getNMSClassWithoutException(s + "GameStateChange");
|
||||
OPEN_WINDOW_HORSE = NMSUtils.getNMSClassWithoutException(s + "OpenWindowHorse");
|
||||
KEEP_ALIVE = NMSUtils.getNMSClassWithoutException(s + "KeepAlive");
|
||||
MAP_CHUNK = NMSUtils.getNMSClassWithoutException(s + "MapChunk");
|
||||
WORLD_EVENT = NMSUtils.getNMSClassWithoutException(s + "WorldEvent");
|
||||
WORLD_PARTICLES = NMSUtils.getNMSClassWithoutException(s + "WorldParticles");
|
||||
LIGHT_UPDATE = NMSUtils.getNMSClassWithoutException(s + "LightUpdate");
|
||||
LOGIN = NMSUtils.getNMSClassWithoutException(s + "Login");
|
||||
MAP = NMSUtils.getNMSClassWithoutException(s + "Map");
|
||||
OPEN_WINDOW_MERCHANT = NMSUtils.getNMSClassWithoutException(s + "OpenWindowMerchant");
|
||||
ENTITY = NMSUtils.getNMSClassWithoutException(s + "Entity");
|
||||
REL_ENTITY_MOVE = Reflection.getSubClass(ENTITY, s + "RelEntityMove");
|
||||
REL_ENTITY_MOVE_LOOK = Reflection.getSubClass(ENTITY, s + "RelEntityMoveLook");
|
||||
ENTITY_LOOK = Reflection.getSubClass(ENTITY, s + "EntityLook");
|
||||
if (REL_ENTITY_MOVE == null) {
|
||||
//is not a subclass and should be accessed normally
|
||||
REL_ENTITY_MOVE = NMSUtils.getNMSClassWithoutException(s + "RelEntityMove");
|
||||
REL_ENTITY_MOVE_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityMoveLook");
|
||||
ENTITY_LOOK = NMSUtils.getNMSClassWithoutException(s + "RelEntityLook");
|
||||
}
|
||||
VEHICLE_MOVE = NMSUtils.getNMSClassWithoutException(s + "VehicleMove");
|
||||
OPEN_BOOK = NMSUtils.getNMSClassWithoutException(s + "OpenBook");
|
||||
OPEN_WINDOW = NMSUtils.getNMSClassWithoutException(s + "OpenWindow");
|
||||
OPEN_SIGN_EDITOR = NMSUtils.getNMSClassWithoutException(s + "OpenSignEditor");
|
||||
AUTO_RECIPE = NMSUtils.getNMSClassWithoutException(s + "AutoRecipe");
|
||||
ABILITIES = NMSUtils.getNMSClassWithoutException(s + "Abilities");
|
||||
COMBAT_EVENT = NMSUtils.getNMSClassWithoutException(s + "CombatEvent");
|
||||
PLAYER_INFO = NMSUtils.getNMSClassWithoutException(s + "PlayerInfo");
|
||||
LOOK_AT = NMSUtils.getNMSClassWithoutException(s + "LookAt");
|
||||
POSITION = NMSUtils.getNMSClassWithoutException(s + "Position");
|
||||
RECIPES = NMSUtils.getNMSClassWithoutException(s + "Recipes");
|
||||
ENTITY_DESTROY = NMSUtils.getNMSClassWithoutException(s + "EntityDestroy");
|
||||
REMOVE_ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "RemoveEntityEffect");
|
||||
RESOURCE_PACK_SEND = NMSUtils.getNMSClassWithoutException(s + "ResourcePackSend");
|
||||
RESPAWN = NMSUtils.getNMSClassWithoutException(s + "Respawn");
|
||||
ENTITY_HEAD_ROTATION = NMSUtils.getNMSClassWithoutException(s + "EntityHeadRotation");
|
||||
SELECT_ADVANCEMENT_TAB = NMSUtils.getNMSClassWithoutException(s + "SelectAdvancementTab");
|
||||
WORLD_BORDER = NMSUtils.getNMSClassWithoutException(s + "WorldBorder");
|
||||
CAMERA = NMSUtils.getNMSClassWithoutException(s + "Camera");
|
||||
HELD_ITEM_SLOT = NMSUtils.getNMSClassWithoutException(s + "HeldItemSlot");
|
||||
VIEW_CENTRE = NMSUtils.getNMSClassWithoutException(s + "ViewCentre");
|
||||
VIEW_DISTANCE = NMSUtils.getNMSClassWithoutException(s + "ViewDistance");
|
||||
SCOREBOARD_DISPLAY_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardDisplayObjective");
|
||||
ENTITY_METADATA = NMSUtils.getNMSClassWithoutException(s + "EntityMetadata");
|
||||
ATTACH_ENTITY = NMSUtils.getNMSClassWithoutException(s + "AttachEntity");
|
||||
ENTITY_VELOCITY = NMSUtils.getNMSClassWithoutException(s + "EntityVelocity");
|
||||
ENTITY_EQUIPMENT = NMSUtils.getNMSClassWithoutException(s + "EntityEquipment");
|
||||
EXPERIENCE = NMSUtils.getNMSClassWithoutException(s + "Experience");
|
||||
UPDATE_HEALTH = NMSUtils.getNMSClassWithoutException(s + "UpdateHealth");
|
||||
SCOREBOARD_OBJECTIVE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardObjective");
|
||||
MOUNT = NMSUtils.getNMSClassWithoutException(s + "Mount");
|
||||
SCOREBOARD_TEAM = NMSUtils.getNMSClassWithoutException(s + "ScoreboardTeam");
|
||||
SCOREBOARD_SCORE = NMSUtils.getNMSClassWithoutException(s + "ScoreboardScore");
|
||||
SPAWN_POSITION = NMSUtils.getNMSClassWithoutException(s + "SpawnPosition");
|
||||
UPDATE_TIME = NMSUtils.getNMSClassWithoutException(s + "UpdateTime");
|
||||
TITLE = NMSUtils.getNMSClassWithoutException(s + "Title");
|
||||
ENTITY_SOUND = NMSUtils.getNMSClassWithoutException(s + "EntitySound");
|
||||
NAMED_SOUND_EFFECT = NMSUtils.getNMSClassWithoutException(s + "NamedSoundEffect");
|
||||
STOP_SOUND = NMSUtils.getNMSClassWithoutException(s + "StopSound");
|
||||
PLAYER_LIST_HEADER_FOOTER = NMSUtils.getNMSClassWithoutException(s + "PlayerListHeaderFooter");
|
||||
NBT_QUERY = NMSUtils.getNMSClassWithoutException(s + "NBTQuery");
|
||||
COLLECT = NMSUtils.getNMSClassWithoutException(s + "Collect");
|
||||
ENTITY_TELEPORT = NMSUtils.getNMSClassWithoutException(s + "EntityTeleport");
|
||||
ADVANCEMENTS = NMSUtils.getNMSClassWithoutException(s + "Advancements");
|
||||
UPDATE_ATTRIBUTES = NMSUtils.getNMSClassWithoutException(s + "UpdateAttributes");
|
||||
ENTITY_EFFECT = NMSUtils.getNMSClassWithoutException(s + "EntityEffect");
|
||||
RECIPE_UPDATE = NMSUtils.getNMSClassWithoutException(s + "RecipeUpdate");
|
||||
TAGS = NMSUtils.getNMSClassWithoutException(s + "Tags");
|
||||
MAP_CHUNK_BULK = NMSUtils.getNMSClassWithoutException(s + "MapChunkBulk");
|
||||
PacketType.Server.init();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+91
-50
@@ -1,66 +1,110 @@
|
||||
package io.github.retrooper.packetevents.packet;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public abstract class Packet {
|
||||
@Deprecated
|
||||
public final class PacketTypeNames {
|
||||
private static final ServerVersion version = PacketEvents.getAPI().getServerUtilities().getServerVersion();
|
||||
|
||||
private static Class<?> packetPlayInFlying, packetPlayInPosition, packetPlayInPositionLook, packetPlayInLook;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetPlayInFlying = NMSUtils.getNMSClass(Client.FLYING);
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, they are on 1.9+ so we just initiate the rest of the variables
|
||||
public static final class Util {
|
||||
private static Class<?> packetPlayInFlying, packetPlayInPosition, packetPlayInPositionLook, packetPlayInLook, packetPlayInUseEntity;
|
||||
|
||||
static {
|
||||
try {
|
||||
//Only exists in 1.7->1.8.8 & 1.16 protocol
|
||||
packetPlayInFlying = NMSUtils.getNMSClass(Client.FLYING);
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, they are on 1.9->1.15.2
|
||||
}
|
||||
try {
|
||||
packetPlayInPosition = NMSUtils.getNMSClass(Client.POSITION);
|
||||
packetPlayInPositionLook = NMSUtils.getNMSClass(Client.POSITION_LOOK);
|
||||
packetPlayInLook = NMSUtils.getNMSClass(Client.LOOK);
|
||||
} catch (ClassNotFoundException e2) {
|
||||
e2.printStackTrace();
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
packetPlayInPosition = Reflection.getSubClass(packetPlayInFlying, Client.POSITION);
|
||||
packetPlayInPositionLook = Reflection.getSubClass(packetPlayInFlying, Client.POSITION_LOOK);
|
||||
packetPlayInLook = Reflection.getSubClass(packetPlayInFlying, Client.LOOK);
|
||||
}
|
||||
|
||||
try {
|
||||
packetPlayInUseEntity = NMSUtils.getNMSClass(Client.USE_ENTITY);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NMS packet an instanceof the "PacketPlayInFlying" packet in the 1.8 protocol?
|
||||
* Supports 1.9->1.15.2 too!
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return If the nms packet provided is an instanceof the "PacketPlayInFlying" packet in the 1.8 protocol!
|
||||
*/
|
||||
public static boolean isInstanceOfFlyingPacket(Object nmsPacket) {
|
||||
//1.7->1.8.8
|
||||
if (packetPlayInFlying != null) {
|
||||
return packetPlayInFlying.isInstance(nmsPacket);
|
||||
} else {
|
||||
//1.9->1.15.2
|
||||
return packetPlayInPosition.isInstance(nmsPacket)
|
||||
|| packetPlayInPositionLook.isInstance(nmsPacket)
|
||||
|| packetPlayInLook.isInstance(nmsPacket);
|
||||
/**
|
||||
* Is this NMS packet an instance of the "PacketPlayInFlying" packet?
|
||||
* Supports 1.9->1.15.2 too!
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return If the nms packet provided is an instanceof the "PacketPlayInFlying" packet in the 1.8 protocol & 1.16 protocol!
|
||||
*/
|
||||
public static boolean isInstanceOfFlyingPacket(final Object nmsPacket) {
|
||||
//1.7->1.8.8
|
||||
if (packetPlayInFlying != null) {
|
||||
return packetPlayInFlying.isInstance(nmsPacket);
|
||||
} else {
|
||||
//1.9->1.15.2
|
||||
return isInstanceOfPositionOrPositionLook(nmsPacket) || isInstanceOfPositionLookPacket(nmsPacket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NMS packet an instance of the "PacketPlayInPosition" packet?
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return nmsPacket instanceof PacketPlayInPosition
|
||||
*/
|
||||
public static boolean isInstanceOfPositionPacket(final Object nmsPacket) {
|
||||
return packetPlayInPosition.isInstance(nmsPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NMS packet an instance of the "PacketPlayInPositionLook" packet?
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return nmsPacket instanceof PacketPlayInPositionLook
|
||||
*/
|
||||
public static boolean isInstanceOfPositionLookPacket(final Object nmsPacket) {
|
||||
return packetPlayInPositionLook.isInstance(nmsPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NMS Packet an instanceof the "PacketPlayInPosition" or "PacketPlayInPositionLook"
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return nmsPacket instanceof PacketPlayInPosition || nmsPacket instanceof PacketPlayInPositionLook
|
||||
*/
|
||||
public static boolean isInstanceOfPositionOrPositionLook(final Object nmsPacket) {
|
||||
return isInstanceOfPositionPacket(nmsPacket) || isInstanceOfPositionLookPacket(nmsPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NMS Packet an instance of the "PacketPlayInLook" packet?
|
||||
*
|
||||
* @param nmsPacket
|
||||
* @return nmsPacket instanceof PacketPlayInLook
|
||||
*/
|
||||
public static boolean isInstanceOfLook(final Object nmsPacket) {
|
||||
return packetPlayInLook.isInstance(nmsPacket);
|
||||
}
|
||||
|
||||
public static boolean isInstanceOfUseEntity(final Object nmsPacket) {
|
||||
return packetPlayInUseEntity.isInstance(nmsPacket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use isInstanceOfFlyingPacket(nmsPacketObject) instead of this, as the flying packet is the only packet that has subclasses (in 1.8 atleast).
|
||||
* Will be removed in newer versions of PacketEvents!
|
||||
*
|
||||
* @param fatherPacket
|
||||
* @param childPacket
|
||||
* @return isInstanceOf
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isInstanceOf(String fatherPacket, String childPacket) {
|
||||
if (fatherPacket.equals(Client.FLYING) && childPacket.equals(Client.POSITION) || childPacket.equals(Client.POSITION_LOOK) || childPacket.equals(Client.LOOK)) {
|
||||
return true;
|
||||
}
|
||||
return fatherPacket.equals(childPacket);
|
||||
}
|
||||
|
||||
public static class Client {
|
||||
public static final class Client {
|
||||
private static final String c = "PacketPlayIn";
|
||||
|
||||
@Deprecated
|
||||
/*
|
||||
* Only exists in 1.7.10->1.8.8 & 1.16+
|
||||
*/
|
||||
public static final String FLYING = c + "Flying";
|
||||
|
||||
|
||||
@@ -92,10 +136,9 @@ public abstract class Packet {
|
||||
public static final String SET_CREATIVE_SLOT = c + "SetCreativeSlot";
|
||||
|
||||
public static final String KEEP_ALIVE = c + "KeepAlive";
|
||||
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
public static final class Server {
|
||||
private static final String s = "PacketPlayOut";
|
||||
|
||||
public static final String ANIMATION = s + "Animation";
|
||||
@@ -124,15 +167,13 @@ public abstract class Packet {
|
||||
public static final String SERVER_DIFFICULTY = s + "ServerDifficulty";
|
||||
}
|
||||
|
||||
public static class Login {
|
||||
public static final class Login {
|
||||
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
|
||||
public static final String PING = "PacketStatusInPing";
|
||||
public static final String START = "PacketStatusInStart";
|
||||
public static final String SUCCESS = "PacketLoginOutSuccess";
|
||||
public static final String ENCRYPTION_BEGIN_IN = "PacketLoginInEncryptionBegin";
|
||||
public static final String ENCRYPTION_BEGIN_OUT = "PacketLoginOutEncryptionBegin";
|
||||
|
||||
public static final String[] LOGIN_PACKETS = new String[]{"PacketHandshakingInSetProtocol", "PacketLoginInStart", "PacketLoginInEncryptionBegin"};
|
||||
}
|
||||
|
||||
}
|
||||
+8
-28
@@ -1,13 +1,11 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.abilities;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
private static Class<?> abilitiesClass;
|
||||
private static final Field[] fields = new Field[6];
|
||||
|
||||
static {
|
||||
|
||||
@@ -16,24 +14,6 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
fields[0] = abilitiesClass.getDeclaredField("a");
|
||||
fields[1] = abilitiesClass.getDeclaredField("b");
|
||||
fields[2] = abilitiesClass.getDeclaredField("c");
|
||||
fields[3] = abilitiesClass.getDeclaredField("d");
|
||||
fields[4] = abilitiesClass.getDeclaredField("e");
|
||||
fields[5] = abilitiesClass.getDeclaredField("f");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (Field f : fields) {
|
||||
if (f != null) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isVulnerable;
|
||||
@@ -50,12 +30,12 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
@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);
|
||||
this.isVulnerable = Reflection.getField(abilitiesClass, boolean.class, 0).getBoolean(packet);
|
||||
this.isFlying = Reflection.getField(abilitiesClass, boolean.class, 1).getBoolean(packet);
|
||||
this.allowFly = Reflection.getField(abilitiesClass, boolean.class, 2).getBoolean(packet);
|
||||
this.instantBuild = Reflection.getField(abilitiesClass, boolean.class, 3).getBoolean(packet);
|
||||
this.flySpeed = Reflection.getField(abilitiesClass, float.class, 0).getFloat(packet);
|
||||
this.walkSpeed = Reflection.getField(abilitiesClass, float.class, 1).getFloat(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -69,7 +49,7 @@ public final class WrappedPacketInAbilities extends WrappedPacket {
|
||||
return isFlying;
|
||||
}
|
||||
|
||||
public boolean canFly() {
|
||||
public boolean isFlightAllowed() {
|
||||
return allowFly;
|
||||
}
|
||||
|
||||
|
||||
+26
-63
@@ -1,70 +1,33 @@
|
||||
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.enums.minecraft.PlayerDigType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
//ALL
|
||||
private static Class<?> blockDigClass;
|
||||
//1.8
|
||||
private static final Field[] fields = new Field[3];
|
||||
private static Class<?> blockPositionClass;
|
||||
private static final Reflection.FieldAccessor<Integer>[] blockPosXYZ = new Reflection.FieldAccessor[3];
|
||||
//1.7
|
||||
private static Field face;
|
||||
private static Field e;
|
||||
private static Class<?> blockDigClass, blockPositionClass, enumDirectionClass, digTypeClass;
|
||||
|
||||
static {
|
||||
|
||||
try {
|
||||
blockDigClass = NMSUtils.getNMSClass("PacketPlayInBlockDig");
|
||||
if (version != ServerVersion.v_1_7_10) {
|
||||
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
blockPositionClass = NMSUtils.getNMSClass("BlockPosition");
|
||||
enumDirectionClass = NMSUtils.getNMSClass("EnumDirection");
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
//blockpos
|
||||
fields[0] = blockDigClass.getDeclaredField("a");
|
||||
//direction
|
||||
fields[1] = blockDigClass.getDeclaredField("b");
|
||||
//digtype
|
||||
fields[2] = blockDigClass.getDeclaredField("c");
|
||||
|
||||
if (version != ServerVersion.v_1_7_10) {
|
||||
blockPosXYZ[0] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 0);
|
||||
blockPosXYZ[1] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 1);
|
||||
blockPosXYZ[2] = Reflection.getField(blockPositionClass.getSuperclass(), int.class, 2);
|
||||
} else {
|
||||
face = blockDigClass.getDeclaredField("face");
|
||||
e = blockDigClass.getDeclaredField("e");
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (Field f : fields) {
|
||||
if (f != null) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (e != null) {
|
||||
e.setAccessible(true);
|
||||
}
|
||||
|
||||
if (face != null) {
|
||||
face.setAccessible(true);
|
||||
digTypeClass = NMSUtils.getNMSClass("EnumPlayerDigType");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//It is probably a subclass
|
||||
digTypeClass = Reflection.getSubClass(blockDigClass, "EnumPlayerDigType");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,26 +45,18 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
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));
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
setupCoordinates(blockDigClass, packet);
|
||||
enumDirection = Direction.get(Reflection.getField(digTypeClass, int.class, 3).getInt(packet));
|
||||
enumDigType = PlayerDigType.get(Reflection.getField(digTypeClass, int.class, 4).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 Object blockPosObj = Reflection.getField(blockDigClass, blockPositionClass, 0).get(packet);
|
||||
final Object enumDirectionObj = Reflection.getField(blockDigClass, enumDirectionClass, 0).get(packet);
|
||||
final Object digTypeObj = Reflection.getField(blockDigClass, digTypeClass, 0).get(packet);
|
||||
|
||||
final int x = blockPosXYZ[0].get(blockPosObj);
|
||||
final int y = blockPosXYZ[1].get(blockPosObj);
|
||||
final int z = blockPosXYZ[2].get(blockPosObj);
|
||||
|
||||
this.blockPosition = new Vector3i(x, y, z);
|
||||
Class<?> blockPosSuper = blockPositionClass;
|
||||
setupCoordinates(blockPosSuper, blockPosObj);
|
||||
|
||||
enumDirection = Direction.valueOf(((Enum) enumDirectionObj).name());
|
||||
enumDigType = PlayerDigType.valueOf(((Enum) digTypeObj).name());
|
||||
@@ -113,6 +68,14 @@ public final class WrappedPacketInBlockDig extends WrappedPacket {
|
||||
this.digType = enumDigType;
|
||||
}
|
||||
|
||||
private void setupCoordinates(final Class<?> cls, final Object object) throws IllegalAccessException {
|
||||
final int x = Reflection.getField(cls, int.class, 0).getInt(object);
|
||||
final int y = Reflection.getField(cls, int.class, 1).getInt(object);
|
||||
final int z = Reflection.getField(cls, int.class, 2).getInt(object);
|
||||
|
||||
this.blockPosition = new Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
public Vector3i getBlockPosition() {
|
||||
return blockPosition;
|
||||
}
|
||||
|
||||
+10
-8
@@ -10,9 +10,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public final class WrappedPacketInBlockPlace extends WrappedPacket {
|
||||
static {
|
||||
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
|
||||
WrappedPacketInBlockPlace_1_9.initStatic();
|
||||
} else if (version.isLowerThan(ServerVersion.v_1_9) && version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
WrappedPacketInBlockPlace_1_8.initStatic();
|
||||
}
|
||||
}
|
||||
@@ -31,14 +29,18 @@ public final class WrappedPacketInBlockPlace extends WrappedPacket {
|
||||
ItemStack itemStack = null;
|
||||
try {
|
||||
if (version.isHigherThan(ServerVersion.v_1_8_8)) {
|
||||
final WrappedPacketInBlockPlace_1_9 updatedBlockPlace = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
|
||||
final Block block = updatedBlockPlace.getBlock();
|
||||
final WrappedPacketInBlockPlace_1_9 blockPlace_1_9 = new WrappedPacketInBlockPlace_1_9(getPlayer(), packet);
|
||||
final Block block = blockPlace_1_9.getBlock();
|
||||
position = new Vector3i(block.getX(), block.getY(), block.getZ());
|
||||
itemStack = new ItemStack(block.getType());
|
||||
} else if (version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
final WrappedPacketInBlockPlace_1_8 blockPlace_1_8 = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
position = blockPlace_1_8.getBlockPosition();
|
||||
itemStack = blockPlace_1_8.getItemStack();
|
||||
} else {
|
||||
final WrappedPacketInBlockPlace_1_8 legacyBlockPlace = new WrappedPacketInBlockPlace_1_8(packet);
|
||||
position = legacyBlockPlace.getBlockPosition();
|
||||
itemStack = legacyBlockPlace.getItemStack();
|
||||
final WrappedPacketInBlockPlace_1_7_10 blockPlace_1_7_10 = new WrappedPacketInBlockPlace_1_7_10(getPlayer(), packet);
|
||||
position = blockPlace_1_7_10.getBlockPosition();
|
||||
this.itemStack = blockPlace_1_7_10.getItemStack();
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
+15
-17
@@ -1,15 +1,15 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import io.github.retrooper.packetevents.utils.vector.Vector3i;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
|
||||
private static final Reflection.MethodInvoker[] blockPositionXYZInvoker = new Reflection.MethodInvoker[3];
|
||||
private static Class<?> blockPlaceClass, blockPositionClass;
|
||||
private static Reflection.FieldAccessor<?> blockPositionAccessor, itemStackFieldAccessor;
|
||||
private Vector3i blockPosition;
|
||||
private ItemStack itemStack;
|
||||
|
||||
@@ -25,27 +25,25 @@ final class WrappedPacketInBlockPlace_1_8 extends WrappedPacket {
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
itemStackFieldAccessor = Reflection.getField(blockPlaceClass, NMSUtils.nmsItemStackClass, 0);
|
||||
|
||||
blockPositionAccessor = Reflection.getField(blockPlaceClass, blockPositionClass, 1);
|
||||
|
||||
blockPositionXYZInvoker[0] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getX");
|
||||
blockPositionXYZInvoker[1] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getY");
|
||||
blockPositionXYZInvoker[2] = Reflection.getMethod(blockPositionClass.getSuperclass(), "getZ");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
Object nmsBlockPos = blockPositionAccessor.get(packet);
|
||||
try {
|
||||
Object nmsBlockPos = Reflection.getField(blockPlaceClass, blockPositionClass, 1).get(packet);
|
||||
|
||||
int x = (int) blockPositionXYZInvoker[0].invoke(nmsBlockPos);
|
||||
int y = (int) blockPositionXYZInvoker[1].invoke(nmsBlockPos);
|
||||
int z = (int) blockPositionXYZInvoker[2].invoke(nmsBlockPos);
|
||||
final int[] coords = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
final String s = "get" + (i == 0 ? "X" : i == 1 ? "Y" : "Z");
|
||||
coords[i] = (int) Reflection.getMethod(blockPositionClass.getSuperclass(), s, 0).invoke(nmsBlockPos);
|
||||
}
|
||||
|
||||
this.blockPosition = new Vector3i(x, y, z);
|
||||
this.blockPosition = new Vector3i(coords[0], coords[1], coords[2]);
|
||||
|
||||
this.itemStack = NMSUtils.toBukkitItemStack(itemStackFieldAccessor.get(packet));
|
||||
this.itemStack = NMSUtils.toBukkitItemStack(Reflection.getField(blockPlaceClass, NMSUtils.nmsItemStackClass, 0).get(packet));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3i getBlockPosition() {
|
||||
|
||||
+2
-14
@@ -2,33 +2,21 @@ package io.github.retrooper.packetevents.packetwrappers.in.blockplace;
|
||||
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.Material;
|
||||
import io.github.retrooper.packetevents.utils.BlockIteratorUtils;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
final class WrappedPacketInBlockPlace_1_9 extends WrappedPacket {
|
||||
private static Class<?> blockPlaceClass_1_9;
|
||||
private Block block;
|
||||
|
||||
public WrappedPacketInBlockPlace_1_9(final Player player, final Object packet) {
|
||||
super(player, packet);
|
||||
}
|
||||
|
||||
protected static void initStatic() {
|
||||
try {
|
||||
blockPlaceClass_1_9 = NMSUtils.getNMSClass("PacketPlayInUseItem");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
this.block = getPlayer().getTargetBlock(null, 3);
|
||||
|
||||
this.block = BlockIteratorUtils.getBlockLookingAt(getPlayer(), 3);
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
|
||||
+2
-20
@@ -1,30 +1,18 @@
|
||||
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.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInChat extends WrappedPacket {
|
||||
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 String message;
|
||||
@@ -33,17 +21,11 @@ public final class WrappedPacketInChat extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
private static String getChatFieldName() {
|
||||
if (version == ServerVersion.v_1_7_10) {
|
||||
return "message";
|
||||
}
|
||||
return "a";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
final Object obj = field.get(packet);
|
||||
final Object obj = Reflection.getField(chatPacketClass, String.class, 0).get(packet);
|
||||
this.message = obj.toString();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
+29
-39
@@ -1,47 +1,34 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.entityaction;
|
||||
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.enums.PlayerAction;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.enums.minecraft.PlayerAction;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInEntityAction extends WrappedPacket {
|
||||
private static Class<?> entityActionClass;
|
||||
@Nullable
|
||||
private static Class<?> enumPlayerActionClass;
|
||||
private static final Field[] fields = new Field[3];
|
||||
@Nullable
|
||||
private static Object[] enumPlayerActionConstants;
|
||||
|
||||
static {
|
||||
try {
|
||||
entityActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction");
|
||||
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
enumPlayerActionClass = NMSUtils.getNMSClass("PacketPlayInEntityAction$EnumPlayerAction");
|
||||
for (final Class<?> sub : entityActionClass.getDeclaredClasses()) {
|
||||
if (sub.getSimpleName().equals("EnumPlayerAction")) {
|
||||
enumPlayerActionClass = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enumPlayerActionClass = NMSUtils.getNMSClass("EnumPlayerAction");
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
//ints in 1.7.10, EnumPlayerAction in 1.8+
|
||||
fields[0] = entityActionClass.getDeclaredField("a");
|
||||
fields[1] = entityActionClass.getDeclaredField("animation");
|
||||
fields[2] = entityActionClass.getDeclaredField("c");
|
||||
if (version.isHigherThan(ServerVersion.v_1_7_10)) {
|
||||
enumPlayerActionConstants = enumPlayerActionClass.getEnumConstants();
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (final Field f : fields) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private Entity entity;
|
||||
@@ -56,34 +43,37 @@ public final class WrappedPacketInEntityAction extends WrappedPacket {
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
final int entityId = fields[0].getInt(packet);
|
||||
final int jumpBoost = fields[2].getInt(packet);
|
||||
final int entityId = Reflection.getField(entityActionClass, int.class, 0).getInt(packet);
|
||||
final int jumpBoost;
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
jumpBoost = Reflection.getField(entityActionClass, int.class, 2).getInt(packet);
|
||||
} else {
|
||||
jumpBoost = Reflection.getField(entityActionClass, int.class, 1).getInt(packet);
|
||||
}
|
||||
|
||||
int animationIndex = -1;
|
||||
|
||||
//1.7.10
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
animationIndex = fields[1].getInt(packet);
|
||||
animationIndex = Reflection.getField(entityActionClass, int.class, 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;
|
||||
}
|
||||
final Object enumObj = Reflection.getField(entityActionClass, enumPlayerActionClass, 0).get(packet);
|
||||
final String enumValue = enumObj.toString();
|
||||
try {
|
||||
this.action = PlayerAction.valueOf(enumValue);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//They aren't on a legacy version and the enum has changed
|
||||
final PlayerAction.UpdatedPlayerAction updatedPlayerAction = PlayerAction.UpdatedPlayerAction.valueOf(enumValue);
|
||||
this.action = PlayerAction.get(updatedPlayerAction.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.entityId = entityId;
|
||||
this.action = action;
|
||||
this.jumpBoost = jumpBoost;
|
||||
this.action = PlayerAction.get((byte) animationIndex);
|
||||
|
||||
if (animationIndex != -1) {
|
||||
this.action = PlayerAction.get(animationIndex);
|
||||
}
|
||||
this.entity = NMSUtils.getEntityById(this.entityId);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
+58
-40
@@ -1,15 +1,12 @@
|
||||
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.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class WrappedPacketInFlying extends WrappedPacket {
|
||||
private static Class<?> flyingClass;
|
||||
private static final Field[] fields = new Field[8]; //x, y, z, yaw pitch, onGround, isPositionPacket, isLookPacket
|
||||
|
||||
static {
|
||||
|
||||
@@ -18,26 +15,6 @@ public class WrappedPacketInFlying extends WrappedPacket {
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
fields[0] = flyingClass.getDeclaredField("x");
|
||||
fields[1] = flyingClass.getDeclaredField("y");
|
||||
fields[2] = flyingClass.getDeclaredField("z");
|
||||
fields[3] = flyingClass.getDeclaredField("yaw");
|
||||
fields[4] = flyingClass.getDeclaredField("pitch");
|
||||
fields[5] = flyingClass.getDeclaredField(getOnGroundFieldName());
|
||||
fields[6] = flyingClass.getDeclaredField("hasPos");
|
||||
fields[7] = flyingClass.getDeclaredField("hasLook");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (Field f : fields) {
|
||||
if (f != null) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double x;
|
||||
@@ -53,27 +30,21 @@ public class WrappedPacketInFlying extends WrappedPacket {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
private static String getOnGroundFieldName() {
|
||||
if (version == ServerVersion.v_1_7_10) {
|
||||
return "g";
|
||||
}
|
||||
return "f";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.x = fields[0].getDouble(packet);
|
||||
this.y = fields[1].getDouble(packet);
|
||||
this.z = fields[2].getDouble(packet);
|
||||
//x, y, z, yaw pitch, onGround, isPosition, isLook
|
||||
this.x = Reflection.getField(flyingClass, double.class, 0).getDouble(packet);
|
||||
this.y = Reflection.getField(flyingClass, double.class, 1).getDouble(packet);
|
||||
this.z = Reflection.getField(flyingClass, double.class, 2).getDouble(packet);
|
||||
|
||||
this.yaw = fields[3].getFloat(packet);
|
||||
this.pitch = fields[4].getFloat(packet);
|
||||
this.yaw = Reflection.getField(flyingClass, float.class, 0).getFloat(packet);
|
||||
this.pitch = Reflection.getField(flyingClass, float.class, 1).getFloat(packet);
|
||||
|
||||
this.onGround = fields[5].getBoolean(packet);
|
||||
this.onGround = Reflection.getField(flyingClass, boolean.class, 0).getBoolean(packet);
|
||||
|
||||
this.isPosition = fields[6].getBoolean(packet);
|
||||
this.isLook = fields[7].getBoolean(packet);
|
||||
this.isPosition = Reflection.getField(flyingClass, boolean.class, 1).getBoolean(packet);
|
||||
this.isLook = Reflection.getField(flyingClass, boolean.class, 2).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -118,11 +89,21 @@ public class WrappedPacketInFlying extends WrappedPacket {
|
||||
|
||||
@Override
|
||||
public boolean isPosition() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 1).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLook() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 2).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -133,14 +114,51 @@ public class WrappedPacketInFlying extends WrappedPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLook() {
|
||||
public boolean isPosition() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 1).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLook() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 2).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class WrappedPacketInLook extends WrappedPacketInFlying {
|
||||
|
||||
public WrappedPacketInLook(Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPosition() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 1).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLook() {
|
||||
try {
|
||||
return Reflection.getField(flyingClass, boolean.class, 2).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+3
-13
@@ -2,14 +2,11 @@ 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.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
private static Class<?> keepAliveClass;
|
||||
//1.7.10->1.12.2 has int field "a", rest as long field "a"
|
||||
private static Field idField;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -17,13 +14,6 @@ public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
idField = keepAliveClass.getDeclaredField("a");
|
||||
idField.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private long id;
|
||||
@@ -36,9 +26,9 @@ public final class WrappedPacketInKeepAlive extends WrappedPacket {
|
||||
protected void setup() {
|
||||
try {
|
||||
if (version.isHigherThan(ServerVersion.v_1_12)) {
|
||||
this.id = idField.getLong(packet);
|
||||
this.id = Reflection.getField(keepAliveClass, long.class, 0).getLong(packet);
|
||||
} else {
|
||||
this.id = idField.getInt(packet);
|
||||
this.id = Reflection.getField(keepAliveClass, int.class, 0).getInt(packet);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.steervehicle;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public class WrappedPacketInSteerVehicle extends WrappedPacket {
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketPlayInSteerVehicle");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private float side, forward;
|
||||
private boolean jump, unmount;
|
||||
|
||||
public WrappedPacketInSteerVehicle(Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.side = Reflection.getField(packetClass, float.class, 0).getFloat(packet);
|
||||
this.forward = Reflection.getField(packetClass, float.class, 1).getFloat(packet);
|
||||
|
||||
this.jump = Reflection.getField(packetClass, boolean.class, 0).getBoolean(packet);
|
||||
this.unmount = Reflection.getField(packetClass, boolean.class, 1).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//Positive side value means left, negative means right
|
||||
public float getSideValue() {
|
||||
return side;
|
||||
}
|
||||
|
||||
//Positive forward value means forward, negative is backwards
|
||||
public float getForwardValue() {
|
||||
return forward;
|
||||
}
|
||||
|
||||
public boolean isJump() {
|
||||
return jump;
|
||||
}
|
||||
|
||||
public boolean isUnmount() {
|
||||
return unmount;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.transaction;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public final class WrappedPacketInTransaction extends WrappedPacket {
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketPlayInTransaction");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private int windowId;
|
||||
private short actionNumber;
|
||||
private boolean accepted;
|
||||
|
||||
public WrappedPacketInTransaction(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.windowId = Reflection.getField(packetClass, int.class, 0).getInt(packet);
|
||||
this.actionNumber = Reflection.getField(packetClass, short.class, 0).getShort(packet);
|
||||
this.accepted = Reflection.getField(packetClass, boolean.class, 0).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getWindowId() {
|
||||
return windowId;
|
||||
}
|
||||
|
||||
public short getActionNumber() {
|
||||
return actionNumber;
|
||||
}
|
||||
|
||||
public boolean isAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
}
|
||||
+13
-21
@@ -1,42 +1,34 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.in.useentity;
|
||||
|
||||
import io.github.retrooper.packetevents.enums.EntityUseAction;
|
||||
import io.github.retrooper.packetevents.enums.minecraft.EntityUseAction;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
private static Class<?> useEntityClass;
|
||||
private static Class<?> entityClass;
|
||||
private static final Field[] fields = new Field[2];
|
||||
private static Class<?> useEntityClass, entityClass, enumEntityUseActionClass;
|
||||
|
||||
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);
|
||||
enumEntityUseActionClass = NMSUtils.getNMSClass("EnumEntityUseAction");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, it is probably a subclass
|
||||
for (final Class<?> sub : useEntityClass.getDeclaredClasses()) {
|
||||
if (sub.getSimpleName().equals("EnumEntityUseAction")) {
|
||||
enumEntityUseActionClass = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int entityId;
|
||||
@@ -50,9 +42,9 @@ public final class WrappedPacketInUseEntity extends WrappedPacket {
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.entityId = fields[0].getInt(packet);
|
||||
this.entityId = Reflection.getField(useEntityClass, int.class, 0).getInt(packet);
|
||||
this.entity = NMSUtils.getEntityById(this.entityId);
|
||||
final Object useActionEnum = fields[1].get(packet);
|
||||
final Object useActionEnum = Reflection.getField(useEntityClass, enumEntityUseActionClass, 0).get(packet);
|
||||
this.action = EntityUseAction.valueOf(useActionEnum.toString());
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.login;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
|
||||
public final class WrappedPacketLoginHandshake extends WrappedPacket {
|
||||
private static Class<?> loginHandshakeClass;
|
||||
private static final FieldAccessor<?>[] fields = new FieldAccessor[3];
|
||||
|
||||
static {
|
||||
try {
|
||||
loginHandshakeClass = NMSUtils.getNMSClass("PacketHandshakingInSetProtocol");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
fields[0] = Reflection.getField(loginHandshakeClass, int.class, 0);
|
||||
fields[1] = Reflection.getField(loginHandshakeClass, String.class, 0);
|
||||
fields[2] = Reflection.getField(loginHandshakeClass, int.class, 1);
|
||||
}
|
||||
|
||||
private int protocolVersion, port;
|
||||
private String hostname;
|
||||
|
||||
public WrappedPacketLoginHandshake(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
final Object protocolVersionObj = fields[0].get(packet);
|
||||
final Object hostNameObj = fields[1].get(packet);
|
||||
final Object portObj = fields[2].get(packet);
|
||||
|
||||
this.protocolVersion = (int) protocolVersionObj;
|
||||
this.hostname = hostNameObj.toString();
|
||||
this.port = (int) portObj;
|
||||
}
|
||||
|
||||
public int getProtocolVersion() {
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.login;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public final class WrappedPacketLoginInEncryptionBegin extends WrappedPacket {
|
||||
private static final Reflection.FieldAccessor<byte[]>[] fields = new Reflection.FieldAccessor[2];
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketLoginInEncryptionBegin");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
fields[0] = Reflection.getField(packetClass, byte[].class, 0);
|
||||
fields[1] = Reflection.getField(packetClass, byte[].class, 1);
|
||||
}
|
||||
|
||||
private byte[] publicKey, verifyToken;
|
||||
|
||||
public WrappedPacketLoginInEncryptionBegin(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
this.publicKey = fields[0].get(packet);
|
||||
this.verifyToken = fields[1].get(packet);
|
||||
}
|
||||
|
||||
public byte[] getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public byte[] getVerifyToken() {
|
||||
return verifyToken;
|
||||
}
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.login;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
|
||||
public final class WrappedPacketLoginOutEncryptionBegin extends WrappedPacket {
|
||||
private static final Reflection.FieldAccessor<?>[] fields = new Reflection.FieldAccessor[3];
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketLoginOutEncryptionBegin");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
fields[0] = Reflection.getField(packetClass, String.class, 0);
|
||||
fields[1] = Reflection.getField(packetClass, PublicKey.class, 1);
|
||||
fields[2] = Reflection.getField(packetClass, byte[].class, 2);
|
||||
}
|
||||
|
||||
private String encodedString;
|
||||
private PublicKey encodedKey;
|
||||
private byte[] byteArray;
|
||||
|
||||
public WrappedPacketLoginOutEncryptionBegin(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
//string - a (encodedstring)
|
||||
//public key - b (encoded)
|
||||
//byte array - c(byte array)
|
||||
this.encodedString = fields[0].get(packet).toString();
|
||||
this.encodedKey = (PublicKey) fields[1].get(packet);
|
||||
this.byteArray = (byte[]) fields[2].get(packet);
|
||||
}
|
||||
|
||||
public String getEncodedString() {
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
public PublicKey getEncodedKey() {
|
||||
return encodedKey;
|
||||
}
|
||||
|
||||
public byte[] getByteArray() {
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.login;
|
||||
|
||||
import io.github.retrooper.packetevents.mojang.GameProfile;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public final class WrappedPacketLoginStart extends WrappedPacket {
|
||||
private static final Reflection.FieldAccessor<com.mojang.authlib.GameProfile> gameProfileAccessor;
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketLoginInStart");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
gameProfileAccessor = Reflection.getField(packetClass, com.mojang.authlib.GameProfile.class, 0);
|
||||
}
|
||||
|
||||
private GameProfile gameProfile;
|
||||
|
||||
public WrappedPacketLoginStart(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
com.mojang.authlib.GameProfile gp = gameProfileAccessor.get(packet);
|
||||
this.gameProfile = new GameProfile(gp.getId(), gp.getName());
|
||||
}
|
||||
|
||||
public GameProfile getGameProfile() {
|
||||
return gameProfile;
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.login;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
public final class WrappedPacketLoginStatusPing extends WrappedPacket {
|
||||
private static final Reflection.FieldAccessor<Long> numberAccessor;
|
||||
private static Class<?> packetClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketStatusInPing");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
numberAccessor = Reflection.getField(packetClass, long.class, 0);
|
||||
}
|
||||
|
||||
private long number;
|
||||
|
||||
public WrappedPacketLoginStatusPing(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
this.number = numberAccessor.get(packet);
|
||||
}
|
||||
|
||||
public long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.out.abilities;
|
||||
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
final class PlayerAbilitiesUtils {
|
||||
public static Class<?> playerAbilitiesClass;
|
||||
public static Constructor<?> playerAbilitiesConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
playerAbilitiesClass = NMSUtils.getNMSClass("PlayerAbilities");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
playerAbilitiesConstructor = playerAbilitiesClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getPlayerAbilities(final boolean isVulnerable, final boolean isFlying, final boolean allowFlight, final boolean canBuildInstantly,
|
||||
final float flySpeed, final float walkSpeed) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
final Object instance = playerAbilitiesConstructor.newInstance();
|
||||
Reflection.getField(playerAbilitiesClass, boolean.class, 0).setBoolean(instance, isVulnerable);
|
||||
Reflection.getField(playerAbilitiesClass, boolean.class, 1).setBoolean(instance, isFlying);
|
||||
Reflection.getField(playerAbilitiesClass, boolean.class, 2).setBoolean(instance, allowFlight);
|
||||
Reflection.getField(playerAbilitiesClass, boolean.class, 3).setBoolean(instance, canBuildInstantly);
|
||||
|
||||
Reflection.getField(playerAbilitiesClass, float.class, 0).setFloat(instance, flySpeed);
|
||||
Reflection.getField(playerAbilitiesClass, float.class, 1).setFloat(instance, walkSpeed);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.out.abilities;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutAbilities extends WrappedPacket implements Sendable {
|
||||
private static Class<?> packetClass;
|
||||
private static Constructor<?> packetConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketPlayOutAbilities");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
packetConstructor = packetClass.getConstructor(PlayerAbilitiesUtils.playerAbilitiesClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean vulnerable, flying, allowFlight, instantBuild;
|
||||
private float flySpeed, walkSpeed;
|
||||
|
||||
public WrappedPacketOutAbilities(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutAbilities(final boolean isVulnerable, final boolean isFlying, final boolean allowFlight, final boolean canBuildInstantly,
|
||||
final float flySpeed, final float walkSpeed) {
|
||||
super(null);
|
||||
this.vulnerable = isVulnerable;
|
||||
this.flying = isFlying;
|
||||
this.allowFlight = allowFlight;
|
||||
this.instantBuild = canBuildInstantly;
|
||||
this.flySpeed = flySpeed;
|
||||
this.walkSpeed = walkSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.vulnerable = Reflection.getField(packetClass, boolean.class, 0).getBoolean(packet);
|
||||
this.flying = Reflection.getField(packetClass, boolean.class, 1).getBoolean(packet);
|
||||
this.allowFlight = Reflection.getField(packetClass, boolean.class, 2).getBoolean(packet);
|
||||
this.instantBuild = Reflection.getField(packetClass, boolean.class, 3).getBoolean(packet);
|
||||
|
||||
this.flySpeed = Reflection.getField(packetClass, float.class, 0).getFloat(packet);
|
||||
this.walkSpeed = Reflection.getField(packetClass, float.class, 0).getFloat(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isVulnerable() {
|
||||
return vulnerable;
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return flying;
|
||||
}
|
||||
|
||||
public boolean isFlightAllowed() {
|
||||
return allowFlight;
|
||||
}
|
||||
|
||||
public boolean canInstantlyBuild() {
|
||||
return instantBuild;
|
||||
}
|
||||
|
||||
public float getFlySpeed() {
|
||||
return flySpeed;
|
||||
}
|
||||
|
||||
public float getWalkSpeed() {
|
||||
return walkSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
return packetConstructor.newInstance(PlayerAbilitiesUtils.getPlayerAbilities(vulnerable, flying, allowFlight, instantBuild, flySpeed, walkSpeed));
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+4
-16
@@ -1,19 +1,18 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.out.animation;
|
||||
|
||||
import io.github.retrooper.packetevents.enums.EntityAnimationType;
|
||||
import io.github.retrooper.packetevents.enums.minecraft.EntityAnimationType;
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutAnimation extends WrappedPacket implements Sendable {
|
||||
private static Class<?> animationClass, nmsEntityClass;
|
||||
private static Constructor<?> animationConstructor;
|
||||
private static final Field[] fields = new Field[2];
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -28,17 +27,6 @@ public final class WrappedPacketOutAnimation extends WrappedPacket implements Se
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
fields[0] = animationClass.getDeclaredField("a");
|
||||
fields[1] = animationClass.getDeclaredField("b");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (final Field f : fields) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Entity entity;
|
||||
@@ -61,9 +49,9 @@ public final class WrappedPacketOutAnimation extends WrappedPacket implements Se
|
||||
try {
|
||||
//a - ID
|
||||
//b - TYPE
|
||||
this.entityID = fields[0].getInt(packet);
|
||||
this.entityID = Reflection.getField(animationClass, int.class, 0).getInt(packet);
|
||||
this.entity = NMSUtils.getEntityById(this.entityID);
|
||||
this.type = EntityAnimationType.get(fields[1].getInt(packet));
|
||||
this.type = EntityAnimationType.get(Reflection.getField(animationClass, int.class, 1).getInt(packet));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
+13
-44
@@ -1,60 +1,39 @@
|
||||
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.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class WrappedPacketOutChat extends WrappedPacket implements Sendable {
|
||||
private static Constructor<?> chatClassConstructor;
|
||||
private static Class<?> chatClass, iChatBaseComponentClass, chatSerializerClass;
|
||||
private static Field iChatBaseField;
|
||||
private static Method serialize, getStringOfIChatBase;
|
||||
|
||||
static {
|
||||
try {
|
||||
chatClass = NMSUtils.getNMSClass("PacketPlayOutChat");
|
||||
iChatBaseComponentClass = NMSUtils.getNMSClass("IChatBaseComponent");
|
||||
|
||||
//In 1.8.3+ the ChatSerializer class is declared in the IChatBaseComponent class, so we have to handle tahat
|
||||
if (version.isHigherThan(ServerVersion.v_1_8)) {
|
||||
for (final Class<?> cls : iChatBaseComponentClass.getDeclaredClasses()) {
|
||||
if (cls.getSimpleName().equals("ChatSerializer")) {
|
||||
chatSerializerClass = cls;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
chatSerializerClass = NMSUtils.getNMSClass("ChatSerializer");
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//In 1.8.3+ the ChatSerializer class is declared in the IChatBaseComponent class, so we have to handle that
|
||||
try {
|
||||
chatSerializerClass = NMSUtils.getNMSClass("ChatSerializer");
|
||||
} catch (ClassNotFoundException e) {
|
||||
//That is fine, it is probably a subclass
|
||||
chatSerializerClass = Reflection.getSubClass(iChatBaseComponentClass, "ChatSerializer");
|
||||
}
|
||||
|
||||
try {
|
||||
chatClassConstructor = chatClass.getConstructor(iChatBaseComponentClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
serialize = chatSerializerClass.getMethod("a", String.class);
|
||||
getStringOfIChatBase = iChatBaseComponentClass.getMethod(getTextMethodName());
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
iChatBaseField = chatClass.getDeclaredField("a");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
iChatBaseField.setAccessible(true);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,7 +50,7 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
|
||||
public static String toStringFromIChatBaseComponent(Object obj) {
|
||||
try {
|
||||
return getStringOfIChatBase.invoke(obj).toString();
|
||||
return Reflection.getMethod(iChatBaseComponentClass, String.class, 0).invoke(obj).toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -80,30 +59,20 @@ public final class WrappedPacketOutChat extends WrappedPacket implements Sendabl
|
||||
|
||||
public static Object toIChatBaseComponent(String msg) {
|
||||
try {
|
||||
return serialize.invoke(null, msg);
|
||||
return Reflection.getMethod(chatSerializerClass, 0, String.class).invoke(null, msg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getTextMethodName() {
|
||||
//1.7.10
|
||||
if (version.isLowerThan(ServerVersion.v_1_8)) {
|
||||
return "e"; //or c
|
||||
} else {
|
||||
return "getText";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
//all fields are IChatBaseComponents, and named 'a'
|
||||
|
||||
try {
|
||||
Object iChatBaseObj = iChatBaseField.get(packet);
|
||||
final Object iChatBaseObj = Reflection.getField(chatClass, iChatBaseComponentClass, 0).get(packet);
|
||||
|
||||
Object contentString = getStringOfIChatBase.invoke(iChatBaseObj);
|
||||
final Object contentString = Reflection.getMethod(iChatBaseComponentClass, String.class, 0).invoke(iChatBaseObj);
|
||||
|
||||
this.message = contentString.toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
|
||||
+12
-30
@@ -3,17 +3,16 @@ 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.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutEntityVelocity extends WrappedPacket implements Sendable {
|
||||
private static Constructor<?> velocityConstructor, vec3dConstructor;
|
||||
private static Class<?> velocityClass, vec3dClass;
|
||||
private static final Field[] fields = new Field[4];
|
||||
|
||||
/**
|
||||
* Velocity Constructor parameter types:
|
||||
@@ -32,35 +31,18 @@ public final class WrappedPacketOutEntityVelocity extends WrappedPacket implemen
|
||||
}
|
||||
|
||||
try {
|
||||
if (version.isHigherThan(ServerVersion.v_1_13_2)) {
|
||||
velocityConstructor = velocityClass.getConstructor(int.class, double.class, double.class, double.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//That is fine, just a newer version
|
||||
try {
|
||||
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 e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private Entity entity;
|
||||
@@ -84,11 +66,11 @@ public final class WrappedPacketOutEntityVelocity extends WrappedPacket implemen
|
||||
protected void setup() {
|
||||
try {
|
||||
int i = 0;
|
||||
final int entityId = fields[0].getInt(packet);
|
||||
final int entityId = Reflection.getField(velocityClass, int.class, 0).getInt(packet);
|
||||
|
||||
final int x = fields[1].getInt(packet);
|
||||
final int y = fields[2].getInt(packet);
|
||||
final int z = fields[3].getInt(packet);
|
||||
final int x = Reflection.getField(velocityClass, int.class, 1).getInt(packet);
|
||||
final int y = Reflection.getField(velocityClass, int.class, 2).getInt(packet);
|
||||
final int z = Reflection.getField(velocityClass, int.class, 3).getInt(packet);
|
||||
|
||||
this.entityId = entityId;
|
||||
this.entity = NMSUtils.getEntityById(this.entityId);
|
||||
|
||||
+6
-4
@@ -3,14 +3,13 @@ package io.github.retrooper.packetevents.packetwrappers.out.kickdisconnect;
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.packetwrappers.out.chat.WrappedPacketOutChat;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutKickDisconnect extends WrappedPacket implements Sendable {
|
||||
private static final Reflection.FieldAccessor<?> iChatBaseComponentAccessor;
|
||||
private static Class<?> packetClass, iChatBaseComponentClass;
|
||||
private static Constructor<?> kickDisconnectConstructor;
|
||||
|
||||
@@ -27,7 +26,6 @@ public final class WrappedPacketOutKickDisconnect extends WrappedPacket implemen
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
iChatBaseComponentAccessor = Reflection.getField(packetClass, iChatBaseComponentClass, 0);
|
||||
}
|
||||
|
||||
private String kickMessage;
|
||||
@@ -43,7 +41,11 @@ public final class WrappedPacketOutKickDisconnect extends WrappedPacket implemen
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
this.kickMessage = WrappedPacketOutChat.toStringFromIChatBaseComponent(iChatBaseComponentAccessor.get(packet));
|
||||
try {
|
||||
this.kickMessage = WrappedPacketOutChat.toStringFromIChatBaseComponent(Reflection.getField(packetClass, iChatBaseComponentClass, 0).get(packet));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String getKickMessage() {
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.out.transaction;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class WrappedPacketOutTransaction extends WrappedPacket implements Sendable {
|
||||
private static Class<?> packetClass;
|
||||
private static Constructor<?> packetConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketPlayOutTransaction");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
packetConstructor = packetClass.getConstructor(int.class, short.class, boolean.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private int windowId;
|
||||
private short actionNumber;
|
||||
private boolean accepted;
|
||||
|
||||
public WrappedPacketOutTransaction(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
public WrappedPacketOutTransaction(final int windowId, final short actionNumber, final boolean accepted) {
|
||||
super(null);
|
||||
this.windowId = windowId;
|
||||
this.actionNumber = actionNumber;
|
||||
this.accepted = accepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.windowId = Reflection.getField(packetClass, int.class, 0).getInt(packet);
|
||||
this.actionNumber = Reflection.getField(packetClass, short.class, 0).getShort(packet);
|
||||
this.accepted = Reflection.getField(packetClass, boolean.class, 0).getBoolean(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getWindowId() {
|
||||
return windowId;
|
||||
}
|
||||
|
||||
public short getActionNumber() {
|
||||
return actionNumber;
|
||||
}
|
||||
|
||||
public boolean isAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
return packetConstructor.newInstance(windowId, actionNumber, accepted);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package io.github.retrooper.packetevents.packetwrappers.out.updatehealth;
|
||||
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.packetwrappers.api.WrappedPacket;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.NMSUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class WrappedPacketOutUpdateHealth extends WrappedPacket implements Sendable {
|
||||
private static Class<?> packetClass;
|
||||
private static Constructor<?> packetConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
packetClass = NMSUtils.getNMSClass("PacketPlayOutUpdateHealth");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
packetConstructor = packetClass.getConstructor(float.class, int.class, float.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private float health, foodSaturation;
|
||||
private int food;
|
||||
|
||||
public WrappedPacketOutUpdateHealth(final Object packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://wiki.vg/Protocol#Update_Health
|
||||
*
|
||||
* @param health
|
||||
* @param food
|
||||
* @param foodSaturation
|
||||
*/
|
||||
public WrappedPacketOutUpdateHealth(final float health, final int food, final float foodSaturation) {
|
||||
super(null);
|
||||
this.health = health;
|
||||
this.food = food;
|
||||
this.foodSaturation = foodSaturation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
try {
|
||||
this.health = Reflection.getField(packetClass, float.class, 0).getFloat(packet);
|
||||
this.foodSaturation = Reflection.getField(packetClass, float.class, 0).getFloat(packet);
|
||||
this.food = Reflection.getField(packetClass, int.class, 0).getInt(packet);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public float getHealth() {
|
||||
return health;
|
||||
}
|
||||
|
||||
public float getFoodSaturation() {
|
||||
return foodSaturation;
|
||||
}
|
||||
|
||||
public int getFood() {
|
||||
return food;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asNMSPacket() {
|
||||
try {
|
||||
return packetConstructor.newInstance(health, food, foodSaturation);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package io.github.retrooper.packetevents.reflectionutils;
|
||||
|
||||
|
||||
import io.github.retrooper.packetevents.reflectionutils.fielddata.FieldWithIndex;
|
||||
import io.github.retrooper.packetevents.reflectionutils.fielddata.FieldWithName;
|
||||
import io.github.retrooper.packetevents.reflectionutils.fielddata.FieldWithTypeAndIndex;
|
||||
import io.github.retrooper.packetevents.reflectionutils.methoddata.MethodWithIndexAndParams;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author retrooper
|
||||
*/
|
||||
public final class Reflection {
|
||||
private static final HashMap<Class<?>, Field[]> cachedFields = new HashMap<Class<?>, Field[]>();
|
||||
private static final HashMap<Class<?>, Method[]> cachedMethods = new HashMap<Class<?>, Method[]>();
|
||||
private static final HashMap<Class<?>, Class<?>[]> cachedSubclasses = new HashMap<Class<?>, Class<?>[]>();
|
||||
|
||||
|
||||
//FIELDS
|
||||
private static final HashMap<FieldWithName, Field> fieldWithNameHashMap = new HashMap<FieldWithName, Field>();
|
||||
private static final HashMap<FieldWithTypeAndIndex, Field> fieldWithTypeAndIndexHashMap = new HashMap<FieldWithTypeAndIndex, Field>();
|
||||
private static final HashMap<FieldWithIndex, Field> fieldWithIndexHashMap = new HashMap<FieldWithIndex, Field>();
|
||||
private static final HashMap<MethodWithIndexAndParams, Method> methodWithIndexAndParamsHashMap = new HashMap<MethodWithIndexAndParams, Method>();
|
||||
|
||||
public static Field[] getFields(final Class<?> cls) {
|
||||
if (cachedFields.containsKey(cls)) {
|
||||
return cachedFields.get(cls);
|
||||
} else {
|
||||
final Field[] fields = cls.getDeclaredFields();
|
||||
for (final Field f : fields) {
|
||||
f.setAccessible(true);
|
||||
}
|
||||
cachedFields.put(cls, fields);
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
||||
public static Field getField(final Class<?> cls, final String name) {
|
||||
final FieldWithName fwn = new FieldWithName(cls, name);
|
||||
if (!fieldWithNameHashMap.containsKey(fwn)) {
|
||||
for (final Field f : getFields(cls)) {
|
||||
if (f.getName().equals(name)) {
|
||||
fieldWithNameHashMap.put(fwn, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fieldWithNameHashMap.get(fwn);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Field getField(final Class<?> cls, final Class<?> dataType, final int index) {
|
||||
final FieldWithTypeAndIndex fwtai = new FieldWithTypeAndIndex(cls, dataType, index);
|
||||
if (!fieldWithTypeAndIndexHashMap.containsKey(fwtai)) {
|
||||
int i = 0;
|
||||
for (final Field f : getFields(cls)) {
|
||||
if (f.getType().equals(dataType)) {
|
||||
if (i++ == index) {
|
||||
fieldWithTypeAndIndexHashMap.put(fwtai, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fieldWithTypeAndIndexHashMap.get(fwtai);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Field getField(final Class<?> cls, final int index) {
|
||||
final FieldWithIndex fwi = new FieldWithIndex(cls, index);
|
||||
if (!fieldWithIndexHashMap.containsKey(fwi)) {
|
||||
int i = 0;
|
||||
for (final Field f : getFields(cls)) {
|
||||
if (index == i++) {
|
||||
fieldWithIndexHashMap.put(fwi, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fieldWithIndexHashMap.get(fwi);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//METHODS
|
||||
public static Method[] getMethods(final Class<?> cls) {
|
||||
if (cachedMethods.containsKey(cls)) {
|
||||
return cachedMethods.get(cls);
|
||||
} else {
|
||||
final Method[] methods = cls.getDeclaredMethods();
|
||||
for (final Method m : methods) {
|
||||
m.setAccessible(true);
|
||||
}
|
||||
cachedMethods.put(cls, methods);
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
|
||||
public static Method getMethod(final Class<?> cls, final int index, final Class<?>... params) {
|
||||
final MethodWithIndexAndParams mwiap = new MethodWithIndexAndParams(cls, index, params);
|
||||
if (!methodWithIndexAndParamsHashMap.containsKey(mwiap)) {
|
||||
int i = 0;
|
||||
for (final Method m : getMethods(cls)) {
|
||||
if (Arrays.equals(m.getParameterTypes(), params) && index == i++) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return methodWithIndexAndParamsHashMap.get(mwiap);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//THE REST LATER
|
||||
|
||||
public static Method getMethod(final Class<?> cls, final String name, Class<?> returning, Class<?>... params) {
|
||||
for (final Method m : getMethods(cls)) {
|
||||
if (m.getName().equals(name) && Arrays.equals(m.getParameterTypes(), params) && m.getReturnType().equals(returning)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method getMethod(final Class<?> cls, final String name, final int index) {
|
||||
int i = 0;
|
||||
for (final Method m : getMethods(cls)) {
|
||||
if (m.getName().equals(name) && index == i++) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method getMethod(final Class<?> cls, final Class<?> returning, final int index) {
|
||||
int i = 0;
|
||||
for (final Method m : getMethods(cls)) {
|
||||
if (m.getReturnType().equals(returning) && index == i++) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method getMethod(final Class<?> cls, final String name, final Class<?> returning) {
|
||||
int i = 0;
|
||||
for (final Method m : getMethods(cls)) {
|
||||
if (m.getName().equals(name) && m.getReturnType().equals(returning)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class<?>[] getSubClasses(final Class<?> cls) {
|
||||
if (cachedSubclasses.containsKey(cls)) {
|
||||
return cachedSubclasses.get(cls);
|
||||
} else {
|
||||
final Class<?>[] subclasses = cls.getDeclaredClasses();
|
||||
cachedSubclasses.put(cls, subclasses);
|
||||
return subclasses;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getSubClass(final Class<?> cls, final String name) {
|
||||
for (final Class<?> subclass : getSubClasses(cls)) {
|
||||
if (subclass.getSimpleName().equals(name)) {
|
||||
return subclass;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class<?> getSubClass(final Class<?> cls, final int index) {
|
||||
final Class<?>[] subclasses = getSubClasses(cls);
|
||||
for (int i = 0; i < index + 1; i++) {
|
||||
final Class<?> c = subclasses[i];
|
||||
if (i == index) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package io.github.retrooper.packetevents.reflectionutils.fielddata;
|
||||
|
||||
public class FieldWithIndex {
|
||||
private final Class<?> cls;
|
||||
private final int index;
|
||||
|
||||
public FieldWithIndex(Class<?> cls, int index) {
|
||||
this.cls = cls;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Class<?> getCls() {
|
||||
return cls;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package io.github.retrooper.packetevents.reflectionutils.fielddata;
|
||||
|
||||
public class FieldWithName {
|
||||
|
||||
private final Class<?> cls;
|
||||
private final String name;
|
||||
|
||||
public FieldWithName(Class<?> cls, String name) {
|
||||
this.cls = cls;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Class<?> getCls() {
|
||||
return cls;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package io.github.retrooper.packetevents.reflectionutils.fielddata;
|
||||
|
||||
public class FieldWithTypeAndIndex {
|
||||
private final Class<?> cls, type;
|
||||
private final int index;
|
||||
|
||||
public FieldWithTypeAndIndex(Class<?> cls, Class<?> type, int index) {
|
||||
this.cls = cls;
|
||||
this.type = type;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Class<?> getCls() {
|
||||
return cls;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package io.github.retrooper.packetevents.reflectionutils.methoddata;
|
||||
|
||||
public class MethodWithIndexAndParams {
|
||||
private final Class<?> cls;
|
||||
private final int index;
|
||||
private final Class<?>[] params;
|
||||
|
||||
public MethodWithIndexAndParams(Class<?> cls, int index, Class<?>[] params) {
|
||||
this.cls = cls;
|
||||
this.index = index;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Class<?> getCls() {
|
||||
return cls;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public Class<?>[] getParams() {
|
||||
return params;
|
||||
}
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
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 {
|
||||
// Deduce the net.minecraft.server.v* package
|
||||
private static final String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
|
||||
private static final String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
private static final String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", "");
|
||||
// Variable replacement
|
||||
private static final 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>
|
||||
*
|
||||
* @param lookupName - the class name with variables.
|
||||
* @return The class.
|
||||
* @see {@link #getClass()} for more information.
|
||||
*/
|
||||
public static Class<Object> getUntypedClass(String lookupName) {
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for invoking a specific constructor.
|
||||
*/
|
||||
public interface ConstructorInvoker {
|
||||
/**
|
||||
* Invoke a constructor for a specific class.
|
||||
*
|
||||
* @param arguments - the arguments to pass to the constructor.
|
||||
* @return The constructed object.
|
||||
*/
|
||||
Object invoke(Object... arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for invoking a specific method.
|
||||
*/
|
||||
public interface MethodInvoker {
|
||||
/**
|
||||
* Invoke a method on a specific target object.
|
||||
*
|
||||
* @param target - the target object, or NULL for a static method.
|
||||
* @param arguments - the arguments to pass to the method.
|
||||
* @return The return value, or NULL if is void.
|
||||
*/
|
||||
Object invoke(Object target, Object... arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for retrieving the field content.
|
||||
*
|
||||
* @param <T> - field type.
|
||||
*/
|
||||
public interface FieldAccessor<T> {
|
||||
/**
|
||||
* Retrieve the content of a field.
|
||||
*
|
||||
* @param target - the target object, or NULL for a static field.
|
||||
* @return The value of the field.
|
||||
*/
|
||||
T get(Object target);
|
||||
|
||||
/**
|
||||
* Set the content of a field.
|
||||
*
|
||||
* @param target - the target object, or NULL for a static field.
|
||||
* @param value - the new value of the field.
|
||||
*/
|
||||
void set(Object target, Object value);
|
||||
|
||||
/**
|
||||
* Determine if the given object has this field.
|
||||
*
|
||||
* @param target - the object to test.
|
||||
* @return TRUE if it does, FALSE otherwise.
|
||||
*/
|
||||
boolean hasField(Object target);
|
||||
}
|
||||
}
|
||||
@@ -1,540 +0,0 @@
|
||||
/*
|
||||
* This file is part of Hawk Anticheat.
|
||||
* Copyright (C) 2018 Hawk Development Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.tinyprotocol;
|
||||
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.impl.PacketSendEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerUninjectEvent;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection.MethodInvoker;
|
||||
import net.minecraft.util.com.google.common.collect.Lists;
|
||||
import net.minecraft.util.com.google.common.collect.MapMaker;
|
||||
import net.minecraft.util.com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.util.io.netty.channel.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a very tiny alternative to ProtocolLib.
|
||||
* <p>
|
||||
* It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)!
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
|
||||
//BROKEN: NPEs when player joins while server is starting, and using PlayerJoinEvent instead will cause NPE for protocol version lookup.
|
||||
//Protocol version number lookup method from DeprecatedLuke's version of TinyProtocol
|
||||
public abstract class TinyProtocol7 {
|
||||
private static final AtomicInteger ID = new AtomicInteger(0);
|
||||
|
||||
// Used in order to lookup a channel
|
||||
private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
|
||||
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
|
||||
private static final FieldAccessor<Object> getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
|
||||
private static final FieldAccessor<Channel> getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
|
||||
|
||||
// Looking up ServerConnection
|
||||
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
|
||||
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
|
||||
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
|
||||
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
|
||||
private static final MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
|
||||
|
||||
// Packets we have to intercept
|
||||
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
|
||||
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
|
||||
|
||||
// Speedup channel/protocol lookup
|
||||
private final Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
||||
// Channels that have already been removed
|
||||
private final Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
protected volatile boolean closed;
|
||||
protected Plugin plugin;
|
||||
private Listener listener;
|
||||
// List of network markers
|
||||
private List<Object> networkManagers;
|
||||
// Injected channel handlers
|
||||
private final List<Channel> serverChannels = Lists.newArrayList();
|
||||
private ChannelInboundHandlerAdapter serverChannelHandler;
|
||||
private ChannelInitializer<Channel> beginInitProtocol;
|
||||
private ChannelInitializer<Channel> endInitProtocol;
|
||||
// Current handler name
|
||||
private final String handlerName;
|
||||
|
||||
/**
|
||||
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
|
||||
* <p>
|
||||
* You can construct multiple instances per plugin.
|
||||
*
|
||||
* @param plugin - the plugin.
|
||||
*/
|
||||
public TinyProtocol7(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Compute handler name
|
||||
this.handlerName = getHandlerName();
|
||||
|
||||
// Prepare existing players
|
||||
registerBukkitEvents();
|
||||
|
||||
try {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Damn you, late bind
|
||||
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
plugin.getLogger().info("[TinyProtocol] Late bind injection successful.");
|
||||
}
|
||||
}.runTask(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void createServerChannelHandler() {
|
||||
// Handle connected channels
|
||||
endInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
try {
|
||||
// This can take a while, so we need to stop the main thread from interfering
|
||||
synchronized (networkManagers) {
|
||||
// Stop injecting channels
|
||||
if (!closed) {
|
||||
channel.eventLoop().submit(() -> injectChannelInternal(channel));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// This is executed before Minecraft's channel handler
|
||||
beginInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
channel.pipeline().addLast(endInitProtocol);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
serverChannelHandler = new ChannelInboundHandlerAdapter() {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel channel = (Channel) msg;
|
||||
|
||||
// Prepare to initialize ths channel
|
||||
channel.pipeline().addFirst(beginInitProtocol);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register bukkit events.
|
||||
*/
|
||||
private void registerBukkitEvents() {
|
||||
listener = new Listener() {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public final void onPlayerLogin(PlayerLoginEvent e) {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
Channel channel = getChannel(e.getPlayer());
|
||||
|
||||
// Don't inject players that have been explicitly uninjected
|
||||
if (!uninjectedChannels.contains(channel)) {
|
||||
injectPlayer(e.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public final void onPluginDisable(PluginDisableEvent e) {
|
||||
if (e.getPlugin().equals(plugin)) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerChannelHandler() {
|
||||
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
|
||||
Object serverConnection = getServerConnection.get(mcServer);
|
||||
boolean looking = true;
|
||||
|
||||
// We need to synchronize against this list
|
||||
networkManagers = (List<Object>) getNetworkMarkers.invoke(null, serverConnection);
|
||||
createServerChannelHandler();
|
||||
|
||||
// Find the correct list, or implicitly throw an exception
|
||||
for (int i = 0; looking; i++) {
|
||||
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
||||
|
||||
for (Object item : list) {
|
||||
if (!(item instanceof ChannelFuture))
|
||||
break;
|
||||
|
||||
// Channel future that contains the server connection
|
||||
Channel serverChannel = ((ChannelFuture) item).channel();
|
||||
|
||||
serverChannels.add(serverChannel);
|
||||
serverChannel.pipeline().addFirst(serverChannelHandler);
|
||||
looking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterChannelHandler() {
|
||||
if (serverChannelHandler == null)
|
||||
return;
|
||||
|
||||
for (Channel serverChannel : serverChannels) {
|
||||
final ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
|
||||
// Remove channel handler
|
||||
serverChannel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
pipeline.remove(serverChannelHandler);
|
||||
} catch (NoSuchElementException e) {
|
||||
// That's fine
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPlayers(Plugin plugin) {
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the server is starting to send a packet to a player.
|
||||
* <p>
|
||||
* Note that this is not executed on the main thread.
|
||||
*
|
||||
* @param receiver - the receiving player, NULL for early login/status packets.
|
||||
* @param channel - the channel that received the packet. Never NULL.
|
||||
* @param packet - the packet being sent.
|
||||
* @return The packet to send instead, or NULL to cancel the transmission.
|
||||
*/
|
||||
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||
final String packetName = packet.getClass().getSimpleName();
|
||||
final PacketSendEvent packetSendEvent = new PacketSendEvent(receiver, packetName, packet);
|
||||
PacketEvents.getEventManager().callEvent(packetSendEvent);
|
||||
if (!packetSendEvent.isCancelled()) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the server has received a packet from a given player.
|
||||
* <p>
|
||||
* Use {@link Channel#remoteAddress()} to get the remote address of the client.
|
||||
*
|
||||
* @param sender - the player that sent the packet, NULL for early login/status packets.
|
||||
* @param channel - channel that received the packet. Never NULL.
|
||||
* @param packet - the packet being received.
|
||||
* @return The packet to recieve instead, or NULL to cancel.
|
||||
*/
|
||||
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular player.
|
||||
* <p>
|
||||
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param player - the destination player.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Player player, Object packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular client.
|
||||
* <p>
|
||||
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Channel channel, Object packet) {
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a player.
|
||||
* <p>
|
||||
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param player - the player that sent the packet.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Player player, Object packet) {
|
||||
receivePacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a given client.
|
||||
* <p>
|
||||
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Channel channel, Object packet) {
|
||||
channel.pipeline().context("encoder").fireChannelRead(packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changed from "tiny-" to "packetevents"
|
||||
*
|
||||
* @return handlerName
|
||||
*/
|
||||
protected String getHandlerName() {
|
||||
return "packetevents-" + plugin.getName() + "-" + ID.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
* <p>
|
||||
* This will automatically be called when a player has logged in.
|
||||
*
|
||||
* @param player - the player to inject.
|
||||
*/
|
||||
public void injectPlayer(Player player) {
|
||||
final PlayerInjectEvent playerInjectEvent = new PlayerInjectEvent(player);
|
||||
PacketEvents.getEventManager().callEvent(playerInjectEvent);
|
||||
if (!playerInjectEvent.isCancelled()) {
|
||||
injectChannelInternal(getChannel(player)).player = player;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The intercepted channel, or NULL if it has already been injected.
|
||||
*/
|
||||
public void injectChannel(Channel channel) {
|
||||
injectChannelInternal(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The packet interceptor.
|
||||
*/
|
||||
private PacketInterceptor injectChannelInternal(Channel channel) {
|
||||
try {
|
||||
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
|
||||
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new PacketInterceptor();
|
||||
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
|
||||
uninjectedChannels.remove(channel);
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return (PacketInterceptor) channel.pipeline().get(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Netty channel associated with a player. This is cached.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return The Netty channel.
|
||||
*/
|
||||
public Channel getChannel(Player player) {
|
||||
Channel channel = channelLookup.get(player.getName());
|
||||
|
||||
// Lookup channel again
|
||||
if (channel == null) {
|
||||
Object connection = getConnection.get(getPlayerHandle.invoke(player));
|
||||
Object manager = getManager.get(connection);
|
||||
|
||||
channelLookup.put(player.getName(), channel = getChannel.get(manager));
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific player.
|
||||
*
|
||||
* @param player - the injected player.
|
||||
*/
|
||||
public void uninjectPlayer(Player player) {
|
||||
uninjectChannel(getChannel(player));
|
||||
PacketEvents.getEventManager().callEvent(new PlayerUninjectEvent(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific channel.
|
||||
* <p>
|
||||
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
|
||||
*
|
||||
* @param channel - the injected channel.
|
||||
*/
|
||||
public void uninjectChannel(final Channel channel) {
|
||||
// No need to guard against this if we're closing
|
||||
if (!closed) {
|
||||
uninjectedChannels.add(channel);
|
||||
}
|
||||
|
||||
// See ChannelInjector in ProtocolLib, line 590
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(handlerName);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given player has been injected by TinyProtocol.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Player player) {
|
||||
return hasInjected(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given channel has been injected by TinyProtocol.
|
||||
*
|
||||
* @param channel - the channel.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Channel channel) {
|
||||
return channel.pipeline().get(handlerName) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cease listening for packets. This is called automatically when your plugin is disabled.
|
||||
*/
|
||||
public final void close() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
|
||||
// Remove our handlers
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
uninjectPlayer(player);
|
||||
}
|
||||
|
||||
// Clean up Bukkit
|
||||
HandlerList.unregisterAll(listener);
|
||||
unregisterChannelHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
private final class PacketInterceptor extends ChannelDuplexHandler {
|
||||
// Updated by the login event
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
// Intercept channel
|
||||
final Channel channel = ctx.channel();
|
||||
handleLoginStart(channel, msg);
|
||||
|
||||
try {
|
||||
msg = onPacketInAsync(player, channel, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
msg = onPacketOutAsync(player, ctx.channel(), msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginStart(Channel channel, Object packet) {
|
||||
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
|
||||
GameProfile profile = getGameProfile.get(packet);
|
||||
channelLookup.put(profile.getName(), channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,545 +0,0 @@
|
||||
/*
|
||||
* This file is part of Hawk Anticheat.
|
||||
* Copyright (C) 2018 Hawk Development Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.tinyprotocol;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.github.retrooper.packetevents.PacketEvents;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerInjectEvent;
|
||||
import io.github.retrooper.packetevents.event.impl.PlayerUninjectEvent;
|
||||
import io.github.retrooper.packetevents.handler.TinyProtocolHandler_1_8;
|
||||
import io.github.retrooper.packetevents.tinyprotocol.Reflection.FieldAccessor;
|
||||
import io.netty.channel.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Represents a very tiny alternative to ProtocolLib.
|
||||
* <p>
|
||||
* It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)!
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
|
||||
//BROKEN: NPEs when player joins while server is starting, and using PlayerJoinEvent instead will cause NPE for protocol version lookup.
|
||||
//Protocol version number lookup method from DeprecatedLuke's version of TinyProtocol
|
||||
public abstract class TinyProtocol8 {
|
||||
private static final AtomicInteger ID = new AtomicInteger(0);
|
||||
|
||||
// Used in order to lookup a channel
|
||||
private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
|
||||
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
|
||||
private static final FieldAccessor<Object> getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
|
||||
private static final FieldAccessor<Channel> getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
|
||||
|
||||
// Looking up ServerConnection
|
||||
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
|
||||
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
|
||||
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
|
||||
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
|
||||
|
||||
// Packets we have to intercept
|
||||
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
|
||||
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
|
||||
|
||||
// Speedup channel/protocol lookup
|
||||
private final Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
||||
// Channels that have already been removed
|
||||
private final Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
// Injected channel handlers
|
||||
private final List<Channel> serverChannels = Lists.newArrayList();
|
||||
protected volatile boolean closed;
|
||||
protected Plugin plugin;
|
||||
private Listener listener;
|
||||
// List of network markers
|
||||
private List<Object> networkManagers;
|
||||
private ChannelInboundHandlerAdapter serverChannelHandler;
|
||||
private ChannelInitializer<Channel> beginInitProtocol;
|
||||
private ChannelInitializer<Channel> endInitProtocol;
|
||||
// Current handler name
|
||||
private final String handlerName;
|
||||
|
||||
/**
|
||||
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
|
||||
* <p>
|
||||
* You can construct multiple instances per plugin.
|
||||
*
|
||||
* @param plugin - the plugin.
|
||||
*/
|
||||
public TinyProtocol8(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Compute handler name
|
||||
this.handlerName = getHandlerName();
|
||||
|
||||
// Prepare existing players
|
||||
registerBukkitEvents();
|
||||
|
||||
try {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
} catch (IllegalArgumentException | NoSuchFieldException | IllegalAccessException ex) {
|
||||
// Damn you, late bind
|
||||
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
registerChannelHandler();
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
registerPlayers(plugin);
|
||||
plugin.getLogger().info("[TinyProtocol] Late bind injection successful.");
|
||||
}
|
||||
}.runTask(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void createServerChannelHandler() {
|
||||
// Handle connected channels
|
||||
endInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
try {
|
||||
// This can take a while, so we need to stop the main thread from interfering
|
||||
synchronized (networkManagers) {
|
||||
// Stop injecting channels
|
||||
if (!closed) {
|
||||
channel.eventLoop().submit(() -> injectChannelInternal(channel));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// This is executed before Minecraft's channel handler
|
||||
beginInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
channel.pipeline().addLast(endInitProtocol);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
serverChannelHandler = new ChannelInboundHandlerAdapter() {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel channel = (Channel) msg;
|
||||
|
||||
// Prepare to initialize ths channel
|
||||
channel.pipeline().addFirst(beginInitProtocol);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register bukkit events.
|
||||
*/
|
||||
private void registerBukkitEvents() {
|
||||
listener = new Listener() {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public final void onPlayerLogin(PlayerLoginEvent e) {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
Channel channel = getChannel(e.getPlayer());
|
||||
|
||||
// Don't inject players that have been explicitly uninjected
|
||||
if (!uninjectedChannels.contains(channel)) {
|
||||
injectPlayer(e.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public final void onPluginDisable(PluginDisableEvent e) {
|
||||
if (e.getPlugin().equals(plugin)) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function modified by Retrooper
|
||||
*
|
||||
* @throws NoSuchFieldException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerChannelHandler() throws NoSuchFieldException, IllegalAccessException {
|
||||
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
|
||||
Object serverConnection = getServerConnection.get(mcServer);
|
||||
boolean looking = true;
|
||||
|
||||
/*
|
||||
* I am doing this so we can support 1.8->1.15.2, the previous method TinyProtocol used wasn't supported on some versions
|
||||
* like 1.15.2
|
||||
*/
|
||||
final Field networkManagersField = serverConnection.getClass().getDeclaredField(TinyProtocolHandler_1_8.getNetworkManagersFieldName());
|
||||
networkManagersField.setAccessible(true);
|
||||
networkManagers = (List<Object>) networkManagersField.get(serverConnection);
|
||||
createServerChannelHandler();
|
||||
|
||||
// Find the correct list, or implicitly throw an exception
|
||||
for (int i = 0; looking; i++) {
|
||||
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
||||
for (Object item : list) {
|
||||
if (!(item instanceof ChannelFuture))
|
||||
break;
|
||||
|
||||
// Channel future that contains the server connection
|
||||
Channel serverChannel = ((ChannelFuture) item).channel();
|
||||
|
||||
serverChannels.add(serverChannel);
|
||||
serverChannel.pipeline().addFirst(serverChannelHandler);
|
||||
looking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterChannelHandler() {
|
||||
if (serverChannelHandler == null)
|
||||
return;
|
||||
|
||||
for (Channel serverChannel : serverChannels) {
|
||||
final ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
|
||||
// Remove channel handler
|
||||
serverChannel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
pipeline.remove(serverChannelHandler);
|
||||
} catch (NoSuchElementException e) {
|
||||
// That's fine
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPlayers(Plugin plugin) {
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the server is starting to send a packet to a player.
|
||||
* <p>
|
||||
* Note that this is not executed on the main thread.
|
||||
*
|
||||
* @param receiver - the receiving player, NULL for early login/status packets.
|
||||
* @param channel - the channel that received the packet. Never NULL.
|
||||
* @param packet - the packet being sent.
|
||||
* @return The packet to send instead, or NULL to cancel the transmission.
|
||||
*/
|
||||
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the server has received a packet from a given player.
|
||||
* <p>
|
||||
* Use {@link Channel#remoteAddress()} to get the remote address of the client.
|
||||
*
|
||||
* @param sender - the player that sent the packet, NULL for early login/status packets.
|
||||
* @param channel - channel that received the packet. Never NULL.
|
||||
* @param packet - the packet being received.
|
||||
* @return The packet to recieve instead, or NULL to cancel.
|
||||
*/
|
||||
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular player.
|
||||
* <p>
|
||||
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param player - the destination player.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Player player, Object packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular client.
|
||||
* <p>
|
||||
* Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Channel channel, Object packet) {
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a player.
|
||||
* <p>
|
||||
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param player - the player that sent the packet.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Player player, Object packet) {
|
||||
receivePacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a given client.
|
||||
* <p>
|
||||
* Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Channel channel, Object packet) {
|
||||
channel.pipeline().context("encoder").fireChannelRead(packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changed from "tiny-" to "packetevents"
|
||||
*
|
||||
* @return handlerName
|
||||
*/
|
||||
protected String getHandlerName() {
|
||||
return "packetevents-" + plugin.getName() + "-" + ID.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
* <p>
|
||||
* This will automatically be called when a player has logged in.
|
||||
*
|
||||
* @param player - the player to inject.
|
||||
*/
|
||||
public void injectPlayer(Player player) {
|
||||
final PlayerInjectEvent playerInjectEvent = new PlayerInjectEvent(player);
|
||||
PacketEvents.getEventManager().callEvent(playerInjectEvent);
|
||||
if (!playerInjectEvent.isCancelled()) {
|
||||
injectChannelInternal(getChannel(player)).player = player;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The intercepted channel, or NULL if it has already been injected.
|
||||
*/
|
||||
public void injectChannel(Channel channel) {
|
||||
injectChannelInternal(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The packet interceptor.
|
||||
*/
|
||||
private PacketInterceptor injectChannelInternal(Channel channel) {
|
||||
try {
|
||||
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
|
||||
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new PacketInterceptor();
|
||||
channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
|
||||
uninjectedChannels.remove(channel);
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return (PacketInterceptor) channel.pipeline().get(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Netty channel associated with a player. This is cached.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return The Netty channel.
|
||||
*/
|
||||
public Channel getChannel(Player player) {
|
||||
Channel channel = channelLookup.get(player.getName());
|
||||
|
||||
// Lookup channel again
|
||||
if (channel == null) {
|
||||
Object connection = getConnection.get(getPlayerHandle.invoke(player));
|
||||
Object manager = getManager.get(connection);
|
||||
|
||||
channelLookup.put(player.getName(), channel = getChannel.get(manager));
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific player.
|
||||
*
|
||||
* @param player - the injected player.
|
||||
*/
|
||||
public void uninjectPlayer(Player player) {
|
||||
uninjectChannel(getChannel(player));
|
||||
PacketEvents.getEventManager().callEvent(new PlayerUninjectEvent(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific channel.
|
||||
* <p>
|
||||
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
|
||||
*
|
||||
* @param channel - the injected channel.
|
||||
*/
|
||||
public void uninjectChannel(final Channel channel) {
|
||||
// No need to guard against this if we're closing
|
||||
if (!closed) {
|
||||
uninjectedChannels.add(channel);
|
||||
}
|
||||
|
||||
// See ChannelInjector in ProtocolLib, line 590
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(handlerName);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given player has been injected by TinyProtocol.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Player player) {
|
||||
return hasInjected(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given channel has been injected by TinyProtocol.
|
||||
*
|
||||
* @param channel - the channel.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Channel channel) {
|
||||
return channel.pipeline().get(handlerName) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cease listening for packets. This is called automatically when your plugin is disabled.
|
||||
*/
|
||||
public final void close() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
|
||||
// Remove our handlers
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
uninjectPlayer(player);
|
||||
}
|
||||
|
||||
// Clean up Bukkit
|
||||
HandlerList.unregisterAll(listener);
|
||||
unregisterChannelHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
private final class PacketInterceptor extends ChannelDuplexHandler {
|
||||
// Updated by the login event
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
// Intercept channel
|
||||
final Channel channel = ctx.channel();
|
||||
handleLoginStart(channel, msg);
|
||||
|
||||
try {
|
||||
msg = onPacketInAsync(player, channel, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
msg = onPacketOutAsync(player, ctx.channel(), msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginStart(Channel channel, Object packet) {
|
||||
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
|
||||
GameProfile profile = getGameProfile.get(packet);
|
||||
channelLookup.put(profile.getName(), channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.github.retrooper.packetevents.utils;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
|
||||
public class BlockIteratorUtils {
|
||||
public static Block getBlockLookingAt(final Player player, final int distance) {
|
||||
final Location location = player.getEyeLocation();
|
||||
final BlockIterator blocksToAdd = new BlockIterator(location, 0.0D, distance);
|
||||
Block block = null;
|
||||
while (blocksToAdd.hasNext()) {
|
||||
block = blocksToAdd.next();
|
||||
}
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package io.github.retrooper.packetevents.utils;
|
||||
import io.github.retrooper.packetevents.annotations.Nullable;
|
||||
import io.github.retrooper.packetevents.enums.ServerVersion;
|
||||
import io.github.retrooper.packetevents.packetwrappers.Sendable;
|
||||
import io.github.retrooper.packetevents.reflectionutils.Reflection;
|
||||
import io.github.retrooper.packetevents.utils.nms_entityfinder.EntityFinderUtils;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -15,21 +16,19 @@ import java.lang.reflect.Method;
|
||||
|
||||
public final class NMSUtils {
|
||||
private static final ServerVersion version = ServerVersion.getVersion();
|
||||
|
||||
|
||||
public static final String nettyPrefix = version.isLowerThan(ServerVersion.v_1_8) ? "net.minecraft.util.io.netty" : "io.netty";
|
||||
private static final String nmsDir = ServerVersion.getNMSDirectory();
|
||||
private static final String obcDir = ServerVersion.getOBCDirectory();
|
||||
|
||||
public static Class<?> minecraftServerClass, craftWorldsClass,
|
||||
packetClass, entityPlayerClass, playerConnectionClass, craftPlayerClass, serverConnectionClass, craftEntityClass, craftItemStack, nmsItemStackClass;
|
||||
|
||||
packetClass, entityPlayerClass, playerConnectionClass,
|
||||
craftPlayerClass, serverConnectionClass, craftEntityClass,
|
||||
craftItemStack, nmsItemStackClass, networkManagerClass, nettyChannelClass;
|
||||
private static Method getServerMethod, getCraftWorldHandleMethod, getServerConnection, getCraftPlayerHandle, getCraftEntityHandle, sendPacketMethod, asBukkitCopy;
|
||||
|
||||
private static Field recentTPSField, entityPlayerPingField, playerConnectionField;
|
||||
|
||||
static {
|
||||
try {
|
||||
nettyChannelClass = getNettyClass("channel.Channel");
|
||||
minecraftServerClass = getNMSClass("MinecraftServer");
|
||||
craftWorldsClass = getOBCClass("CraftWorld");
|
||||
craftPlayerClass = getOBCClass("entity.CraftPlayer");
|
||||
@@ -40,6 +39,7 @@ public final class NMSUtils {
|
||||
craftEntityClass = getOBCClass("entity.CraftEntity");
|
||||
craftItemStack = getOBCClass("inventory.CraftItemStack");
|
||||
nmsItemStackClass = getNMSClass("ItemStack");
|
||||
networkManagerClass = getNMSClass("NetworkManager");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -65,8 +65,6 @@ public final class NMSUtils {
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static Object getMinecraftServerInstance() throws InvocationTargetException, IllegalAccessException {
|
||||
@@ -83,6 +81,15 @@ public final class NMSUtils {
|
||||
return Class.forName(nmsDir + "." + name);
|
||||
}
|
||||
|
||||
public static Class<?> getNMSClassWithoutException(String name) {
|
||||
try {
|
||||
return getNMSClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<?> getOBCClass(String name) throws ClassNotFoundException {
|
||||
return Class.forName(obcDir + "." + name);
|
||||
}
|
||||
@@ -124,16 +131,42 @@ public final class NMSUtils {
|
||||
}
|
||||
|
||||
public static Object getEntityPlayer(final Player player) {
|
||||
final Object craftPlayer = getCraftPlayer(player);
|
||||
Object entityPlayer = null;
|
||||
try {
|
||||
return getCraftPlayerHandle.invoke(craftPlayer);
|
||||
return getCraftPlayerHandle.invoke(getCraftPlayer(player));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getPlayerConnection(final Player player) {
|
||||
try {
|
||||
return playerConnectionField.get(getEntityPlayer(player));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getNetworkManager(final Player player) {
|
||||
try {
|
||||
return Reflection.getField(playerConnectionClass, networkManagerClass, 0).get(getPlayerConnection(player));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getChannel(final Player player) {
|
||||
try {
|
||||
return Reflection.getField(networkManagerClass, nettyChannelClass, 0).get(getNetworkManager(player));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getPlayerPing(final Player player) {
|
||||
Object entityPlayer = getEntityPlayer(player);
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
class ProtocolLibAPIAccessor {
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ProtocolLibUtils {
|
||||
public static boolean isAvailable() {
|
||||
return Bukkit.getPluginManager().isPluginEnabled("ProtocolLib");
|
||||
}
|
||||
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return ProtocolLibAPIAccessor.getProtocolVersion(player);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import protocolsupport.api.ProtocolSupportAPI;
|
||||
|
||||
class ProtocolSupportAPIAccessor {
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return ProtocolSupportAPI.getProtocolVersion(player).getId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ProtocolSupportUtils {
|
||||
public static boolean isAvailable() {
|
||||
return Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
|
||||
}
|
||||
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return ProtocolSupportAPIAccessor.getProtocolVersion(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class VersionLookupUtils {
|
||||
/**
|
||||
* If ViaVersion is present, we get the protocol version with the ViaVersion API.
|
||||
* If ProtocolSupport is present, we get the protocol version with the ProtocolSupport API.
|
||||
* If ProtocolLib is present, we get the protocol version with the ProtocolLib API.
|
||||
* Otherwise return -1
|
||||
*
|
||||
* @param player
|
||||
* @return protocol version of the player if ViaVersion or ProtocolSupport or ProtocolLib is present. Otherwise -1
|
||||
*/
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
if (ViaUtils.isAvailable()) {
|
||||
return ViaUtils.getProtocolVersion(player);
|
||||
} else if (ProtocolSupportUtils.isAvailable()) {
|
||||
return ProtocolSupportUtils.getProtocolVersion(player);
|
||||
} else if (ProtocolLibUtils.isAvailable()) {
|
||||
return ProtocolLibUtils.getProtocolVersion(player);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
class ViaAPIAccessor {
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return getProtocolVersion(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static int getProtocolVersion(final UUID uuid) {
|
||||
return Via.getAPI().getPlayerVersion(uuid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.github.retrooper.packetevents.utils.api;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public class ViaUtils {
|
||||
public static int getProtocolVersion(final Player player) {
|
||||
return ViaAPIAccessor.getProtocolVersion(player);
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.lang.reflect.Method;
|
||||
|
||||
public final class EntityFinderUtils {
|
||||
@Nullable
|
||||
private static final ServerVersion version = PacketEvents.getServerVersion();
|
||||
private static final ServerVersion version = PacketEvents.getAPI().getServerUtilities().getServerVersion();
|
||||
private static Class<?> worldServerClass;
|
||||
private static Class<?> craftWorldClass;
|
||||
private static Class<?> entityClass;
|
||||
|
||||
Reference in new issue
Block a user