Compare commits

...
40 Commits
Author SHA1 Message Date
Dan Mulloy e2f949c3a7 Update version to 4.5.0 for release 2019-12-24 15:00:28 -05:00
Dan Mulloy c3c59337ff Update to 1.15.1 2019-12-24 14:57:15 -05:00
Dan Mulloy fdf315ba7d Update URLs to HTTPS
Finally got around to it on my ci and nexus
2019-12-24 14:23:05 -05:00
Dan Mulloy f46bd56e8f Fix name of deprecated BED packet
Might fix compatibility with 1.8
2019-12-17 19:42:31 -05:00
Dan Mulloy b1efed0c0c Fix get entity by ID with Citizens and HD
Fixes #729
Addresses filoghost/HolographicDisplays#135
2019-12-17 19:41:53 -05:00
MiniDigger 524fb1ba68 Support multiple EntityTrackerEntryImpls, fixes #732 (#733) 2019-12-16 12:32:26 -05:00
Dan Mulloy 3ff2ccf1b3 Add build number back to version, update maven plugins 2019-12-15 14:50:39 -05:00
Dan Mulloy e915fd0f9a Fix player action enum compatibility with 1.14 and below 2019-12-15 14:50:02 -05:00
Dan Mulloy 6f8b2377b1 Fix last wrapped exception
Fixes #711
2019-12-14 16:54:18 -05:00
Dan Mulloy c893a3f11e Fix player action enum in 1.15 2019-12-13 18:57:21 -05:00
Dan Mulloy 73c71e0198 Update to Minecraft 1.15 2019-12-13 16:19:40 -05:00
Dan Mulloy bb305fdaad Remove legacy packet id 2019-12-11 21:37:21 -05:00
Dan Mulloy b4d4eb29af Fix error filtering reports
Fixes #718
2019-12-05 17:02:16 -05:00
Dan Mulloy 6d9fe45fb4 Tested with 1.14.4 2019-12-05 16:49:22 -05:00
Dan Mulloy b292c8485b Disable strict JavaDoc checking 2019-12-05 16:48:56 -05:00
Dan Mulloy 1e4da2c93b Update issue templates 2019-11-13 12:12:03 -05:00
Dan Mulloy 84e31d032b Fix villager data breaking versions below 1.14 2019-10-30 12:02:15 -04:00
Dan Mulloy 59c8c8c9db Fix WrappedBlockData deep clone
Fixes #661
Fixes #662
2019-10-29 17:01:15 -04:00
Dan Mulloy a76ceb94cc Add modifier for EntityTypes
Fixes #710
2019-10-29 16:52:30 -04:00
Dan Mulloy 9a108af219 Update dependency info in readme 2019-10-24 09:57:58 -04:00
Dan Mulloy 2f09dec1c5 Move back to Maven
Didn't really gain anything from Gradle but it broke some stuff
2019-10-23 19:17:37 -04:00
Felix Klauke 4c43f125f9 Use gradle wrapper instead of travis ci's inbuilt gradle version. (#706)
At the moment travis will always use its pre installed gradle version what leads to unpredictable build behaviour as the version can change at any time. As this project has already defined a gradle wrapper the CI should use it.
2019-10-16 12:07:07 -04:00
Dan Mulloy b5cff49358 Update issue templates 2019-10-01 17:28:36 -04:00
Dan Mulloy 446a1c8326 Clone OptionalInts too 2019-08-07 11:38:50 -04:00
Dan Mulloy 8c20d19339 Try to fix a null pointer
Addresses #665
2019-08-07 11:34:59 -04:00
Dan Mulloy 9dfffe5366 Move Travis to openjdk8
Something about Oracle and licenses. Who woulda thought
2019-08-03 13:10:20 -04:00
Dan Mulloy 19dd81ce94 Fix EntityUtilities updateEntity on 1.14
Fixes #651
2019-08-03 13:03:16 -04:00
Dan Mulloy dd9eac3d6d Add wrapper for villager data
Fixes #637
2019-08-03 12:35:58 -04:00
Dan Mulloy 916434251d Add support for long array nbt type
Fixes #648
2019-08-03 11:46:58 -04:00
Dan Mulloy 62e8d82e16 Update to 1.14.4, add BLOCK_BREAK packet
Also called Acknowledge Player Digging, but we go by what Spigot calls it
2019-08-03 11:41:55 -04:00
BuildTools d7be712959 Add api-version, tweak version pattern to support pre releases
Fixes #638
Fixes #636
Fixes #626
2019-06-23 15:28:40 +02:00
Dan Mulloy 490b1dadcb Fix logger debug when testing 2019-05-07 23:11:05 -04:00
Dan Mulloy 502c5960e3 Fix join/quit exceptions when wrappers break 2019-05-07 22:58:59 -04:00
Dan Mulloy d297e373b4 Specifically clone Spigot's chat components to fix stack overflow
Addresses #601
2019-05-06 20:32:20 -04:00
Dan Mulloy 9f5d95f617 Hopefully fix chat cloning issues
Addresses #601
2019-05-06 16:20:19 -04:00
Dan Mulloy b14b4cc345 Fix entity tracking in 1.14
Fixes #600
2019-05-04 22:41:32 -04:00
Dan Mulloy e41bb8753b Backport some fixes, fix version in plugin yml
Still need to get automatic filtering fixed
2019-05-04 01:45:41 -04:00
Dan Mulloy 565f169e94 Update to Minecraft 1.14 2019-05-03 23:22:44 -04:00
Dan Mulloy 7b7449ee15 Migrate to Gradle with a single module 2018-09-22 17:48:06 -04:00
Dan Mulloy 95bb026fa9 Update parent pom version
Can't wait to move to gradle with just one build file
2018-09-22 17:27:53 -04:00
336 changed files with 2991 additions and 2187 deletions

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
---
name: API question
about: Questions related to using ProtocolLib in your plugins
title: ''
labels: ''
assignees: ''
---
**Make sure you're doing the following**
- [ ] You're using the latest build for your server version
- [ ] This isn't an issue caused by another plugin
- [ ] You've checked for duplicate issues
- [ ] You didn't use `/reload`
**Describe the question**
A clear and concise description of what your question is.
**API method(s) used**
List what API method(s) you're using
**Expected behavior**
A clear and concise description of what you expected to happen.
**Code**
If applicable, add relevant code from your project
**Additional context**
Add any other context about the problem here.
+30
View File
@@ -0,0 +1,30 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Version Info**
Provide your ProtocolLib install info with `/protocol dump` through pastebin.
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+4
View File
@@ -175,4 +175,8 @@ pip-log.txt
.DS_Store
# Log4J files
logs/
.gradle/
build/
logs/
+2 -3
View File
@@ -1,12 +1,11 @@
language: java
jdk:
- oraclejdk8
- openjdk8
script: mvn clean test
#before_install: cd ProtocolLib
install: true
notifications:
email:
recipients:
- "dmulloy2@live.com"
on_success: change
on_failure: always
on_failure: always
+169 -169
View File
@@ -1,169 +1,169 @@
# ProtocolLib [![Travis Status](https://travis-ci.org/dmulloy2/ProtocolLib.svg?branch=master)](https://travis-ci.org/dmulloy2/ProtocolLib)
Certain tasks are impossible to perform with the standard Bukkit API, and may require
working with and even modify Minecraft directly. A common technique is to modify incoming
and outgoing [packets](http://www.wiki.vg/Protocol), or inject custom packets into the
stream. This is quite cumbersome to do, however, and most implementations will break
as soon as a new version of Minecraft has been released, mostly due to obfuscation.
Critically, different plugins that use this approach may _hook_ into the same classes,
with unpredictable outcomes. More than often this causes plugins to crash, but it may also
lead to more subtle bugs.
Currently maintained by dmulloy2 on behalf of [Spigot](http://www.spigotmc.org/).
### Resources
* [Resource Page](http://www.spigotmc.org/resources/protocollib.1997/)
* [Dev Builds](http://ci.dmulloy2.net/job/ProtocolLib)
* [JavaDoc](http://ci.dmulloy2.net/job/ProtocolLib/javadoc)
### Compilation
ProtocolLib is built with Maven and requires Spigot and SpigotAPI, which can be found [here](http://www.spigotmc.org/wiki/buildtools/).
### A new API
__ProtocolLib__ attempts to solve this problem by providing a event API, much like Bukkit,
that allows plugins to monitor, modify, or cancel packets sent and received. But, more importantly,
the API also hides all the gritty, obfuscated classes with a simple index based read/write system.
You no longer have to reference CraftBukkit!
### Using ProtocolLib
To use this library, first add ProtocolLib.jar to your Java build path. Then, add ProtocolLib
as a dependency or soft dependency to your plugin.yml file like any other plugin:
````yml
depend: [ProtocolLib]
````
You can also add ProtocolLib as a Maven dependency:
````xml
<repositories>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
...
</repositories>
<dependencies>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.4.0</version>
</dependency>
</dependencies>
````
Or use the maven dependency with gradle:
```gradle
repositories {
maven { url "http://repo.dmulloy2.net/nexus/repository/public/" }
}
dependencies {
compileOnly group: "com.comphenix.protocol", name: "ProtocolLib", version: "4.4.0";
}
```
Then get a reference to ProtocolManager in onLoad() or onEnable() and you're good to go.
````java
private ProtocolManager protocolManager;
public void onLoad() {
protocolManager = ProtocolLibrary.getProtocolManager();
}
````
To listen for packets sent by the server to a client, add a server-side listener:
````java
// Disable all sound effects
protocolManager.addPacketListener(
new PacketAdapter(this, ListenerPriority.NORMAL,
PacketType.Play.Server.NAMED_SOUND_EFFECT) {
@Override
public void onPacketSending(PacketEvent event) {
// Item packets (id: 0x29)
if (event.getPacketType() ==
PacketType.Play.Server.NAMED_SOUND_EFFECT) {
event.setCancelled(true);
}
}
});
````
It's also possible to read and modify the content of these packets. For instance, you can create a global
censor by listening for Packet3Chat events:
````java
// Censor
protocolManager.addPacketListener(new PacketAdapter(this,
ListenerPriority.NORMAL,
PacketType.Play.Client.CHAT) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CHAT) {
PacketContainer packet = event.getPacket();
String message = packet.getStrings().read(0);
if (message.contains("shit")
|| message.contains("damn")) {
event.setCancelled(true);
event.getPlayer().sendMessage("Bad manners!");
}
}
}
});
````
### Sending packets
Normally, you might have to do something ugly like the following:
````java
Packet60Explosion fakeExplosion = new Packet60Explosion();
fakeExplosion.a = player.getLocation().getX();
fakeExplosion.b = player.getLocation().getY();
fakeExplosion.c = player.getLocation().getZ();
fakeExplosion.d = 3.0F;
fakeExplosion.e = new ArrayList<Object>();
((CraftPlayer) player).getHandle().netServerHandler.sendPacket(fakeExplosion);
````
But with ProtocolLib, you can turn that into something more manageable. Notice that
you don't have to create an ArrayList with this version:
````java
PacketContainer fakeExplosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
fakeExplosion.getDoubles().
write(0, player.getLocation().getX()).
write(1, player.getLocation().getY()).
write(2, player.getLocation().getZ());
fakeExplosion.getFloat().write(0, 3.0F);
try {
protocolManager.sendServerPacket(player, fakeExplosion);
} catch (InvocationTargetException e) {
throw new RuntimeException(
"Cannot send packet " + fakeExplosion, e);
}
````
### Compatibility
One of the main goals of this project was to achieve maximum compatibility with CraftBukkit. And the end
result is quite flexible. Aside from netty package changes, it should be resilient against future changes.
It's likely that I won't have to update ProtocolLib for anything but bug fixes and new features.
How is this possible? It all comes down to reflection in the end. Essentially, no name is hard coded -
every field, method and class is deduced by looking at field types, package names or parameter
types. It's remarkably consistent across different versions.
# ProtocolLib [![Travis Status](https://travis-ci.org/dmulloy2/ProtocolLib.svg?branch=master)](https://travis-ci.org/dmulloy2/ProtocolLib)
Certain tasks are impossible to perform with the standard Bukkit API, and may require
working with and even modify Minecraft directly. A common technique is to modify incoming
and outgoing [packets](https://www.wiki.vg/Protocol), or inject custom packets into the
stream. This is quite cumbersome to do, however, and most implementations will break
as soon as a new version of Minecraft has been released, mostly due to obfuscation.
Critically, different plugins that use this approach may _hook_ into the same classes,
with unpredictable outcomes. More than often this causes plugins to crash, but it may also
lead to more subtle bugs.
Currently maintained by dmulloy2 on behalf of [Spigot](https://www.spigotmc.org/).
### Resources
* [Resource Page](https://www.spigotmc.org/resources/protocollib.1997/)
* [Dev Builds](https://ci.dmulloy2.net/job/ProtocolLib)
* [JavaDoc](https://ci.dmulloy2.net/job/ProtocolLib/javadoc)
### Compilation
ProtocolLib is built with Maven and requires Spigot and SpigotAPI, which can be found [here](https://www.spigotmc.org/wiki/buildtools/).
### A new API
__ProtocolLib__ attempts to solve this problem by providing a event API, much like Bukkit,
that allows plugins to monitor, modify, or cancel packets sent and received. But, more importantly,
the API also hides all the gritty, obfuscated classes with a simple index based read/write system.
You no longer have to reference CraftBukkit!
### Using ProtocolLib
To use this library, first add ProtocolLib.jar to your Java build path. Then, add ProtocolLib
as a dependency or soft dependency to your plugin.yml file like any other plugin:
````yml
depend: [ProtocolLib]
````
You can also add ProtocolLib as a Maven dependency:
````xml
<repositories>
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
...
</repositories>
<dependencies>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.5.0</version>
</dependency>
</dependencies>
````
Or use the maven dependency with gradle:
```gradle
repositories {
maven { url "https://repo.dmulloy2.net/nexus/repository/public/" }
}
dependencies {
compileOnly group: "com.comphenix.protocol", name: "ProtocolLib", version: "4.5.0";
}
```
Then get a reference to ProtocolManager in onLoad() or onEnable() and you're good to go.
````java
private ProtocolManager protocolManager;
public void onLoad() {
protocolManager = ProtocolLibrary.getProtocolManager();
}
````
To listen for packets sent by the server to a client, add a server-side listener:
````java
// Disable all sound effects
protocolManager.addPacketListener(
new PacketAdapter(this, ListenerPriority.NORMAL,
PacketType.Play.Server.NAMED_SOUND_EFFECT) {
@Override
public void onPacketSending(PacketEvent event) {
// Item packets (id: 0x29)
if (event.getPacketType() ==
PacketType.Play.Server.NAMED_SOUND_EFFECT) {
event.setCancelled(true);
}
}
});
````
It's also possible to read and modify the content of these packets. For instance, you can create a global
censor by listening for Packet3Chat events:
````java
// Censor
protocolManager.addPacketListener(new PacketAdapter(this,
ListenerPriority.NORMAL,
PacketType.Play.Client.CHAT) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CHAT) {
PacketContainer packet = event.getPacket();
String message = packet.getStrings().read(0);
if (message.contains("shit")
|| message.contains("damn")) {
event.setCancelled(true);
event.getPlayer().sendMessage("Bad manners!");
}
}
}
});
````
### Sending packets
Normally, you might have to do something ugly like the following:
````java
Packet60Explosion fakeExplosion = new Packet60Explosion();
fakeExplosion.a = player.getLocation().getX();
fakeExplosion.b = player.getLocation().getY();
fakeExplosion.c = player.getLocation().getZ();
fakeExplosion.d = 3.0F;
fakeExplosion.e = new ArrayList<Object>();
((CraftPlayer) player).getHandle().netServerHandler.sendPacket(fakeExplosion);
````
But with ProtocolLib, you can turn that into something more manageable. Notice that
you don't have to create an ArrayList with this version:
````java
PacketContainer fakeExplosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
fakeExplosion.getDoubles().
write(0, player.getLocation().getX()).
write(1, player.getLocation().getY()).
write(2, player.getLocation().getZ());
fakeExplosion.getFloat().write(0, 3.0F);
try {
protocolManager.sendServerPacket(player, fakeExplosion);
} catch (InvocationTargetException e) {
throw new RuntimeException(
"Cannot send packet " + fakeExplosion, e);
}
````
### Compatibility
One of the main goals of this project was to achieve maximum compatibility with CraftBukkit. And the end
result is quite flexible. Aside from netty package changes, it should be resilient against future changes.
It's likely that I won't have to update ProtocolLib for anything but bug fixes and new features.
How is this possible? It all comes down to reflection in the end. Essentially, no name is hard coded -
every field, method and class is deduced by looking at field types, package names or parameter
types. It's remarkably consistent across different versions.
File renamed without changes.
-193
View File
@@ -1,193 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>ProtocolLib-API</artifactId>
<name>ProtocolLib-API</name>
<version>4.4.0</version>
<description>Provides read/write access to the Minecraft protocol.</description>
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
<packaging>jar</packaging>
<parent>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-Parent</artifactId>
<version>4.4.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.number></project.build.number>
<project.fullVersion>${project.version}</project.fullVersion>
</properties>
<build>
<defaultGoal>clean install</defaultGoal>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>com.comphenix.protocol.Application</Main-Class>
<Implementation-Title>ProtocolLib</Implementation-Title>
<Implementation-Version>${project.fullVersion}</Implementation-Version>
<Implementation-Vendor>dmulloy2</Implementation-Vendor>
</manifestEntries>
</archive>
<finalName>ProtocolLib</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<systemProperties>
<property>
<name>projectVersion</name>
<value>${project.version}</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jenkins</id>
<activation>
<property>
<name>env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<project.build.number>-b${env.BUILD_NUMBER}</project.build.number>
<project.fullVersion>${project.version}${project.build.number}</project.fullVersion>
</properties>
</profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<properties>
<project.fullVersion>${project.version}</project.fullVersion>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- TODO: Look into signing releases
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</profile>
</profiles>
<scm>
<connection>scm:git:git://github.com/dmulloy2/ProtocolLib.git</connection>
<developerConnection>scm:git:git@github.com:dmulloy2/ProtocolLib.git</developerConnection>
<url>https://github.com/dmulloy2/ProtocolLib</url>
</scm>
<licenses>
<license>
<name>GNU GENERAL PUBLIC LICENSE - Version 2, June 1991</name>
<url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>dmulloy2</id>
<name>Dan Mulloy</name>
<url>http://dmulloy2.net/</url>
<roles>
<role>developer</role>
<role>maintainer</role>
</roles>
</developer>
<developer>
<id>aadnk</id>
<name>Kristian S. Stangeland</name>
<email>kr_stang@hotmail.com</email>
<url>http://comphenix.net/</url>
<roles>
<role>former author</role>
</roles>
<timezone>1</timezone>
</developer>
</developers>
</project>
@@ -1,108 +0,0 @@
/**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2015 dmulloy2
*
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.injector.netty;
import java.util.Map;
import java.util.Map.Entry;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLogger;
import com.comphenix.protocol.PacketType.Protocol;
import com.comphenix.protocol.PacketType.Sender;
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
import com.comphenix.protocol.injector.packet.MapContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.google.common.collect.Maps;
/**
* @author dmulloy2
*/
public class NettyProtocolRegistry extends ProtocolRegistry {
public NettyProtocolRegistry() {
super();
}
@Override
protected synchronized void initialize() {
Object[] protocols = enumProtocol.getEnumConstants();
// ID to Packet class maps
Map<Object, Map<Integer, Class<?>>> serverMaps = Maps.newLinkedHashMap();
Map<Object, Map<Integer, Class<?>>> clientMaps = Maps.newLinkedHashMap();
Register result = new Register();
StructureModifier<Object> modifier = null;
// Iterate through the protocols
for (Object protocol : protocols) {
if (modifier == null)
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
StructureModifier<Map<Object, Map<Integer, Class<?>>>> maps = modifier.withTarget(protocol).withType(Map.class);
for (Entry<Object, Map<Integer, Class<?>>> entry : maps.read(0).entrySet()) {
String direction = entry.getKey().toString();
if (direction.contains("CLIENTBOUND")) { // Sent by Server
serverMaps.put(protocol, entry.getValue());
} else if (direction.contains("SERVERBOUND")) { // Sent by Client
clientMaps.put(protocol, entry.getValue());
}
}
}
// Maps we have to occasionally check have changed
for (Map<Integer, Class<?>> map : serverMaps.values()) {
result.containers.add(new MapContainer(map));
}
for (Map<Integer, Class<?>> map : clientMaps.values()) {
result.containers.add(new MapContainer(map));
}
for (Object protocol : protocols) {
Enum<?> enumProtocol = (Enum<?>) protocol;
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
// Associate known types
if (serverMaps.containsKey(protocol))
associatePackets(result, serverMaps.get(protocol), equivalent, Sender.SERVER);
if (clientMaps.containsKey(protocol))
associatePackets(result, clientMaps.get(protocol), equivalent, Sender.CLIENT);
}
// Exchange (thread safe, as we have only one writer)
this.register = result;
}
@Override
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
PacketType type = PacketType.fromCurrent(protocol, sender, entry.getKey(), entry.getValue());
try {
register.typeToClass.put(type, entry.getValue());
if (sender == Sender.SERVER)
register.serverPackets.add(type);
if (sender == Sender.CLIENT)
register.clientPackets.add(type);
} catch (Exception ex) {
ProtocolLogger.debug("Encountered an exception associating packet " + type, ex);
}
}
}
}
@@ -1,33 +0,0 @@
/**
* (c) 2018 dmulloy2
*/
package com.comphenix.protocol.reflect.cloning;
import java.util.Optional;
/**
* A cloner that can clone Java Optional objects
* @author dmulloy2
*/
public class JavaOptionalCloner implements Cloner {
protected Cloner wrapped;
public JavaOptionalCloner(Cloner wrapped) {
this.wrapped = wrapped;
}
@Override
public boolean canClone(Object source) {
return source instanceof Optional;
}
@Override
public Object clone(Object source) {
Optional<?> optional = (Optional<?>) source;
return optional.map(o -> wrapped.clone(o));
}
public Cloner getWrapped() {
return wrapped;
}
}
-265
View File
@@ -1,265 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>ProtocolLib</artifactId>
<name>ProtocolLib</name>
<version>4.4.0</version>
<description>Provides read/write access to the Minecraft protocol.</description>
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
<packaging>jar</packaging>
<parent>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-Parent</artifactId>
<version>4.4.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.number></project.build.number>
<project.fullVersion>${project.version}</project.fullVersion>
<powermock.version>1.7.4</powermock.version>
</properties>
<build>
<defaultGoal>clean install</defaultGoal>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>net.sf</pattern>
<shadedPattern>com.comphenix.net.sf</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<excludes>
<exclude>org.spigotmc:spigot</exclude>
<exclude>org.spigotmc:spigot-api</exclude>
<exclude>junit:junit</exclude>
<exclude>io.netty:*</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>com.comphenix.protocol.Application</Main-Class>
<Implementation-Title>ProtocolLib</Implementation-Title>
<Implementation-Version>${project.fullVersion}</Implementation-Version>
<Implementation-Vendor>dmulloy2</Implementation-Vendor>
</manifestEntries>
</archive>
<finalName>${project.name}</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<systemProperties>
<property>
<name>projectVersion</name>
<value>${project.version}</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jenkins</id>
<activation>
<property>
<name>env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<project.build.number>-b${env.BUILD_NUMBER}</project.build.number>
<project.fullVersion>${project.version}${project.build.number}</project.fullVersion>
</properties>
</profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<properties>
<project.fullVersion>${project.version}</project.fullVersion>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- TODO: Look into signing releases
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</profile>
</profiles>
<scm>
<connection>scm:git:git://github.com/dmulloy2/ProtocolLib.git</connection>
<developerConnection>scm:git:git@github.com:dmulloy2/ProtocolLib.git</developerConnection>
<url>https://github.com/dmulloy2/ProtocolLib</url>
</scm>
<licenses>
<license>
<name>GNU GENERAL PUBLIC LICENSE - Version 2, June 1991</name>
<url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>dmulloy2</id>
<name>Dan Mulloy</name>
<url>http://dmulloy2.net/</url>
<roles>
<role>developer</role>
<role>maintainer</role>
</roles>
</developer>
<developer>
<id>aadnk</id>
<name>Kristian S. Stangeland</name>
<email>kr_stang@hotmail.com</email>
<url>http://comphenix.net/</url>
<roles>
<role>former author</role>
</roles>
<timezone>1</timezone>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- Testing dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,256 +0,0 @@
/*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.injector;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.Validate;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.WrappedIntHashMap;
import com.google.common.collect.Lists;
/**
* Used to perform certain operations on entities.
*
* @author Kristian
*/
class EntityUtilities {
private static Field entityTrackerField;
private static Field trackedEntitiesField;
private static Field trackedPlayersField;
private static Field trackerField;
private static Method scanPlayersMethod;
/*
public static void updateEntity2(Entity entity, List<Player> observers) {
EntityTrackerEntry entry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
List<EntityPlayer> nmsPlayers = getNmsPlayers(observers);
entry.trackedPlayers.removeAll(nmsPlayers);
entry.scanPlayers(nmsPlayers);
}
*/
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
if (entity == null || !entity.isValid()) {
return;
}
try {
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
if (trackerEntry == null) {
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + ".");
}
if (trackedPlayersField == null) {
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
}
// Phew, finally there.
Collection<?> trackedPlayers = getTrackedPlayers(trackedPlayersField, trackerEntry);
List<Object> nmsPlayers = unwrapBukkit(observers);
trackedPlayers.removeAll(nmsPlayers);
// We have to rely on a NAME once again. Damn it.
// TODO: Make sure this stays up to date with version changes - 1.8 - 1.10
if (scanPlayersMethod == null) {
scanPlayersMethod = trackerEntry.getClass().getMethod("scanPlayers", List.class);
}
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
throw new FieldAccessException("Security limitation prevents access to 'get' method in IntHashMap", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Exception occurred in Minecraft.", e);
} catch (SecurityException e) {
throw new FieldAccessException("Security limitation prevents access to 'scanPlayers' method in trackerEntry.", e);
} catch (NoSuchMethodException e) {
throw new FieldAccessException("Cannot find 'scanPlayers' method. Is ProtocolLib up to date?", e);
}
}
/**
* Retrieve every client that is receiving information about a given entity.
* @param entity - the entity that is being tracked.
* @return Every client/player that is tracking the given entity.
* @throws FieldAccessException If reflection failed.
*/
public static List<Player> getEntityTrackers(Entity entity) {
if (entity == null || !entity.isValid()) {
return new ArrayList<>();
}
try {
List<Player> result = new ArrayList<Player>();
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
if (trackerEntry == null) {
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + ".");
}
if (trackedPlayersField == null) {
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
}
Collection<?> trackedPlayers = getTrackedPlayers(trackedPlayersField, trackerEntry);
// Wrap every player - we also ensure that the underlying tracker list is immutable
for (Object tracker : trackedPlayers) {
if (MinecraftReflection.isMinecraftPlayer(tracker)) {
result.add((Player) MinecraftReflection.getBukkitEntity(tracker));
}
}
return result;
} catch (IllegalAccessException e) {
throw new FieldAccessException("Security limitation prevented access to the list of tracked players.", e);
}
}
// Damn you, Paper
private static Collection<?> getTrackedPlayers(Field field, Object entry) throws IllegalAccessException {
Validate.notNull(field, "Cannot find 'trackedPlayers' field.");
Validate.notNull(entry, "entry cannot be null!");
Object value = FieldUtils.readField(field, entry, false);
if (value instanceof Collection) {
return (Collection<?>) value;
} else if (value instanceof Map) {
return ((Map<?, ?>) value).keySet();
} else {
// Please. No more changes.
throw new IllegalStateException("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value.getClass());
}
}
/*
private static EntityTrackerEntry getEntityTrackerEntry2(World world, int entityID) {
WorldServer worldServer = ((CraftWorld) world).getHandle();
EntityTracker tracker = worldServer.tracker;
return tracker.trackedEntities.get(entityID);
}
*/
private static Object getEntityTrackerEntry(World world, int entityID) throws FieldAccessException, IllegalArgumentException {
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
Object worldServer = unwrapper.unwrapItem(world);
if (entityTrackerField == null)
entityTrackerField = FuzzyReflection.fromObject(worldServer).
getFieldByType("tracker", MinecraftReflection.getEntityTrackerClass());
// Get the tracker
Object tracker = null;
try {
tracker = FieldUtils.readField(entityTrackerField, worldServer, false);
} catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot access 'tracker' field due to security limitations.", e);
}
// Looking for an IntHashMap in the tracker entry
if (trackedEntitiesField == null) {
trackedEntitiesField = FuzzyReflection.fromObject(tracker, false)
.getFieldByType("trackedEntities", MinecraftReflection.getIntHashMapClass());
}
// Read the map
Object trackedEntities = null;
try {
trackedEntities = FieldUtils.readField(trackedEntitiesField, tracker, false);
} catch (IllegalAccessException e) {
throw new FieldAccessException("Cannot access 'trackedEntities' field due to security limitations.", e);
}
return WrappedIntHashMap.fromHandle(trackedEntities).get(entityID);
}
/**
* Retrieve entity from a ID, even it it's newly created.
* @return The associated entity.
* @throws FieldAccessException Reflection error.
*/
public static Entity getEntityFromID(World world, int entityID) throws FieldAccessException {
try {
Object trackerEntry = getEntityTrackerEntry(world, entityID);
Object tracker = null;
// Handle NULL cases
if (trackerEntry != null) {
if (trackerField == null) {
try {
Class<?> entryClass = MinecraftReflection.getMinecraftClass("EntityTrackerEntry");
trackerField = entryClass.getDeclaredField("tracker");
} catch (NoSuchFieldException e) {
// Assume it's the first entity field then
trackerField = FuzzyReflection.fromObject(trackerEntry, true)
.getFieldByType("tracker", MinecraftReflection.getEntityClass());
}
}
tracker = FieldUtils.readField(trackerField, trackerEntry, true);
}
// If the tracker is NULL, we'll just assume this entity doesn't exist
if (tracker != null)
return (Entity) MinecraftReflection.getBukkitEntity(tracker);
else
return null;
} catch (Exception e) {
throw new FieldAccessException("Cannot find entity from ID " + entityID + ".", e);
}
}
private static List<Object> unwrapBukkit(List<Player> players) {
List<Object> output = Lists.newArrayList();
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
// Get the NMS equivalent
for (Player player : players) {
Object result = unwrapper.unwrapItem(player);
if (result != null)
output.add(result);
else
throw new IllegalArgumentException("Cannot unwrap item " + player);
}
return output;
}
}
@@ -1,96 +0,0 @@
/**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2016 dmulloy2
* <p>
* 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 2 of
* the License, or (at your option) any later version.
* <p>
* 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.
* <p>
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import com.comphenix.protocol.PacketType.Protocol;
import com.comphenix.protocol.PacketType.Sender;
import com.comphenix.protocol.injector.packet.PacketRegistry;
import net.minecraft.server.v1_13_R2.EnumProtocol;
import net.minecraft.server.v1_13_R2.EnumProtocolDirection;
import net.minecraft.server.v1_13_R2.PacketLoginInStart;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author dmulloy2
*/
public class PacketTypeTest {
@BeforeClass
public static void initializeReflection() {
BukkitInitialization.initializePackage();
}
@Test
public void testFindCurrent() {
assertEquals(PacketType.Play.Client.STEER_VEHICLE, PacketType.findCurrent(Protocol.PLAY, Sender.CLIENT, "SteerVehicle"));
}
@Test
public void testLoginStart() {
// This packet is critical for handleLoin
assertEquals(PacketLoginInStart.class, PacketType.Login.Client.START.getPacketClass());
}
@Test
public void testDeprecation() {
assertTrue("Packet isn't properly deprecated", PacketType.Status.Server.OUT_SERVER_INFO.isDeprecated());
assertTrue("Deprecated packet isn't properly included",
PacketRegistry.getServerPacketTypes().contains(PacketType.Status.Server.OUT_SERVER_INFO));
assertFalse("Packet isn't properly deprecated", PacketType.Play.Server.CHAT.isDeprecated());
assertEquals("Deprecated packets aren't equal", PacketType.Status.Server.OUT_SERVER_INFO,
PacketType.Status.Server.SERVER_INFO);
}
@Test
@SuppressWarnings("unchecked")
public void ensureTypesAreCorrect() throws Exception {
boolean fail = false;
EnumProtocol[] protocols = EnumProtocol.values();
for (EnumProtocol protocol : protocols) {
Field field = EnumProtocol.class.getDeclaredField("h");
field.setAccessible(true);
Map<EnumProtocolDirection, Map<Integer, Class<?>>> map = (Map<EnumProtocolDirection, Map<Integer, Class<?>>>) field.get(protocol);
for (Entry<EnumProtocolDirection, Map<Integer, Class<?>>> entry : map.entrySet()) {
Map<Integer, Class<?>> treeMap = new TreeMap<>(entry.getValue());
for (Entry<Integer, Class<?>> entry1 : treeMap.entrySet()) {
try {
PacketType type = PacketType.fromClass(entry1.getValue());
if (type.getCurrentId() != entry1.getKey())
throw new IllegalStateException("Packet ID for " + type + " is incorrect. Expected " + entry1.getKey() + ", but got " + type.getCurrentId());
} catch (Throwable ex) {
ex.printStackTrace();
fail = true;
}
}
}
}
assertTrue("Packet type(s) were incorrect!", !fail);
}
}
+335 -129
View File
@@ -1,129 +1,335 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-Parent</artifactId>
<version>4.4.0</version>
<name>ProtocolLib-Parent</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spigotVersion>1.13.1-R0.1-SNAPSHOT</spigotVersion>
</properties>
<modules>
<module>modules/API</module>
<module>modules/ProtocolLib</module>
</modules>
<description>Provides read/write access to the Minecraft protocol.</description>
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
<packaging>pom</packaging>
<inceptionYear>2012</inceptionYear>
<distributionManagement>
<repository>
<id>dmulloy2-releases</id>
<url>http://repo.dmulloy2.net/nexus/repository/releases/</url>
</repository>
<snapshotRepository>
<id>dmulloy2-snapshots</id>
<url>http://repo.dmulloy2.net/nexus/repository/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<!-- Compile with the old version of Netty for backwards compat -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.23.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${spigotVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>${spigotVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.comphenix.executors</groupId>
<artifactId>BukkitExecutors</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean package install</defaultGoal>
<finalName>${project.name}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<!--
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*.yml</include>
</includes>
</resource>
</resources>
-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<failOnError>false</failOnError>
<encoding>ISO-8859-1</encoding>
<doctitle>ProtocolLib JavaDocs</doctitle>
<windowtitle>ProtocolLib JavaDocs</windowtitle>
<bottom>Copyright &#169; {inceptionYear}&#x2013;{currentYear}
Comphenix and dmulloy2. Licensed under the GNU GPL v2.</bottom>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<name>ProtocolLib</name>
<version>4.5.0</version>
<description>Provides read/write access to the Minecraft protocol.</description>
<url>https://github.com/dmulloy2/ProtocolLib</url>
<packaging>jar</packaging>
<inceptionYear>2012</inceptionYear>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.number></project.build.number>
<project.fullVersion>${project.version}</project.fullVersion>
<powermock.version>2.0.4</powermock.version>
<spigot.version>1.15.1-R0.1-SNAPSHOT</spigot.version>
</properties>
<build>
<defaultGoal>clean install</defaultGoal>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>net.sf</pattern>
<shadedPattern>com.comphenix.net.sf</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<excludes>
<exclude>org.spigotmc:spigot</exclude>
<exclude>org.spigotmc:spigot-api</exclude>
<exclude>junit:junit</exclude>
<exclude>io.netty:*</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>com.comphenix.protocol.Application</Main-Class>
<Implementation-Title>ProtocolLib</Implementation-Title>
<Implementation-Version>${project.fullVersion}</Implementation-Version>
<Implementation-Vendor>dmulloy2</Implementation-Vendor>
</manifestEntries>
</archive>
<finalName>${project.name}</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<systemProperties>
<property>
<name>projectVersion</name>
<value>${project.version}</value>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<failOnError>false</failOnError>
<encoding>ISO-8859-1</encoding>
<doctitle>ProtocolLib JavaDocs</doctitle>
<windowtitle>ProtocolLib JavaDocs</windowtitle>
<bottom>Copyright &#169; {inceptionYear}&#x2013;{currentYear}
Comphenix and dmulloy2. Licensed under the GNU GPL v2.</bottom>
<additionalOptions>
<additionalOption>-Xdoclint:none</additionalOption>
</additionalOptions>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jenkins</id>
<activation>
<property>
<name>env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<project.build.number>-b${env.BUILD_NUMBER}</project.build.number>
<!--<project.fullVersion>${project.version}${project.build.number}</project.fullVersion>-->
<project.fullVersion>${project.version}</project.fullVersion>
</properties>
</profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<properties>
<project.fullVersion>${project.version}</project.fullVersion>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- TODO: Look into signing releases
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</profile>
</profiles>
<scm>
<connection>scm:git:git://github.com/dmulloy2/ProtocolLib.git</connection>
<developerConnection>scm:git:git@github.com:dmulloy2/ProtocolLib.git</developerConnection>
<url>https://github.com/dmulloy2/ProtocolLib</url>
</scm>
<licenses>
<license>
<name>GNU GENERAL PUBLIC LICENSE - Version 2, June 1991</name>
<url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>dmulloy2</id>
<name>Dan Mulloy</name>
<url>http://dmulloy2.net/</url>
<roles>
<role>developer</role>
<role>maintainer</role>
</roles>
</developer>
<developer>
<id>aadnk</id>
<name>Kristian S. Stangeland</name>
<email>kr_stang@hotmail.com</email>
<url>http://comphenix.net/</url>
<roles>
<role>former author</role>
</roles>
<timezone>1</timezone>
</developer>
</developers>
<distributionManagement>
<repository>
<id>dmulloy2-releases</id>
<url>https://repo.dmulloy2.net/nexus/repository/releases/</url>
</repository>
<snapshotRepository>
<id>dmulloy2-snapshots</id>
<url>https://repo.dmulloy2.net/nexus/repository/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<!-- Compile with the old version of Netty for backwards compat -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.23.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.5</version>
<scope>compile</scope>
</dependency>
<!-- TODO fold BukkitExecutors into ProtocolLib -->
<dependency>
<groupId>com.comphenix.executors</groupId>
<artifactId>BukkitExecutors</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!-- Testing dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -33,11 +33,11 @@ import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.netty.WirePacket;
import com.google.common.base.Charsets;
import org.apache.commons.io.HexDump;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.libs.org.apache.commons.io.HexDump;
import org.bukkit.plugin.Plugin;
/**
@@ -5,17 +5,10 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
import java.util.function.Consumer;
import com.comphenix.protocol.PacketTypeLookup.ClassLookup;
import com.comphenix.protocol.events.ConnectionSide;
@@ -29,6 +22,9 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
/**
* Represents the type of a packet in a specific protocol.
* <p>
@@ -109,92 +105,99 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static class Server extends PacketTypeEnum {
private final static Sender SENDER = Sender.SERVER;
public static final PacketType SPAWN_ENTITY = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "SpawnEntity");
public static final PacketType SPAWN_ENTITY_EXPERIENCE_ORB = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "SpawnEntityExperienceOrb");
public static final PacketType SPAWN_ENTITY_WEATHER = new PacketType(PROTOCOL, SENDER, 0x02, 0x02, "SpawnEntityWeather");
public static final PacketType SPAWN_ENTITY_LIVING = new PacketType(PROTOCOL, SENDER, 0x03, 0x03, "SpawnEntityLiving");
public static final PacketType SPAWN_ENTITY_PAINTING = new PacketType(PROTOCOL, SENDER, 0x04, 0x04, "SpawnEntityPainting");
public static final PacketType NAMED_ENTITY_SPAWN = new PacketType(PROTOCOL, SENDER, 0x05, 0x05, "NamedEntitySpawn");
public static final PacketType ANIMATION = new PacketType(PROTOCOL, SENDER, 0x06, 0x06, "Animation");
public static final PacketType STATISTIC = new PacketType(PROTOCOL, SENDER, 0x07, 0x07, "Statistic");
public static final PacketType BLOCK_BREAK_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x08, 0x08, "BlockBreakAnimation");
public static final PacketType TILE_ENTITY_DATA = new PacketType(PROTOCOL, SENDER, 0x09, 0x09, "TileEntityData");
public static final PacketType BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x0A, 0x0A, "BlockAction");
public static final PacketType BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x0B, 0x0B, "BlockChange");
public static final PacketType BOSS = new PacketType(PROTOCOL, SENDER, 0x0C, 0x0C, "Boss");
public static final PacketType SERVER_DIFFICULTY = new PacketType(PROTOCOL, SENDER, 0x0D, 0x0D, "ServerDifficulty");
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x0E, 0x0F, "Chat");
public static final PacketType MULTI_BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x0F, 0x10, "MultiBlockChange");
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x10, 0x0E, "TabComplete");
public static final PacketType COMMANDS = new PacketType(PROTOCOL, SENDER, 0x11, -0x01, "Commands");
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x12, 0x11, "Transaction");
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x13, 0x12, "CloseWindow");
public static final PacketType OPEN_WINDOW = new PacketType(PROTOCOL, SENDER, 0x14, 0x13, "OpenWindow");
public static final PacketType WINDOW_ITEMS = new PacketType(PROTOCOL, SENDER, 0x15, 0x14, "WindowItems");
public static final PacketType WINDOW_DATA = new PacketType(PROTOCOL, SENDER, 0x16, 0x15, "WindowData");
public static final PacketType SET_SLOT = new PacketType(PROTOCOL, SENDER, 0x17, 0x16, "SetSlot");
public static final PacketType SET_COOLDOWN = new PacketType(PROTOCOL, SENDER, 0x18, 0x17, "SetCooldown");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x19, 0x18, "CustomPayload");
public static final PacketType CUSTOM_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1A, 0x19, "CustomSoundEffect");
public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x1B, 0x1A, "KickDisconnect");
public static final PacketType ENTITY_STATUS = new PacketType(PROTOCOL, SENDER, 0x1C, 0x1B, "EntityStatus");
public static final PacketType NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x1D, -0x01, "NBTQuery");
public static final PacketType EXPLOSION = new PacketType(PROTOCOL, SENDER, 0x1E, 0x1C, "Explosion");
public static final PacketType UNLOAD_CHUNK = new PacketType(PROTOCOL, SENDER, 0x1F, 0x1D, "UnloadChunk");
public static final PacketType GAME_STATE_CHANGE = new PacketType(PROTOCOL, SENDER, 0x20, 0x1E, "GameStateChange");
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x21, 0x1F, "KeepAlive");
public static final PacketType MAP_CHUNK = new PacketType(PROTOCOL, SENDER, 0x22, 0x20, "MapChunk");
public static final PacketType WORLD_EVENT = new PacketType(PROTOCOL, SENDER, 0x23, 0x21, "WorldEvent");
public static final PacketType WORLD_PARTICLES = new PacketType(PROTOCOL, SENDER, 0x24, 0x22, "WorldParticles");
public static final PacketType LOGIN = new PacketType(PROTOCOL, SENDER, 0x25, 0x23, "Login");
public static final PacketType MAP = new PacketType(PROTOCOL, SENDER, 0x26, 0x24, "Map");
public static final PacketType ENTITY = new PacketType(PROTOCOL, SENDER, 0x27, 0x25, "Entity");
public static final PacketType REL_ENTITY_MOVE = new PacketType(PROTOCOL, SENDER, 0x28, 0x26, "RelEntityMove");
public static final PacketType REL_ENTITY_MOVE_LOOK = new PacketType(PROTOCOL, SENDER, 0x29, 0x27, "RelEntityMoveLook");
public static final PacketType ENTITY_LOOK = new PacketType(PROTOCOL, SENDER, 0x2A, 0x28, "EntityLook");
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x2B, 0x29, "VehicleMove");
public static final PacketType OPEN_SIGN_EDITOR = new PacketType(PROTOCOL, SENDER, 0x2C, 0x2A, "OpenSignEditor");
public static final PacketType AUTO_RECIPE = new PacketType(PROTOCOL, SENDER, 0x2D, 0x2B, "AutoRecipe");
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x2E, 0x2C, "Abilities");
public static final PacketType COMBAT_EVENT = new PacketType(PROTOCOL, SENDER, 0x2F, 0x2D, "CombatEvent");
public static final PacketType PLAYER_INFO = new PacketType(PROTOCOL, SENDER, 0x30, 0x2E, "PlayerInfo");
public static final PacketType LOOK_AT = new PacketType(PROTOCOL, SENDER, 0x31, -0x01, "LookAt");
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x32, 0x2F, "Position");
public static final PacketType BED = new PacketType(PROTOCOL, SENDER, 0x33, 0x30, "Bed");
public static final PacketType RECIPES = new PacketType(PROTOCOL, SENDER, 0x34, 0x31, "Recipes");
public static final PacketType ENTITY_DESTROY = new PacketType(PROTOCOL, SENDER, 0x35, 0x32, "EntityDestroy");
public static final PacketType REMOVE_ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x36, 0x33, "RemoveEntityEffect");
public static final PacketType RESOURCE_PACK_SEND = new PacketType(PROTOCOL, SENDER, 0x37, 0x34, "ResourcePackSend");
public static final PacketType RESPAWN = new PacketType(PROTOCOL, SENDER, 0x38, 0x35, "Respawn");
public static final PacketType ENTITY_HEAD_ROTATION = new PacketType(PROTOCOL, SENDER, 0x39, 0x36, "EntityHeadRotation");
public static final PacketType SELECT_ADVANCEMENT_TAB = new PacketType(PROTOCOL, SENDER, 0x3A, 0x37, "SelectAdvancementTab");
public static final PacketType WORLD_BORDER = new PacketType(PROTOCOL, SENDER, 0x3B, 0x38, "WorldBorder");
public static final PacketType CAMERA = new PacketType(PROTOCOL, SENDER, 0x3C, 0x39, "Camera");
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x3D, 0x3A, "HeldItemSlot");
public static final PacketType SCOREBOARD_DISPLAY_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x3E, 0x3B, "ScoreboardDisplayObjective");
public static final PacketType ENTITY_METADATA = new PacketType(PROTOCOL, SENDER, 0x3F, 0x3C, "EntityMetadata");
public static final PacketType ATTACH_ENTITY = new PacketType(PROTOCOL, SENDER, 0x40, 0x3D, "AttachEntity");
public static final PacketType ENTITY_VELOCITY = new PacketType(PROTOCOL, SENDER, 0x41, 0x3E, "EntityVelocity");
public static final PacketType ENTITY_EQUIPMENT = new PacketType(PROTOCOL, SENDER, 0x42, 0x3F, "EntityEquipment");
public static final PacketType EXPERIENCE = new PacketType(PROTOCOL, SENDER, 0x43, 0x40, "Experience");
public static final PacketType UPDATE_HEALTH = new PacketType(PROTOCOL, SENDER, 0x44, 0x41, "UpdateHealth");
public static final PacketType SCOREBOARD_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x45, 0x42, "ScoreboardObjective");
public static final PacketType MOUNT = new PacketType(PROTOCOL, SENDER, 0x46, 0x43, "Mount");
public static final PacketType SCOREBOARD_TEAM = new PacketType(PROTOCOL, SENDER, 0x47, 0x44, "ScoreboardTeam");
public static final PacketType SCOREBOARD_SCORE = new PacketType(PROTOCOL, SENDER, 0x48, 0x45, "ScoreboardScore");
public static final PacketType SPAWN_POSITION = new PacketType(PROTOCOL, SENDER, 0x49, 0x46, "SpawnPosition");
public static final PacketType UPDATE_TIME = new PacketType(PROTOCOL, SENDER, 0x4A, 0x47, "UpdateTime");
public static final PacketType TITLE = new PacketType(PROTOCOL, SENDER, 0x4B, 0x48, "Title");
public static final PacketType STOP_SOUND = new PacketType(PROTOCOL, SENDER, 0x4C, -0x01, "StopSound");
public static final PacketType NAMED_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x4D, 0x49, "NamedSoundEffect");
public static final PacketType PLAYER_LIST_HEADER_FOOTER = new PacketType(PROTOCOL, SENDER, 0x4E, 0x4A, "PlayerListHeaderFooter");
public static final PacketType COLLECT = new PacketType(PROTOCOL, SENDER, 0x4F, 0x4B, "Collect");
public static final PacketType ENTITY_TELEPORT = new PacketType(PROTOCOL, SENDER, 0x50, 0x4C, "EntityTeleport");
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x51, 0x4D, "Advancements");
public static final PacketType UPDATE_ATTRIBUTES = new PacketType(PROTOCOL, SENDER, 0x52, 0x4E, "UpdateAttributes");
public static final PacketType ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x53, 0x4F, "EntityEffect");
public static final PacketType RECIPE_UPDATE = new PacketType(PROTOCOL, SENDER, 0x54, 0x54, "RecipeUpdate");
public static final PacketType TAGS = new PacketType(PROTOCOL, SENDER, 0x55, 0x55, "Tags");
public static final PacketType SPAWN_ENTITY = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "SpawnEntity");
public static final PacketType SPAWN_ENTITY_EXPERIENCE_ORB = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "SpawnEntityExperienceOrb");
public static final PacketType SPAWN_ENTITY_WEATHER = new PacketType(PROTOCOL, SENDER, 0x02, 0xFF, "SpawnEntityWeather");
public static final PacketType SPAWN_ENTITY_LIVING = new PacketType(PROTOCOL, SENDER, 0x03, 0xFF, "SpawnEntityLiving");
public static final PacketType SPAWN_ENTITY_PAINTING = new PacketType(PROTOCOL, SENDER, 0x04, 0xFF, "SpawnEntityPainting");
public static final PacketType NAMED_ENTITY_SPAWN = new PacketType(PROTOCOL, SENDER, 0x05, 0xFF, "NamedEntitySpawn");
public static final PacketType ANIMATION = new PacketType(PROTOCOL, SENDER, 0x06, 0xFF, "Animation");
public static final PacketType STATISTIC = new PacketType(PROTOCOL, SENDER, 0x07, 0xFF, "Statistic");
public static final PacketType BLOCK_BREAK = new PacketType(PROTOCOL, SENDER, 0x08, 0xFF, "BlockBreak");
public static final PacketType BLOCK_BREAK_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x09, 0xFF, "BlockBreakAnimation");
public static final PacketType TILE_ENTITY_DATA = new PacketType(PROTOCOL, SENDER, 0x0A, 0xFF, "TileEntityData");
public static final PacketType BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x0B, 0xFF, "BlockAction");
public static final PacketType BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x0C, 0xFF, "BlockChange");
public static final PacketType BOSS = new PacketType(PROTOCOL, SENDER, 0x0D, 0xFF, "Boss");
public static final PacketType SERVER_DIFFICULTY = new PacketType(PROTOCOL, SENDER, 0x0E, 0xFF, "ServerDifficulty");
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x0F, 0xFF, "Chat");
public static final PacketType MULTI_BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x10, 0xFF, "MultiBlockChange");
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x11, 0xFF, "TabComplete");
public static final PacketType COMMANDS = new PacketType(PROTOCOL, SENDER, 0x12, 0xFF, "Commands");
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x13, 0xFF, "Transaction");
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x14, 0xFF, "CloseWindow");
public static final PacketType WINDOW_ITEMS = new PacketType(PROTOCOL, SENDER, 0x15, 0xFF, "WindowItems");
public static final PacketType WINDOW_DATA = new PacketType(PROTOCOL, SENDER, 0x16, 0xFF, "WindowData");
public static final PacketType SET_SLOT = new PacketType(PROTOCOL, SENDER, 0x17, 0xFF, "SetSlot");
public static final PacketType SET_COOLDOWN = new PacketType(PROTOCOL, SENDER, 0x18, 0xFF, "SetCooldown");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x19, 0xFF, "CustomPayload");
public static final PacketType CUSTOM_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1A, 0xFF, "CustomSoundEffect");
public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x1B, 0xFF, "KickDisconnect");
public static final PacketType ENTITY_STATUS = new PacketType(PROTOCOL, SENDER, 0x1C, 0xFF, "EntityStatus");
public static final PacketType EXPLOSION = new PacketType(PROTOCOL, SENDER, 0x1D, 0xFF, "Explosion");
public static final PacketType UNLOAD_CHUNK = new PacketType(PROTOCOL, SENDER, 0x1E, 0xFF, "UnloadChunk");
public static final PacketType GAME_STATE_CHANGE = new PacketType(PROTOCOL, SENDER, 0x1F, 0xFF, "GameStateChange");
public static final PacketType OPEN_WINDOW_HORSE = new PacketType(PROTOCOL, SENDER, 0x20, 0xFF, "OpenWindowHorse");
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x21, 0xFF, "KeepAlive");
public static final PacketType MAP_CHUNK = new PacketType(PROTOCOL, SENDER, 0x22, 0xFF, "MapChunk");
public static final PacketType WORLD_EVENT = new PacketType(PROTOCOL, SENDER, 0x23, 0xFF, "WorldEvent");
public static final PacketType WORLD_PARTICLES = new PacketType(PROTOCOL, SENDER, 0x24, 0xFF, "WorldParticles");
public static final PacketType LIGHT_UPDATE = new PacketType(PROTOCOL, SENDER, 0x25, 0xFF, "LightUpdate");
public static final PacketType LOGIN = new PacketType(PROTOCOL, SENDER, 0x26, 0xFF, "Login");
public static final PacketType MAP = new PacketType(PROTOCOL, SENDER, 0x27, 0xFF, "Map");
public static final PacketType OPEN_WINDOW_MERCHANT = new PacketType(PROTOCOL, SENDER, 0x28, 0xFF, "OpenWindowMerchant");
public static final PacketType REL_ENTITY_MOVE = new PacketType(PROTOCOL, SENDER, 0x29, 0xFF, "Entity$RelEntityMove");
public static final PacketType REL_ENTITY_MOVE_LOOK = new PacketType(PROTOCOL, SENDER, 0x2A, 0xFF, "Entity$RelEntityMoveLook");
public static final PacketType ENTITY_LOOK = new PacketType(PROTOCOL, SENDER, 0x2B, 0xFF, "Entity$EntityLook");
public static final PacketType ENTITY = new PacketType(PROTOCOL, SENDER, 0x2C, 0xFF, "Entity");
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x2D, 0xFF, "VehicleMove");
public static final PacketType OPEN_BOOK = new PacketType(PROTOCOL, SENDER, 0x2E, 0xFF, "OpenBook");
public static final PacketType OPEN_WINDOW = new PacketType(PROTOCOL, SENDER, 0x2F, 0xFF, "OpenWindow");
public static final PacketType OPEN_SIGN_EDITOR = new PacketType(PROTOCOL, SENDER, 0x30, 0xFF, "OpenSignEditor");
public static final PacketType AUTO_RECIPE = new PacketType(PROTOCOL, SENDER, 0x31, 0xFF, "AutoRecipe");
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x32, 0xFF, "Abilities");
public static final PacketType COMBAT_EVENT = new PacketType(PROTOCOL, SENDER, 0x33, 0xFF, "CombatEvent");
public static final PacketType PLAYER_INFO = new PacketType(PROTOCOL, SENDER, 0x34, 0xFF, "PlayerInfo");
public static final PacketType LOOK_AT = new PacketType(PROTOCOL, SENDER, 0x35, 0xFF, "LookAt");
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x36, 0xFF, "Position");
public static final PacketType RECIPES = new PacketType(PROTOCOL, SENDER, 0x37, 0xFF, "Recipes");
public static final PacketType ENTITY_DESTROY = new PacketType(PROTOCOL, SENDER, 0x38, 0xFF, "EntityDestroy");
public static final PacketType REMOVE_ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x39, 0xFF, "RemoveEntityEffect");
public static final PacketType RESOURCE_PACK_SEND = new PacketType(PROTOCOL, SENDER, 0x3A, 0xFF, "ResourcePackSend");
public static final PacketType RESPAWN = new PacketType(PROTOCOL, SENDER, 0x3B, 0xFF, "Respawn");
public static final PacketType ENTITY_HEAD_ROTATION = new PacketType(PROTOCOL, SENDER, 0x3C, 0xFF, "EntityHeadRotation");
public static final PacketType SELECT_ADVANCEMENT_TAB = new PacketType(PROTOCOL, SENDER, 0x3D, 0xFF, "SelectAdvancementTab");
public static final PacketType WORLD_BORDER = new PacketType(PROTOCOL, SENDER, 0x3E, 0xFF, "WorldBorder");
public static final PacketType CAMERA = new PacketType(PROTOCOL, SENDER, 0x3F, 0xFF, "Camera");
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x40, 0xFF, "HeldItemSlot");
public static final PacketType VIEW_CENTRE = new PacketType(PROTOCOL, SENDER, 0x41, 0xFF, "ViewCentre");
public static final PacketType VIEW_DISTANCE = new PacketType(PROTOCOL, SENDER, 0x42, 0xFF, "ViewDistance");
public static final PacketType SCOREBOARD_DISPLAY_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x43, 0xFF, "ScoreboardDisplayObjective");
public static final PacketType ENTITY_METADATA = new PacketType(PROTOCOL, SENDER, 0x44, 0xFF, "EntityMetadata");
public static final PacketType ATTACH_ENTITY = new PacketType(PROTOCOL, SENDER, 0x45, 0xFF, "AttachEntity");
public static final PacketType ENTITY_VELOCITY = new PacketType(PROTOCOL, SENDER, 0x46, 0xFF, "EntityVelocity");
public static final PacketType ENTITY_EQUIPMENT = new PacketType(PROTOCOL, SENDER, 0x47, 0xFF, "EntityEquipment");
public static final PacketType EXPERIENCE = new PacketType(PROTOCOL, SENDER, 0x48, 0xFF, "Experience");
public static final PacketType UPDATE_HEALTH = new PacketType(PROTOCOL, SENDER, 0x49, 0xFF, "UpdateHealth");
public static final PacketType SCOREBOARD_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x4A, 0xFF, "ScoreboardObjective");
public static final PacketType MOUNT = new PacketType(PROTOCOL, SENDER, 0x4B, 0xFF, "Mount");
public static final PacketType SCOREBOARD_TEAM = new PacketType(PROTOCOL, SENDER, 0x4C, 0xFF, "ScoreboardTeam");
public static final PacketType SCOREBOARD_SCORE = new PacketType(PROTOCOL, SENDER, 0x4D, 0xFF, "ScoreboardScore");
public static final PacketType SPAWN_POSITION = new PacketType(PROTOCOL, SENDER, 0x4E, 0xFF, "SpawnPosition");
public static final PacketType UPDATE_TIME = new PacketType(PROTOCOL, SENDER, 0x4F, 0xFF, "UpdateTime");
public static final PacketType TITLE = new PacketType(PROTOCOL, SENDER, 0x50, 0xFF, "Title");
public static final PacketType ENTITY_SOUND = new PacketType(PROTOCOL, SENDER, 0x51, 0xFF, "EntitySound");
public static final PacketType NAMED_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x52, 0xFF, "NamedSoundEffect");
public static final PacketType STOP_SOUND = new PacketType(PROTOCOL, SENDER, 0x53, 0xFF, "StopSound");
public static final PacketType PLAYER_LIST_HEADER_FOOTER = new PacketType(PROTOCOL, SENDER, 0x54, 0xFF, "PlayerListHeaderFooter");
public static final PacketType NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x55, 0xFF, "NBTQuery");
public static final PacketType COLLECT = new PacketType(PROTOCOL, SENDER, 0x56, 0xFF, "Collect");
public static final PacketType ENTITY_TELEPORT = new PacketType(PROTOCOL, SENDER, 0x57, 0xFF, "EntityTeleport");
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x58, 0xFF, "Advancements");
public static final PacketType UPDATE_ATTRIBUTES = new PacketType(PROTOCOL, SENDER, 0x59, 0xFF, "UpdateAttributes");
public static final PacketType ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x5A, 0xFF, "EntityEffect");
public static final PacketType RECIPE_UPDATE = new PacketType(PROTOCOL, SENDER, 0x5B, 0xFF, "RecipeUpdate");
public static final PacketType TAGS = new PacketType(PROTOCOL, SENDER, 0x5C, 0xFF, "Tags");
// ---- Removed in 1.9
@@ -251,6 +254,20 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static final PacketType UPDATE_SIGN = MinecraftReflection.signUpdateExists() ? new PacketType(PROTOCOL, SENDER, 252, 252, "UpdateSign") :
TILE_ENTITY_DATA.clone();
// ---- Removed in 1.14
/**
* @deprecated Removed in 1.14
*/
@Deprecated
public static final PacketType BED = new PacketType(PROTOCOL, SENDER, 0x33, 0x33, "Bed");
/**
* @deprecated Renamed to {@link #BED}
*/
@Deprecated
public static final PacketType USE_BED = BED.clone();
private final static Server INSTANCE = new Server();
// Prevent accidental construction
@@ -271,49 +288,52 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static class Client extends PacketTypeEnum {
private final static Sender SENDER = Sender.CLIENT;
public static final PacketType TELEPORT_ACCEPT = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "TeleportAccept");
public static final PacketType TILE_NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x01, -0x01, "TileNBTQuery");
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x02, 0x02, "Chat");
public static final PacketType CLIENT_COMMAND = new PacketType(PROTOCOL, SENDER, 0x03, 0x03, "ClientCommand");
public static final PacketType SETTINGS = new PacketType(PROTOCOL, SENDER, 0x04, 0x04, "Settings");
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x05, 0x01, "TabComplete");
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x06, 0x05, "Transaction");
public static final PacketType ENCHANT_ITEM = new PacketType(PROTOCOL, SENDER, 0x07, 0x06, "EnchantItem");
public static final PacketType WINDOW_CLICK = new PacketType(PROTOCOL, SENDER, 0x08, 0x07, "WindowClick");
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x09, 0x08, "CloseWindow");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x0A, 0x09, "CustomPayload");
public static final PacketType BOOK_EDIT = new PacketType(PROTOCOL, SENDER, 0x0B, -0x01, "BEdit");
public static final PacketType ENTITY_NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x0C, -0x01, "EntityNBTQuery");
public static final PacketType USE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x0D, 0x0A, "UseEntity");
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x0E, 0x0B, "KeepAlive");
public static final PacketType FLYING = new PacketType(PROTOCOL, SENDER, 0x0F, 0x0C, "Flying");
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x10, 0x0D, "Position");
public static final PacketType POSITION_LOOK = new PacketType(PROTOCOL, SENDER, 0x11, 0x0E, "PositionLook");
public static final PacketType LOOK = new PacketType(PROTOCOL, SENDER, 0x12, 0x0F, "Look");
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x13, 0x10, "VehicleMove");
public static final PacketType BOAT_MOVE = new PacketType(PROTOCOL, SENDER, 0x14, 0x11, "BoatMove");
public static final PacketType PICK_ITEM = new PacketType(PROTOCOL, SENDER, 0x15, -0x01, "PickItem");
public static final PacketType AUTO_RECIPE = new PacketType(PROTOCOL, SENDER, 0x16, 0x12, "AutoRecipe");
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x17, 0x13, "Abilities");
public static final PacketType BLOCK_DIG = new PacketType(PROTOCOL, SENDER, 0x18, 0x14, "BlockDig");
public static final PacketType ENTITY_ACTION = new PacketType(PROTOCOL, SENDER, 0x19, 0x15, "EntityAction");
public static final PacketType STEER_VEHICLE = new PacketType(PROTOCOL, SENDER, 0x1A, 0x16, "SteerVehicle");
public static final PacketType RECIPE_DISPLAYED = new PacketType(PROTOCOL, SENDER, 0x1B, 0x17, "RecipeDisplayed");
public static final PacketType ITEM_NAME = new PacketType(PROTOCOL, SENDER, 0x1C, -0x01, "ItemName");
public static final PacketType RESOURCE_PACK_STATUS = new PacketType(PROTOCOL, SENDER, 0x1D, 0x18, "ResourcePackStatus");
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x1E, 0x19, "Advancements");
public static final PacketType TRADE_SELECT = new PacketType(PROTOCOL, SENDER, 0x1F, -0x01, "TrSel");
public static final PacketType BEACON = new PacketType(PROTOCOL, SENDER, 0x20, -0x01, "Beacon");
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x21, 0x1A, "HeldItemSlot");
public static final PacketType SET_COMMAND_BLOCK = new PacketType(PROTOCOL, SENDER, 0x22, 0x22, "SetCommandBlock");
public static final PacketType SET_COMMAND_MINECART = new PacketType(PROTOCOL, SENDER, 0x23, 0x23, "SetCommandMinecart");
public static final PacketType SET_CREATIVE_SLOT = new PacketType(PROTOCOL, SENDER, 0x24, 0x1B, "SetCreativeSlot");
public static final PacketType STRUCTURE_BLOCK = new PacketType(PROTOCOL, SENDER, 0x25, 0x25, "Struct");
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x26, 0x1C, "UpdateSign");
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x27, 0x1D, "ArmAnimation");
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x28, 0x1E, "Spectate");
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x29, 0x1F, "UseItem");
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x2A, 0x20, "BlockPlace");
public static final PacketType TELEPORT_ACCEPT = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "TeleportAccept");
public static final PacketType TILE_NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "TileNBTQuery");
public static final PacketType DIFFICULTY_CHANGE = new PacketType(PROTOCOL, SENDER, 0x02, 0xFF, "DifficultyChange");
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x03, 0xFF, "Chat");
public static final PacketType CLIENT_COMMAND = new PacketType(PROTOCOL, SENDER, 0x04, 0xFF, "ClientCommand");
public static final PacketType SETTINGS = new PacketType(PROTOCOL, SENDER, 0x05, 0xFF, "Settings");
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x06, 0xFF, "TabComplete");
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x07, 0xFF, "Transaction");
public static final PacketType ENCHANT_ITEM = new PacketType(PROTOCOL, SENDER, 0x08, 0xFF, "EnchantItem");
public static final PacketType WINDOW_CLICK = new PacketType(PROTOCOL, SENDER, 0x09, 0xFF, "WindowClick");
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x0A, 0xFF, "CloseWindow");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x0B, 0xFF, "CustomPayload");
public static final PacketType B_EDIT = new PacketType(PROTOCOL, SENDER, 0x0C, 0xFF, "BEdit");
public static final PacketType ENTITY_NBT_QUERY = new PacketType(PROTOCOL, SENDER, 0x0D, 0xFF, "EntityNBTQuery");
public static final PacketType USE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x0E, 0xFF, "UseEntity");
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x0F, 0xFF, "KeepAlive");
public static final PacketType DIFFICULTY_LOCK = new PacketType(PROTOCOL, SENDER, 0x10, 0xFF, "DifficultyLock");
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x11, 0xFF, "Flying$Position");
public static final PacketType POSITION_LOOK = new PacketType(PROTOCOL, SENDER, 0x12, 0xFF, "Flying$PositionLook");
public static final PacketType LOOK = new PacketType(PROTOCOL, SENDER, 0x13, 0xFF, "Flying$Look");
public static final PacketType FLYING = new PacketType(PROTOCOL, SENDER, 0x14, 0xFF, "Flying");
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x15, 0xFF, "VehicleMove");
public static final PacketType BOAT_MOVE = new PacketType(PROTOCOL, SENDER, 0x16, 0xFF, "BoatMove");
public static final PacketType PICK_ITEM = new PacketType(PROTOCOL, SENDER, 0x17, 0xFF, "PickItem");
public static final PacketType AUTO_RECIPE = new PacketType(PROTOCOL, SENDER, 0x18, 0xFF, "AutoRecipe");
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x19, 0xFF, "Abilities");
public static final PacketType BLOCK_DIG = new PacketType(PROTOCOL, SENDER, 0x1A, 0xFF, "BlockDig");
public static final PacketType ENTITY_ACTION = new PacketType(PROTOCOL, SENDER, 0x1B, 0xFF, "EntityAction");
public static final PacketType STEER_VEHICLE = new PacketType(PROTOCOL, SENDER, 0x1C, 0xFF, "SteerVehicle");
public static final PacketType RECIPE_DISPLAYED = new PacketType(PROTOCOL, SENDER, 0x1D, 0xFF, "RecipeDisplayed");
public static final PacketType ITEM_NAME = new PacketType(PROTOCOL, SENDER, 0x1E, 0xFF, "ItemName");
public static final PacketType RESOURCE_PACK_STATUS = new PacketType(PROTOCOL, SENDER, 0x1F, 0xFF, "ResourcePackStatus");
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x20, 0xFF, "Advancements");
public static final PacketType TR_SEL = new PacketType(PROTOCOL, SENDER, 0x21, 0xFF, "TrSel");
public static final PacketType BEACON = new PacketType(PROTOCOL, SENDER, 0x22, 0xFF, "Beacon");
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x23, 0xFF, "HeldItemSlot");
public static final PacketType SET_COMMAND_BLOCK = new PacketType(PROTOCOL, SENDER, 0x24, 0xFF, "SetCommandBlock");
public static final PacketType SET_COMMAND_MINECART = new PacketType(PROTOCOL, SENDER, 0x25, 0xFF, "SetCommandMinecart");
public static final PacketType SET_CREATIVE_SLOT = new PacketType(PROTOCOL, SENDER, 0x26, 0xFF, "SetCreativeSlot");
public static final PacketType SET_JIGSAW = new PacketType(PROTOCOL, SENDER, 0x27, 0xFF, "SetJigsaw");
public static final PacketType STRUCT = new PacketType(PROTOCOL, SENDER, 0x28, 0xFF, "Struct");
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x29, 0xFF, "UpdateSign");
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x2A, 0xFF, "ArmAnimation");
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x2B, 0xFF, "Spectate");
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x2C, 0xFF, "UseItem");
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x2D, 0xFF, "BlockPlace");
private final static Client INSTANCE = new Client();
@@ -348,8 +368,8 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
private final static Sender SENDER = Sender.SERVER;
@ForceAsync
public static final PacketType SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "ServerInfo");
public static final PacketType PONG = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "Pong");
public static final PacketType SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "ServerInfo");
public static final PacketType PONG = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "Pong");
/**
* @deprecated Renamed to {@link #SERVER_INFO}
@@ -378,8 +398,8 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static class Client extends PacketTypeEnum {
private final static Sender SENDER = Sender.CLIENT;
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Start");
public static final PacketType PING = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "Ping");
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "Start");
public static final PacketType PING = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "Ping");
private final static Client INSTANCE = new Client();
@@ -413,11 +433,11 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static class Server extends PacketTypeEnum {
private final static Sender SENDER = Sender.SERVER;
public static final PacketType DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Disconnect");
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "EncryptionBegin");
public static final PacketType SUCCESS = new PacketType(PROTOCOL, SENDER, 0x02, 0x02, "Success");
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 0x03, 0x03, "SetCompression");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x04, -0x01, "CustomPayload");
public static final PacketType DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "Disconnect");
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "EncryptionBegin");
public static final PacketType SUCCESS = new PacketType(PROTOCOL, SENDER, 0x02, 0xFF, "Success");
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 0x03, 0xFF, "SetCompression");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x04, 0xFF, "CustomPayload");
private final static Server INSTANCE = new Server();
@@ -439,9 +459,9 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
public static class Client extends PacketTypeEnum {
private final static Sender SENDER = Sender.CLIENT;
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Start");
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "EncryptionBegin");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x02, -0x01, "CustomPayload");
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0xFF, "Start");
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0xFF, "EncryptionBegin");
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x02, 0xFF, "CustomPayload");
private final static Client INSTANCE = new Client();
@@ -619,7 +639,7 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
/**
* Protocol version of all the current IDs.
*/
private static final MinecraftVersion PROTOCOL_VERSION = MinecraftVersion.EXPLORATION_UPDATE;
private static final MinecraftVersion PROTOCOL_VERSION = MinecraftVersion.VILLAGE_UPDATE;
private final Protocol protocol;
private final Sender sender;
@@ -627,6 +647,7 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
private final int legacyId;
private final MinecraftVersion version;
private final String[] classNames;
String[] names;
private String name;
private boolean deprecated;
@@ -750,7 +771,7 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
}
public static PacketType findCurrent(Protocol protocol, Sender sender, String name) {
name = format(protocol, sender, name);
name = formatClassName(protocol, sender, name);
PacketType type = getLookup().getFromCurrent(protocol, sender, name);
if (type != null) {
@@ -761,11 +782,21 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
}
}
private static String format(Protocol protocol, Sender sender, String name) {
if (name.contains("Packet"))
private static String formatClassName(Protocol protocol, Sender sender, String name) {
String base = MinecraftReflection.getMinecraftPackage() + ".Packet";
if (name.startsWith(base)) {
return name;
}
return String.format("Packet%s%s%s", protocol.getPacketName(), sender.getPacketName(), WordUtils.capitalize(name));
if (name.contains("$")) {
String[] split = name.split("\\$");
String parent = split[0];
String child = split[1];
return base + protocol.getPacketName() + sender.getPacketName() + WordUtils.capitalize(parent)
+ "$Packet" + protocol.getPacketName() + sender.getPacketName() + WordUtils.capitalize(child);
}
return base + protocol.getPacketName() + sender.getPacketName() + WordUtils.capitalize(name);
}
/**
@@ -828,6 +859,8 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
return type;
}
static Consumer<String> onDynamicCreate = x -> {};
/**
* Retrieve a packet type from a protocol, sender, ID, and class for 1.8+
* <p>
@@ -843,15 +876,16 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
Map<String, PacketType> map = lookup.getMap(protocol, sender);
// Check the map first
String clazz = packetClass.getSimpleName();
PacketType type = find(map, clazz);
String className = packetClass.getName();
PacketType type = find(map, className);
if (type == null) {
// Guess we don't support this packet :/
type = new PacketType(protocol, sender, packetId, -1, PROTOCOL_VERSION, clazz);
type = new PacketType(protocol, sender, packetId, -1, PROTOCOL_VERSION, className);
type.dynamic = true;
// Many may be scheduled, but only the first will be executed
scheduleRegister(type, "Dynamic-" + UUID.randomUUID().toString());
onDynamicCreate.accept(className);
}
return type;
@@ -998,8 +1032,10 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
this.classNames = new String[names.length];
for (int i = 0; i < classNames.length; i++) {
classNames[i] = format(protocol, sender, names[i]);
classNames[i] = formatClassName(protocol, sender, names[i]);
}
this.names = names;
}
/**
@@ -1059,7 +1095,9 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
* <p>
* It is unknown if the packet was removed at any point.
* @return The current ID, or {@link #UNKNOWN_PACKET} if unknown.
* @deprecated Don't rely on packet IDs, they change every version
*/
@Deprecated
public int getCurrentId() {
return currentId;
}
@@ -39,12 +39,12 @@ public class ProtocolLibrary {
/**
* The maximum version ProtocolLib has been tested with.
*/
public static final String MAXIMUM_MINECRAFT_VERSION = "1.13.1";
public static final String MAXIMUM_MINECRAFT_VERSION = "1.15.1";
/**
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.13.1) was released.
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.14.4) was released.
*/
public static final String MINECRAFT_LAST_RELEASE_DATE = "2018-08-22";
public static final String MINECRAFT_LAST_RELEASE_DATE = "2019-12-17";
/**
* Plugins that are currently incompatible with ProtocolLib.
@@ -18,6 +18,7 @@ package com.comphenix.protocol;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.plugin.Plugin;
@@ -25,18 +26,15 @@ import org.bukkit.plugin.Plugin;
* @author dmulloy2
*/
public class ProtocolLogger {
private static Plugin plugin;
private static boolean debugEnabled = false;
private static Logger logger = Logger.getLogger("Minecraft");
protected static void init(Plugin plugin) {
ProtocolLogger.plugin = plugin;
}
logger = plugin.getLogger();
public static boolean isDebugEnabled() {
try {
return plugin.getConfig().getBoolean("global.debug", false);
} catch (Throwable ex) { // Enable in testing environments
return true;
}
debugEnabled = plugin.getConfig().getBoolean("global.debug", false);
} catch (Throwable ignored) { }
}
/**
@@ -46,7 +44,7 @@ public class ProtocolLogger {
* @param args Arguments to format in
*/
public static void log(Level level, String message, Object... args) {
plugin.getLogger().log(level, MessageFormat.format(message, args));
logger.log(level, MessageFormat.format(message, args));
}
/**
@@ -65,18 +63,18 @@ public class ProtocolLogger {
* @param ex Exception to log
*/
public static void log(Level level, String message, Throwable ex) {
plugin.getLogger().log(level, message, ex);
logger.log(level, message, ex);
}
public static void debug(String message, Object... args) {
if (isDebugEnabled()) {
if (debugEnabled) {
log("[Debug] " + message, args);
}
}
public static void debug(String message, Throwable ex) {
if (isDebugEnabled()) {
plugin.getLogger().log(Level.WARNING, "[Debug] " + message, ex);
if (debugEnabled) {
logger.log(Level.WARNING, "[Debug] " + message, ex);
}
}
}
@@ -318,12 +318,12 @@ public class AsyncFilterManager implements AsynchronousManager {
// The player is only be null when they're logged out,
// so this should be a pretty safe check
Player player = newEvent.getPlayer();
Player player = syncPacket.getPlayer();
if (player != null) {
// Start the process
getSendingQueue(syncPacket).enqueue(newEvent);
// We know this is occuring on the main thread, so pass TRUE
// We know this is occurring on the main thread, so pass TRUE
getProcessingQueue(syncPacket).enqueue(newEvent, true);
}
}
@@ -1,5 +1,17 @@
package com.comphenix.protocol.concurrency;
import com.comphenix.protocol.utility.SafeCacheBuilder;
import com.comphenix.protocol.utility.Util;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.RemovalListener;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.UncheckedExecutionException;
import org.bukkit.entity.Player;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
@@ -7,18 +19,6 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.entity.Player;
import com.comphenix.protocol.utility.SafeCacheBuilder;
import com.comphenix.protocol.utility.Util;
import com.google.common.base.Function;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.UncheckedExecutionException;
/**
* Represents a concurrent player map.
* <p>
@@ -37,7 +37,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
ADDRESS {
@Override
public Object apply(Player player) {
return player.getAddress();
return player == null ? null : player.getAddress();
}
},
@@ -47,7 +47,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
NAME {
@Override
public Object apply(Player player) {
return player.getName();
return player == null ? null : player.getName();
}
},
}
@@ -55,17 +55,17 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
/**
* An internal map of player keys to values.
*/
protected ConcurrentMap<Object, TValue> valueLookup = createValueMap();
private ConcurrentMap<Object, TValue> valueLookup = createValueMap();
/**
* A cache of the associated keys for each player.
*/
protected ConcurrentMap<Object, Player> keyLookup = createKeyCache();
private ConcurrentMap<Object, Player> keyLookup = createKeyCache();
/**
* The method used to retrieve a unique key for a player.
*/
protected final Function<Player, Object> keyMethod;
private final Function<Player, Object> keyMethod;
/**
* Construct a new concurrent player map that uses each player's address as key.
@@ -89,7 +89,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* Construct a new concurrent player map using the given standard key method.
* @param standardMethod - the standard key method.
*/
public ConcurrentPlayerMap(PlayerKey standardMethod) {
private ConcurrentPlayerMap(PlayerKey standardMethod) {
this.keyMethod = standardMethod;
}
@@ -107,7 +107,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* The default implementation uses a {@link ConcurrentHashMap}.
* @return The value map.
*/
protected ConcurrentMap<Object, TValue> createValueMap() {
private ConcurrentMap<Object, TValue> createValueMap() {
return Maps.newConcurrentMap();
}
@@ -115,19 +115,16 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* Construct a cache of keys and the associated player.
* @return The key map.
*/
protected ConcurrentMap<Object, Player> createKeyCache() {
private ConcurrentMap<Object, Player> createKeyCache() {
return SafeCacheBuilder.newBuilder().
weakValues().
removalListener(
new RemovalListener<Object, Player>() {
@Override
public void onRemoval(RemovalNotification<Object, Player> removed) {
// We ignore explicit removal
if (removed.wasEvicted()) {
onCacheEvicted(removed.getKey());
}
}
}).
(RemovalListener<Object, Player>) removed -> {
// We ignore explicit removal
if (removed.wasEvicted()) {
onCacheEvicted(removed.getKey());
}
}).
build(
new CacheLoader<Object, Player>() {
@Override
@@ -147,7 +144,6 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
/**
* Invoked when an entry in the cache has been evicted, typically by the garbage collector.
* @param key - the key.
* @param player - the value that was evicted or collected.
*/
private void onCacheEvicted(Object key) {
Player newPlayer = findOnlinePlayer(key);
@@ -165,7 +161,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* @param key - a non-null key.
* @return The player with the given key, or NULL if not found.
*/
protected Player findOnlinePlayer(Object key) {
private Player findOnlinePlayer(Object key) {
for (Player player : Util.getOnlinePlayers()) {
if (key.equals(keyMethod.apply(player))) {
return player;
@@ -179,7 +175,7 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* @param key - the key of the player we are locating.
* @return The player, or NULL if not found.
*/
protected Player lookupPlayer(Object key) {
private Player lookupPlayer(Object key) {
try {
return keyLookup.get(key);
} catch (UncheckedExecutionException e) {
@@ -192,7 +188,9 @@ public class ConcurrentPlayerMap<TValue> extends AbstractMap<Player, TValue> imp
* @param player - the player whose key we want to retrieve.
* @return The key.
*/
protected Object cachePlayerKey(Player player) {
private Object cachePlayerKey(Player player) {
Preconditions.checkNotNull(player, "player cannot be null");
Object key = keyMethod.apply(player);
keyLookup.put(key, player);
@@ -55,7 +55,7 @@ public class ReportType {
*/
public static Class<?> getSenderClass(Object sender) {
if (sender == null)
throw new IllegalArgumentException("sender cannot be NUll.");
throw new IllegalArgumentException("sender cannot be null.");
else if (sender instanceof Class<?>)
return (Class<?>) sender;
else
@@ -75,7 +75,7 @@ public class ReportType {
*/
public static String getReportName(Object sender, ReportType type) {
if (sender == null)
throw new IllegalArgumentException("sender cannot be NUll.");
throw new IllegalArgumentException("sender cannot be null.");
return getReportName(getSenderClass(sender), type);
}
@@ -83,13 +83,13 @@ public class ReportType {
* Retrieve the full canonical name of a given report type.
* <p>
* This is in the format <i>canonical_name_of_class#report_type</i>
* @param clazz - the sender class.
* @param sender - the sender class.
* @param type - the report instance.
* @return The full canonical name.
*/
private static String getReportName(Class<?> sender, ReportType type) {
if (sender == null)
throw new IllegalArgumentException("sender cannot be NUll.");
throw new IllegalArgumentException("sender cannot be null.");
// Whether or not we need to retrieve the report name again
if (type.reportName == null) {
@@ -138,11 +138,10 @@ public class ReportType {
* @return All associated report fields.
*/
private static List<Field> getReportFields(Class<?> clazz) {
return FuzzyReflection.fromClass(clazz).getFieldList(
FuzzyFieldContract.newBuilder().
requireModifier(Modifier.STATIC).
typeDerivedOf(ReportType.class).
build()
);
return FuzzyReflection.fromClass(clazz, true)
.getFieldList(FuzzyFieldContract.newBuilder()
.requireModifier(Modifier.STATIC)
.typeDerivedOf(ReportType.class)
.build());
}
}
@@ -58,6 +58,7 @@ import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
@@ -436,6 +437,16 @@ public class PacketContainer implements Serializable {
Preconditions.checkNotNull(event, "event cannot be NULL.");
return getEntityModifier(event.getPlayer().getWorld());
}
/**
* Retrieves a read/write structure for entity types
* @return A modifier for an EntityType.
*/
public StructureModifier<EntityType> getEntityTypeModifier() {
return structureModifier.withType(
MinecraftReflection.getMinecraftClass("EntityTypes"),
BukkitConverters.getEntityTypeConverter());
}
/**
* Retrieves a read/write structure for chunk positions.
@@ -50,7 +50,7 @@ public class PacketEvent extends EventObject implements Cancellable {
"Plugin %s changed packet type from %s to %s in packet listener. This is confusing for other plugins! (Not an error, though!)");
private static final SetMultimap<PacketType, PacketType> CHANGE_WARNINGS =
Multimaps.synchronizedSetMultimap(HashMultimap.<PacketType, PacketType>create());
Multimaps.synchronizedSetMultimap(HashMultimap.create());
/**
* Automatically generated by Eclipse.
@@ -58,8 +58,7 @@ public class PacketEvent extends EventObject implements Cancellable {
private static final long serialVersionUID = -5360289379097430620L;
private transient WeakReference<Player> playerReference;
private transient Player offlinePlayer;
private PacketContainer packet;
private boolean serverPacket;
private boolean cancel;
@@ -90,7 +89,7 @@ public class PacketEvent extends EventObject implements Cancellable {
private PacketEvent(Object source, PacketContainer packet, NetworkMarker marker, Player player, boolean serverPacket, boolean filtered) {
super(source);
this.packet = packet;
this.playerReference = new WeakReference<Player>(player);
this.playerReference = new WeakReference<>(player);
this.networkMarker = marker;
this.serverPacket = serverPacket;
this.filtered = filtered;
@@ -99,7 +98,7 @@ public class PacketEvent extends EventObject implements Cancellable {
private PacketEvent(PacketEvent origial, AsyncMarker asyncMarker) {
super(origial.source);
this.packet = origial.packet;
this.playerReference = origial.playerReference;
this.playerReference = origial.getPlayerReference();
this.cancel = origial.cancel;
this.serverPacket = origial.serverPacket;
this.filtered = origial.filtered;
@@ -317,24 +316,26 @@ public class PacketEvent extends EventObject implements Cancellable {
this.cancel = cancel;
}
/**
* Retrieves the player that has sent the packet or is recieving it.
* @return The player associated with this event.
*/
public Player getPlayer() {
private WeakReference<Player> getPlayerReference() {
Player player = playerReference.get();
// Check if the player has been updated so we can do more stuff
if (player instanceof TemporaryPlayer) {
Player updated = player.getPlayer();
if (updated != null && !(updated instanceof TemporaryPlayer)) {
playerReference.clear();
playerReference = new WeakReference<>(updated);
return updated;
}
}
return player;
return playerReference;
}
/**
* Retrieves the player that has sent the packet or is receiving it.
* @return The player associated with this event.
*/
public Player getPlayer() {
return getPlayerReference().get();
}
/**
@@ -467,7 +468,8 @@ public class PacketEvent extends EventObject implements Cancellable {
output.defaultWriteObject();
// Write the name of the player (or NULL if it's not set)
output.writeObject(playerReference.get() != null ? new SerializedOfflinePlayer(playerReference.get()) : null);
Player player = getPlayer();
output.writeObject(player != null ? new SerializedOfflinePlayer(player) : null);
}
private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
@@ -479,8 +481,8 @@ public class PacketEvent extends EventObject implements Cancellable {
// Better than nothing
if (serialized != null) {
// Store it, to prevent weak reference from cleaning up the reference
offlinePlayer = serialized.getPlayer();
playerReference = new WeakReference<Player>(offlinePlayer);
Player offlinePlayer = serialized.getPlayer();
playerReference = new WeakReference<>(offlinePlayer);
}
}
@@ -16,15 +16,14 @@
*/
package com.comphenix.protocol.events;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang.Validate;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.Validate;
/**
* Stores and retrieves metadata for applicable packet objects.
* @author dmulloy2
@@ -5,28 +5,15 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import com.comphenix.protocol.AsynchronousManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.PacketType.Sender;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.events.ConnectionSide;
import com.comphenix.protocol.events.ListeningWhitelist;
import com.comphenix.protocol.events.NetworkMarker;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.events.*;
import com.comphenix.protocol.injector.netty.WirePacket;
import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.reflect.FieldAccessException;
@@ -37,6 +24,13 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
/**
* A protocol manager that delays all packet listener registrations and unregistrations until
* an underlying protocol manager can be constructed.
@@ -440,7 +434,7 @@ public class DelayedPacketManager implements InternalManager {
if (delegate != null)
delegate.updateEntity(entity, observers);
else
EntityUtilities.updateEntity(entity, observers);
EntityUtilities.getInstance().updateEntity(entity, observers);
}
@Override
@@ -448,7 +442,7 @@ public class DelayedPacketManager implements InternalManager {
if (delegate != null)
return delegate.getEntityFromID(container, id);
else
return EntityUtilities.getEntityFromID(container, id);
return EntityUtilities.getInstance().getEntityFromID(container, id);
}
@Override
@@ -456,7 +450,7 @@ public class DelayedPacketManager implements InternalManager {
if (delegate != null)
return delegate.getEntityTrackers(entity);
else
return EntityUtilities.getEntityTrackers(entity);
return EntityUtilities.getInstance().getEntityTrackers(entity);
}
@Override
@@ -0,0 +1,269 @@
/*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.injector;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.WrappedIntHashMap;
import com.google.common.collect.Lists;
import org.apache.commons.lang.Validate;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
/**
* Used to perform certain operations on entities.
*
* @author Kristian
*/
class EntityUtilities {
private static final boolean NEW_TRACKER = MinecraftVersion.VILLAGE_UPDATE.atOrAbove();
private static final EntityUtilities INSTANCE = new EntityUtilities();
public static EntityUtilities getInstance() {
return INSTANCE;
}
private EntityUtilities() { }
private FieldAccessor entityTrackerField;
private FieldAccessor trackedEntitiesField;
private FieldAccessor trackedPlayersField;
private Map<Class<?>, MethodAccessor> scanPlayersMethods = new HashMap<>();
public void updateEntity(Entity entity, List<Player> observers) {
if (entity == null || !entity.isValid()) {
return;
}
Collection<?> trackedPlayers = getTrackedPlayers(entity);
List<Object> nmsPlayers = unwrapBukkit(observers);
trackedPlayers.removeAll(nmsPlayers);
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
// there can be multiple different entity tracker entry impls, see GH-732....
scanPlayersMethods.computeIfAbsent(trackerEntry.getClass(), this::findScanPlayers).invoke(trackerEntry, nmsPlayers);
}
private MethodAccessor findScanPlayers(Class<?> trackerClass) {
MethodAccessor candidate = Accessors.getMethodAcccessorOrNull(trackerClass, "scanPlayers");
if (candidate != null) {
return candidate;
}
FuzzyReflection fuzzy = FuzzyReflection.fromClass(trackerClass, true);
return Accessors.getMethodAccessor(
fuzzy.getMethod(
FuzzyMethodContract.newBuilder().returnTypeVoid().parameterExactArray(List.class).build()));
}
/**
* Retrieve every client that is receiving information about a given entity.
* @param entity - the entity that is being tracked.
* @return Every client/player that is tracking the given entity.
* @throws FieldAccessException If reflection failed.
*/
public List<Player> getEntityTrackers(Entity entity) {
if (entity == null || !entity.isValid()) {
return new ArrayList<>();
}
List<Player> result = new ArrayList<>();
Collection<?> trackedPlayers = getTrackedPlayers(entity);
// Wrap every player - we also ensure that the underlying tracker list is immutable
for (Object tracker : trackedPlayers) {
if (MinecraftReflection.isMinecraftPlayer(tracker)) {
result.add((Player) MinecraftReflection.getBukkitEntity(tracker));
}
}
return result;
}
private Collection<?> getTrackedPlayers(Entity entity) {
Validate.notNull(entity, "entity cannot be null");
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
Validate.notNull(trackerEntry, "Could not find entity trackers for " + entity);
if (trackedPlayersField == null) {
trackedPlayersField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*"));
}
Validate.notNull(trackedPlayersField, "Could not find trackedPlayers field");
Object value = trackedPlayersField.get(trackerEntry);
if (value instanceof Collection) {
return (Collection<?>) value;
} else if (value instanceof Map) {
return ((Map<?, ?>) value).keySet();
} else {
// Please. No more changes.
throw new IllegalStateException("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value.getClass());
}
}
private MethodAccessor getChunkProvider;
private FieldAccessor chunkMapField;
@SuppressWarnings("unchecked")
private Object getNewEntityTracker(Object worldServer, int entityId) {
if (getChunkProvider == null) {
Class<?> chunkProviderClass = MinecraftReflection.getMinecraftClass("ChunkProviderServer");
getChunkProvider = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(worldServer.getClass(), false).getMethod(
FuzzyMethodContract.newBuilder().parameterCount(0).returnTypeExact(chunkProviderClass).build()));
}
Object chunkProvider = getChunkProvider.invoke(worldServer);
if (chunkMapField == null) {
Class<?> chunkMapClass = MinecraftReflection.getMinecraftClass("PlayerChunkMap");
chunkMapField = Accessors.getFieldAccessor(
FuzzyReflection.fromClass(chunkProvider.getClass(), false).getField(
FuzzyFieldContract.newBuilder().typeExact(chunkMapClass).build()));
}
Object playerChunkMap = chunkMapField.get(chunkProvider);
if (trackedEntitiesField == null) {
trackedEntitiesField = Accessors.getFieldAccessor(
FuzzyReflection.fromClass(playerChunkMap.getClass(), false).getField(
FuzzyFieldContract.newBuilder().typeDerivedOf(Map.class).nameExact("trackedEntities").build()));
}
Map<Integer, Object> trackedEntities = (Map<Integer, Object>) trackedEntitiesField.get(playerChunkMap);
return trackedEntities.get(entityId);
}
private Object getEntityTrackerEntry(World world, int entityID) {
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
Object worldServer = unwrapper.unwrapItem(world);
if (NEW_TRACKER) {
return getNewEntityTracker(worldServer, entityID);
}
if (entityTrackerField == null)
entityTrackerField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(worldServer).
getFieldByType("tracker", MinecraftReflection.getEntityTrackerClass()));
// Get the tracker
Object tracker = entityTrackerField.get(worldServer);
// Looking for an IntHashMap in the tracker entry
if (trackedEntitiesField == null) {
trackedEntitiesField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(tracker, false)
.getFieldByType("trackedEntities", MinecraftReflection.getIntHashMapClass()));
}
// Read the map
Object trackedEntities = trackedEntitiesField.get(tracker);
return WrappedIntHashMap.fromHandle(trackedEntities).get(entityID);
}
private Map<Class<?>, FieldAccessor> trackerFields = new ConcurrentHashMap<>();
private MethodAccessor getEntityFromId;
/**
* Retrieve entity from a ID, even it it's newly created.
* @return The associated entity.
* @throws FieldAccessException Reflection error.
*/
public Entity getEntityFromID(World world, int entityID) {
Validate.notNull(world, "world cannot be null");
Validate.isTrue(entityID >= 0, "entityID cannot be negative");
try {
// first, try to read from the world
// this should be good enough for most cases, but only exists in 1.14+
if (NEW_TRACKER) {
Object worldServer = BukkitUnwrapper.getInstance().unwrapItem(world);
if (getEntityFromId == null) {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(worldServer.getClass(), false);
getEntityFromId = Accessors.getMethodAccessor(fuzzy.getMethod(FuzzyMethodContract.newBuilder()
.parameterExactArray(int.class)
.returnTypeExact(MinecraftReflection.getEntityClass())
.build()));
}
Object entity = getEntityFromId.invoke(worldServer, entityID);
if (entity != null) {
return (Entity) MinecraftReflection.getBukkitEntity(entity);
}
}
// then go into the trackers
Object trackerEntry = getEntityTrackerEntry(world, entityID);
Object tracker = null;
if (trackerEntry != null) {
// plugins like citizens will use their own tracker
FieldAccessor trackerField = trackerFields.computeIfAbsent(trackerEntry.getClass(), x -> {
try {
return Accessors.getFieldAccessor(trackerEntry.getClass(), "tracker", true);
} catch (Exception e) {
// Assume it's the first entity field then
return Accessors.getFieldAccessor(FuzzyReflection.fromObject(trackerEntry, true)
.getFieldByType("tracker", MinecraftReflection.getEntityClass()));
}
});
tracker = trackerField.get(trackerEntry);
}
// If the tracker is NULL, we'll just assume this entity doesn't exist
return tracker != null ? (Entity) MinecraftReflection.getBukkitEntity(tracker) : null;
} catch (Exception e) {
throw new FieldAccessException("Cannot find entity from ID " + entityID + ".", e);
}
}
private List<Object> unwrapBukkit(List<Player> players) {
List<Object> output = Lists.newArrayList();
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
// Get the NMS equivalent
for (Player player : players) {
Object result = unwrapper.unwrapItem(player);
if (result != null)
output.add(result);
else
throw new IllegalArgumentException("Cannot unwrap item " + player);
}
return output;
}
}
@@ -56,8 +56,6 @@ import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import io.netty.channel.Channel;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -74,6 +72,8 @@ import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import io.netty.channel.Channel;
public final class PacketFilterManager implements ListenerInvoker, InternalManager {
public static final ReportType REPORT_CANNOT_LOAD_PACKET_LIST = new ReportType("Cannot load server and client packet list.");
@@ -924,17 +924,17 @@ public final class PacketFilterManager implements ListenerInvoker, InternalManag
@Override
public void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
EntityUtilities.updateEntity(entity, observers);
EntityUtilities.getInstance().updateEntity(entity, observers);
}
@Override
public Entity getEntityFromID(World container, int id) throws FieldAccessException {
return EntityUtilities.getEntityFromID(container, id);
return EntityUtilities.getInstance().getEntityFromID(container, id);
}
@Override
public List<Player> getEntityTrackers(Entity entity) throws FieldAccessException {
return EntityUtilities.getEntityTrackers(entity);
return EntityUtilities.getInstance().getEntityTrackers(entity);
}
/**
Loaded 100 of 336 files, more files were not shown because too many files have changed in this diff. Show more