Compare commits

...
46 Commits
Author SHA1 Message Date
retrooper 8f7ec3d38a PacketEvents 2.1.0 release 2023-11-27 19:18:01 +01:00
retrooper 41969994b2 EntityMetadataProvider has been added, to allow potential packetevents addons to add on to our metadata abstraction. 2023-11-27 19:01:12 +01:00
retrooper 4a2146d16d Merge pull request #622 from rexlManu/2.0
Relocate only the gson and legacy
2023-11-16 20:02:18 +01:00
Emmanuel Lampe 079a2fcc53 Relocate kyori legacy and gson separate for bungeecord 2023-11-15 03:17:02 +01:00
Emmanuel Lampe b9d4ed6a60 Relocate kyori legacy and gson separate 2023-11-15 03:16:09 +01:00
retrooper aec45f19e4 Merge pull request #619 from KaspianDev/fix-merchantoffers
Fix merchant offers always being empty
2023-11-10 17:17:31 +01:00
KaspianDev 0aaa4f42b1 Fix merchant offers always being empty 2023-11-10 16:52:49 +01:00
retrooper 75dfc63d3b Merge pull request #618 from SoSeDiK/blockId
Expose block id to BaseChunk
2023-11-07 18:34:37 +01:00
retrooper ac501a26b2 Fix the way we access NetworkManager (recent server builds have changed it) 2023-11-04 23:03:23 +01:00
SoSeDiK 3ebf39d3bd Expose block id to BaseChunk 2023-11-03 21:17:20 +02:00
retrooper 363931875f Stop depending on funkemunky jars. 2023-11-01 11:11:55 +01:00
retrooper b1802fbc0c Merge pull request #613 from 4drian3d/velocity-changes
Some Velocity module improvements
2023-11-01 10:30:18 +01:00
retrooper 9f9cdca53a Fix connection state issues and casting issues with events 2023-11-01 10:29:27 +01:00
Adrian 00c85f3e41 Some Velocity module improvements
- Removed PostOrder LATE usage
- Use Injected PluginContainer
- Disabled debug mode by default
- Replace deprecated method
2023-10-17 10:36:18 -05:00
retrooper b48a91bcee PotionTypes.getById works now 2023-10-11 19:18:47 +02:00
retrooper 709edd8b21 Merge pull request #610 from AbhigyaKrishna/2.0
Retain backward compatibility with adventure 5.0.0
2023-10-11 18:57:45 +02:00
retrooper 90edf6002e PotionTypes now requires a version to work correctly. 2023-10-11 18:04:30 +02:00
retrooper 4e151f8dfb Pushing out 2.1.0 snapshot for 1.20.2 update 2023-10-07 17:14:07 +02:00
retrooper 0165e8a4ac Merge pull request #607 from booky10/dev/1.20.2
1.20.2 update
2023-10-06 23:48:39 +02:00
retrooper 385000b608 * Add full support for PacketConfigReceive & SendEvent
* WrapperConfigClientClientSettings renamed to WrapperConfigClientSettings
2023-10-06 23:42:54 +02:00
booky10 a1b7c947a0 Use ServerVersion instead of ClientVersion for potion effects 2023-10-03 14:58:31 +02:00
Abhigya ab5163bc66 Retain backward compatibility with adventure 5.0.0 2023-10-02 00:41:27 +05:30
booky10 38b25b6d48 Fix wrapper name for debug pong packet
It's not chunk related, just a copy-paste error
2023-09-27 22:42:25 +02:00
booky10 9d5d4858cf Fix blockstate mappings index 2023-09-23 00:48:32 +02:00
booky10 2e6c43ba06 Extract dimension information from registry data packet instead of login packet 2023-09-22 20:32:30 +02:00
booky10 f180a4a172 Fix packet wrapper constructor parameter types 2023-09-22 20:31:56 +02:00
booky10 5ce6b8bf9e Fix missing clientbound configuration packettype 2023-09-22 20:24:22 +02:00
booky10 b61602741b Rebase on latest changes 2023-09-22 20:24:08 +02:00
booky10 13ba9e7b81 Switch protocol after receiving signaling packet 2023-09-22 20:18:00 +02:00
booky10 d4c9444fd5 Separate encoder and decoder protocol state 2023-09-22 20:17:11 +02:00
booky10 b6c079af66 Add packet wrappers for nearly all new packets in 1.20.2
Only one missing is tags update, which already didn't have a wrapper before
2023-09-22 20:17:11 +02:00
booky10 a18d288079 Update packet structures for 1.20.2 2023-09-22 20:17:09 +02:00
booky10 c3d8f91e85 Update all mappings for 1.20.2 2023-09-22 20:16:37 +02:00
retrooper 0ca2f5c50a Minor tweaks to velocity (update api) 2023-09-22 15:21:47 +02:00
retrooper cdc7ed36e0 PacketEvents 2.0.2 update 2023-09-13 16:01:41 +02:00
retrooper 5d63308a22 Delete WrapperPlayServerChunkData default values 2023-09-13 15:36:20 +02:00
retrooper 214706dbb6 Fix update checker colors 2023-09-12 00:59:18 +02:00
retrooper fa3b563c70 2.0.1 release 2023-09-12 00:36:31 +02:00
retrooper 55e31483e7 Changes to naming of WrapperPlayServerHurtAnimation 2023-09-12 00:02:38 +02:00
retrooper aa34910468 Update User#getWorldNBT usages to handle a nullable value. 2023-09-11 23:35:11 +02:00
retrooper 5e44913a5e Sending packets on proxies is now supported!
* ChannelInjector#isProxy added to detect if our implementation is running on a proxy
2023-08-31 20:25:27 +02:00
retrooper b8dc964112 Add jenkins builds on README 2023-08-31 10:40:57 +02:00
retrooper 890844fb60 Fix broken link in README 2023-08-31 10:40:08 +02:00
retrooper fc57c9e077 Update README 2023-08-31 09:46:32 +02:00
retrooper f12ef113aa Fixed packet-modification on BungeeCord. 2023-08-26 22:35:29 +02:00
retrooper e8144ece97 Minor fix to 1.12 item type mappings. 2023-08-24 18:42:48 +02:00
93 changed files with 26918 additions and 302 deletions

No files matched your search

+5 -12
View File
@@ -1,15 +1,17 @@
# packetevents
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
[![](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://github.com/retrooper/packetevents/blob/2.0/LICENSE) [![](https://github.com/retrooper/packetevents/actions/workflows/build.yml/badge.svg)](https://github.com/retrooper/packetevents/actions) [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/prqzNg9tRU)
PacketEvents is a fast and efficient multi-platform packet processing library. Our packet wrappers are easy to use with multi-version support. With our API you can write code that runs on Spigot, BungeeCord, Velocity, and Fabric! Switch to PacketEvents today by joining \
our [Discord Server](https://discord.me/packetevents) for help.
### Links
* [Find release builds on SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
* [Find release builds on Modrinth](https://modrinth.com/plugin/packetevents)
* [Find development builds on Jenkins](https://ci.codemc.io/job/retrooper/job/packetevents)
* [View documentation on our JavaDocs Page](https://packetevents.github.io/javadocs)
### Setup
[Learn more](https://github.com/retrooper/packetevents/wiki/Setup-2.0)
[How to Setup PacketEvents](https://github.com/retrooper/packetevents/wiki/Depending-on-pre%E2%80%90built-PacketEvents)
### Sponsorships
[![](https://www.ej-technologies.com/images/product_banners/jprofiler_small.png)](https://www.ej-technologies.com/products/jprofiler/overview.html)
@@ -18,15 +20,6 @@ our [Discord Server](https://discord.me/packetevents) for help.
PacketEvents optionally collects statistics using [bStats](https://bstats.org/)\
Check out our [bStats page](https://bstats.org/plugin/bukkit/packetevents/11327)
This library is licensed under the GPLv3 (General Public License version 3). Here are a few sources to learn more about the license.\
[![](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)](https://github.com/retrooper/packetevents/blob/2.0/LICENSE)
### GPL Resources
* https://www.gnu.org/philosophy/free-sw.html
* https://www.gnu.org/philosophy/free-sw.html#clarifying
* https://www.gnu.org/licenses/copyleft.en.html
* https://www.gnu.org/licenses/quick-guide-gplv3.html
* https://gpl-violations.org/faq/sourcecode-faq/
### Credit to these projects
[wiki.vg/Protocol](https://wiki.vg/Protocol)\
[netty](https://github.com/netty/netty)\
@@ -38,7 +38,7 @@ public abstract class PacketEventsAPI<T> {
private final Logger LOGGER = Logger.getLogger(PacketEventsAPI.class.getName());
private static final LogManager LOG_MANAGER = new LogManager();
//TODO UPDATE
private static final PEVersion VERSION = new PEVersion(2, 0, 0);
private static final PEVersion VERSION = new PEVersion(2, 1, 0);
public EventManager getEventManager() {
return EVENT_MANAGER;
@@ -47,20 +47,13 @@ public class PacketReceiveEvent extends ProtocolPacketEvent<Object> {
@Override
public PacketReceiveEvent clone() {
if (this instanceof PacketHandshakeReceiveEvent) {
return ((PacketHandshakeReceiveEvent)this).clone();
}
else if (this instanceof PacketStatusReceiveEvent) {
return ((PacketStatusReceiveEvent)this).clone();
}
else if (this instanceof PacketLoginReceiveEvent) {
return ((PacketLoginReceiveEvent)this).clone();
}
else if (this instanceof PacketPlayReceiveEvent) {
return ((PacketPlayReceiveEvent)this).clone();
}
else {
return null;
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketReceiveEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -18,11 +18,10 @@
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.event.simple.PacketLoginSendEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
import com.github.retrooper.packetevents.event.simple.PacketStatusSendEvent;
import com.github.retrooper.packetevents.event.simple.PacketHandshakeSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
@@ -32,6 +31,7 @@ import java.util.List;
public class PacketSendEvent extends ProtocolPacketEvent<Object> {
private List<Runnable> tasksAfterSend = null;
protected PacketSendEvent(Object channel, User user, Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(PacketSide.SERVER, channel, user, player, rawByteBuf, autoProtocolTranslation);
@@ -65,17 +65,13 @@ public class PacketSendEvent extends ProtocolPacketEvent<Object> {
@Override
public PacketSendEvent clone() {
if (this instanceof PacketStatusSendEvent) {
return ((PacketStatusSendEvent)this).clone();
}
else if (this instanceof PacketLoginSendEvent) {
return ((PacketLoginSendEvent)this).clone();
}
else if (this instanceof PacketPlaySendEvent) {
return ((PacketPlaySendEvent)this).clone();
}
else {
return null;
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketSendEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -78,16 +78,17 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
throw new PacketProcessException("Failed to read the Packet ID of a packet. (Size: " + size + ")");
}
ClientVersion version = serverVersion.toClientVersion();
this.packetType = PacketType.getById(packetSide, user.getConnectionState(),
ConnectionState state = packetSide == PacketSide.CLIENT ? user.getDecoderState() : user.getEncoderState();
this.packetType = PacketType.getById(packetSide, state,
version, packetID);
if (this.packetType == null) {
// mojang fucked up and keeps sending disconnect packets in the wrong protocol state
// mojang messed up and keeps sending disconnect packets in the wrong protocol state
if (PacketType.getById(packetSide, ConnectionState.PLAY, version, packetID) == PacketType.Play.Server.DISCONNECT) {
throw new InvalidDisconnectPacketSend();
}
throw new PacketProcessException("Failed to map the Packet ID " + packetID + " to a PacketType constant. Bound: " + packetSide.getOpposite() + ", Connection state: " + user.getConnectionState() + ", Server version: " + serverVersion.getReleaseName());
throw new PacketProcessException("Failed to map the Packet ID " + packetID + " to a PacketType constant. Bound: " + packetSide.getOpposite() + ", Connection state: " + user.getDecoderState() + ", Server version: " + serverVersion.getReleaseName());
}
this.connectionState = user.getConnectionState();
this.connectionState = state;
}
public ProtocolPacketEvent(int packetID, PacketTypeCommon packetType, ServerVersion serverVersion, Object channel,
@@ -99,7 +100,9 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
this.byteBuf = byteBuf;
this.packetID = packetID;
this.packetType = packetType;
this.connectionState = user.getConnectionState();
this.connectionState = (packetType != null && packetType.getSide() == PacketSide.SERVER)
? user.getEncoderState() : user.getDecoderState();
cloned = true;
}
@@ -166,7 +169,6 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
this.byteBuf = byteBuf;
}
@Deprecated
public int getPacketId() {
return packetID;
}
@@ -41,7 +41,11 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
onPacketStatusReceive((PacketStatusReceiveEvent) event);
} else if (event instanceof PacketLoginReceiveEvent) {
onPacketLoginReceive((PacketLoginReceiveEvent) event);
} else if (event instanceof PacketPlayReceiveEvent) {
}
else if (event instanceof PacketConfigReceiveEvent) {
onPacketConfigReceive((PacketConfigReceiveEvent) event);
}
else if (event instanceof PacketPlayReceiveEvent) {
onPacketPlayReceive((PacketPlayReceiveEvent) event);
}
}
@@ -52,7 +56,11 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
onPacketStatusSend((PacketStatusSendEvent) event);
} else if (event instanceof PacketLoginSendEvent) {
onPacketLoginSend((PacketLoginSendEvent) event);
} else if (event instanceof PacketPlaySendEvent) {
}
else if (event instanceof PacketConfigSendEvent) {
onPacketConfigSend((PacketConfigSendEvent) event);
}
else if (event instanceof PacketPlaySendEvent) {
onPacketPlaySend((PacketPlaySendEvent) event);
}
}
@@ -72,6 +80,12 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
public void onPacketLoginSend(PacketLoginSendEvent event) {
}
public void onPacketConfigReceive(PacketConfigReceiveEvent event) {
}
public void onPacketConfigSend(PacketConfigSendEvent event) {
}
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
}
@@ -0,0 +1,59 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.event.simple;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
public class PacketConfigReceiveEvent extends PacketReceiveEvent {
public PacketConfigReceiveEvent(Object channel, User user,
Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(channel, user, player, rawByteBuf, autoProtocolTranslation);
}
protected PacketConfigReceiveEvent(int packetId, PacketTypeCommon packetType,
ServerVersion serverVersion,
Object channel,
User user, Object player, Object byteBuf) throws PacketProcessException {
super(packetId, packetType, serverVersion, channel, user, player, byteBuf);
}
@Override
public PacketConfigReceiveEvent clone() {
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketConfigReceiveEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
public PacketType.Configuration.Client getPacketType() {
return (PacketType.Configuration.Client) super.getPacketType();
}
}
@@ -0,0 +1,59 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.event.simple;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
public class PacketConfigSendEvent extends PacketSendEvent {
public PacketConfigSendEvent(Object channel, User user,
Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(channel, user, player, rawByteBuf, autoProtocolTranslation);
}
protected PacketConfigSendEvent(int packetId, PacketTypeCommon packetType,
ServerVersion serverVersion,
Object channel,
User user, Object player, Object byteBuf) throws PacketProcessException {
super(packetId, packetType, serverVersion, channel, user, player, byteBuf);
}
@Override
public PacketConfigSendEvent clone() {
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketConfigSendEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
public PacketType.Configuration.Server getPacketType() {
return (PacketType.Configuration.Server) super.getPacketType();
}
}
@@ -32,4 +32,6 @@ public interface ChannelInjector {
void updateUser(Object channel, User user);
void setPlayer(Object channel, Object player);
boolean isProxy();
}
@@ -32,6 +32,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData;
import com.github.retrooper.packetevents.wrapper.handshaking.client.WrapperHandshakingClientHandshake;
import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerLoginSuccess;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
@@ -71,14 +72,32 @@ public class InternalPacketListener extends PacketListenerAbstract {
PacketEvents.getAPI().getLogManager().debug("Mapped player UUID with their channel.");
//Switch the user's connection state to PLAY, but the variable event.getConnectionState() remains LOGIN
//We switch user state immediately to remain in sync with vanilla, allowing you to send PLAY packets immediately
user.setConnectionState(ConnectionState.PLAY);
PacketEvents.getAPI().getLogManager().debug("Transitioned " + profile.getName() + " into the PLAY state!");
// Switch the user's connection state to new state, but the variable event.getConnectionState() remains LOGIN
// We switch user state immediately to remain in sync with vanilla, allowing you to encode packets immediately
boolean proxy = PacketEvents.getAPI().getInjector().isProxy();
if (proxy ? event.getUser().getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_2)
: event.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else {
user.setConnectionState(ConnectionState.PLAY);
}
}
// Join game can be used to update world height, and sets dimension data
// The server sends dimension information in configuration phase >= 1.20.2
else if (event.getPacketType() == PacketType.Configuration.Server.REGISTRY_DATA) {
WrapperConfigServerRegistryData registryData = new WrapperConfigServerRegistryData(event);
// Store world data
NBTCompound registryDataTag = registryData.getRegistryData();
if (registryDataTag != null) {
NBTList<NBTCompound> list = registryDataTag
.getCompoundTagOrNull("minecraft:dimension_type")
.getCompoundListTagOrNull("value");
user.setWorldNBT(list);
}
}
// The server sends dimension information in login packet for >= 1.17 and < 1.20.2
else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) {
WrapperPlayServerJoinGame joinGame = new WrapperPlayServerJoinGame(event);
user.setEntityId(joinGame.getEntityId());
@@ -87,14 +106,22 @@ public class InternalPacketListener extends PacketListenerAbstract {
return; // Fixed world height, no tags are sent to the client
}
// Store world height
NBTList<NBTCompound> list = joinGame.getDimensionCodec().getCompoundTagOrNull("minecraft:dimension_type").getCompoundListTagOrNull("value");
user.setWorldNBT(list);
// Store world data
NBTCompound dimensionCodec = joinGame.getDimensionCodec();
if (dimensionCodec != null) {
NBTList<NBTCompound> list = dimensionCodec
.getCompoundTagOrNull("minecraft:dimension_type")
.getCompoundListTagOrNull("value");
user.setWorldNBT(list);
}
// Update world height
NBTCompound worldNBT = user.getWorldNBT(joinGame.getDimension().getDimensionName()).getCompoundTagOrNull("element");
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
NBTCompound dimension = user.getWorldNBT(joinGame.getDimension().getDimensionName());
if (dimension != null) {
NBTCompound worldNBT = dimension.getCompoundTagOrNull("element");
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
}
}
// Respawn is used to switch dimensions
@@ -105,9 +132,16 @@ public class InternalPacketListener extends PacketListenerAbstract {
return; // Fixed world height, no tags are sent to the client
}
NBTCompound worldNBT = user.getWorldNBT(respawn.getDimension().getDimensionName()).getCompoundTagOrNull("element"); // This is 1.17+, it always sends the world name
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
NBTCompound dimension = user.getWorldNBT(respawn.getDimension().getDimensionName());
if (dimension != null) {
NBTCompound worldNBT = dimension.getCompoundTagOrNull("element"); // This is 1.17+, it always sends the world name
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
}
} else if (event.getPacketType() == PacketType.Play.Server.CONFIGURATION_START) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Server.CONFIGURATION_END) {
user.setEncoderState(ConnectionState.PLAY);
}
}
@@ -125,7 +159,12 @@ public class InternalPacketListener extends PacketListenerAbstract {
PacketEvents.getAPI().getLogManager().debug("Processed " + address.getHostString() + ":" + address.getPort() + "'s client version. Client Version: " + clientVersion.getReleaseName());
//Transition into LOGIN or STATUS connection state immediately, to remain in sync with vanilla
user.setConnectionState(nextState);
PacketEvents.getAPI().getLogManager().debug("Transitioned " + address.getHostString() + ":" + address.getPort() + " into the " + nextState + " state!");
} else if (event.getPacketType() == PacketType.Login.Client.LOGIN_SUCCESS_ACK) {
user.setDecoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Play.Client.CONFIGURATION_ACK) {
user.setDecoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Client.CONFIGURATION_END_ACK) {
user.setDecoderState(ConnectionState.PLAY);
}
}
}
}
@@ -25,6 +25,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.PacketTransformationUtil;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collection;
import java.util.Map;
@@ -96,13 +97,14 @@ public interface ProtocolManager {
getUser(channel).setClientVersion(version);
}
default Object[] transformWrappers(PacketWrapper<?> wrapper, Object channel) {
@ApiStatus.Internal
default Object[] transformWrappers(PacketWrapper<?> wrapper, Object channel, boolean outgoing) {
//It is possible that our packet transformer util decides to transform one wrapper into multiple packets.
//(Correcting some mistakes on your end)
PacketWrapper<?>[] wrappers = PacketTransformationUtil.transform(wrapper);
Object[] buffers = new Object[wrappers.length];
for (int i = 0; i < wrappers.length; i++) {
wrappers[i].prepareForSend(channel);
wrappers[i].prepareForSend(channel, outgoing);
buffers[i] = wrappers[i].buffer;
// Fix race condition when sending packets to multiple people (due to when the buffer is freed)
wrappers[i].buffer = null;
@@ -111,32 +113,32 @@ public interface ProtocolManager {
}
default void sendPacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, true);
sendPackets(channel, transformed);
}
default void sendPacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, true);
sendPacketsSilently(channel, transformed);
}
default void writePacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, true);
writePackets(channel, transformed);
}
default void writePacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, true);
writePacketsSilently(channel, transformed);
}
default void receivePacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, false);
receivePackets(channel, transformed);
}
default void receivePacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper, channel);
Object[] transformed = transformWrappers(wrapper, channel, false);
receivePacketsSilently(channel, transformed);
}
@@ -48,7 +48,7 @@ public enum ServerVersion {
//1.19.1 and 1.19.2 have the same protocol version
V_1_19(759), V_1_19_1(760), V_1_19_2(760), V_1_19_3(761), V_1_19_4(762),
//1.20 and 1.20.1 have the same protocol version
V_1_20(763), V_1_20_1(763),
V_1_20(763), V_1_20_1(763), V_1_20_2(764),
//TODO UPDATE Add server version constant
ERROR(-1, true);
@@ -23,7 +23,7 @@ package com.github.retrooper.packetevents.protocol;
* @since 1.8
*/
public enum ConnectionState {
HANDSHAKING, STATUS, LOGIN, PLAY;
HANDSHAKING, STATUS, LOGIN, PLAY, CONFIGURATION;
public static ConnectionState getById(int id) {
if (id >= values().length || id < 0) {
@@ -0,0 +1,7 @@
package com.github.retrooper.packetevents.protocol.entity.data;
import java.util.List;
public interface EntityMetadataProvider {
List<EntityData> entityData();
}
@@ -150,8 +150,9 @@ public class NBTCodec {
public static NBTCompound readNBTFromBuffer(Object byteBuf, ServerVersion serverVersion) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
try {
boolean named = serverVersion.isOlderThan(ServerVersion.V_1_20_2);
return (NBTCompound) DefaultNBTSerializer.INSTANCE.deserializeTag(
new ByteBufInputStream(byteBuf));
new ByteBufInputStream(byteBuf), named);
} catch (IOException e) {
e.printStackTrace();
}
@@ -179,7 +180,8 @@ public class NBTCodec {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
try (ByteBufOutputStream outputStream = new ByteBufOutputStream(byteBuf)) {
if (tag != null) {
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, tag);
boolean named = serverVersion.isOlderThan(ServerVersion.V_1_20_2);
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, tag, named);
} else {
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, NBTEnd.INSTANCE);
}
@@ -47,21 +47,33 @@ public class NBTSerializer<IN, OUT> {
}
public NBT deserializeTag(IN from) throws IOException {
return deserializeTag(from, true);
}
public NBT deserializeTag(IN from, boolean named) throws IOException {
NBTType<?> type = readTagType(from);
if (type == NBTType.END) {
return null;
}
readTagName(from);
if (named) {
readTagName(from);
}
return readTag(from, type);
}
public void serializeTag(OUT to, NBT tag) throws IOException {
serializeTag(to, tag, true);
}
public void serializeTag(OUT to, NBT tag, boolean named) throws IOException {
NBTType<?> type = tag.getType();
writeTagType(to, type);
if (tag.getType() == NBTType.END) {
return;
}
writeTagName(to, "");
if (named) {
writeTagName(to, "");
}
writeTag(to, tag);
}
@@ -52,7 +52,8 @@ public final class PacketType {
ClientVersion.V_1_19,
ClientVersion.V_1_19_1,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4);
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2);
//TODO UPDATE Update packet type mappings (serverbound pt. 1)
private static final VersionMapper SERVERBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
@@ -70,7 +71,8 @@ public final class PacketType {
ClientVersion.V_1_19,
ClientVersion.V_1_19_1,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4);
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2);
public static void prepare() {
PacketType.Play.Client.load();
@@ -108,6 +110,12 @@ public final class PacketType {
} else {
return Play.Server.getById(version, packetID);
}
case CONFIGURATION:
if (side == PacketSide.CLIENT) {
return Configuration.Client.getById(packetID);
} else {
return Configuration.Server.getById(packetID);
}
default:
return null;
}
@@ -142,6 +150,11 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
@@ -161,6 +174,11 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
@@ -189,6 +207,12 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
@@ -215,6 +239,11 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
@@ -223,7 +252,9 @@ public final class PacketType {
LOGIN_START(0),
ENCRYPTION_RESPONSE(1),
///Added in 1.13
LOGIN_PLUGIN_RESPONSE(2);
LOGIN_PLUGIN_RESPONSE(2),
//Added in 1.20.2
LOGIN_SUCCESS_ACK(3);
private final int id;
@@ -239,6 +270,8 @@ public final class PacketType {
return ENCRYPTION_RESPONSE;
} else if (packetID == 2) {
return LOGIN_PLUGIN_RESPONSE;
} else if (packetID == 3) {
return LOGIN_SUCCESS_ACK;
} else {
return null;
}
@@ -247,6 +280,11 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
@@ -285,6 +323,114 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
// Added in 1.20.2
public static class Configuration {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
CLIENT_SETTINGS(0x00),
PLUGIN_MESSAGE(0x01),
CONFIGURATION_END_ACK(0x02),
KEEP_ALIVE(0x03),
PONG(0x04),
RESOURCE_PACK_STATUS(0x05);
private final int id;
Client(int id) {
this.id = id;
}
public static @Nullable PacketTypeCommon getById(int packetId) {
switch (packetId) {
case 0x00:
return CLIENT_SETTINGS;
case 0x01:
return PLUGIN_MESSAGE;
case 0x02:
return CONFIGURATION_END_ACK;
case 0x03:
return KEEP_ALIVE;
case 0x04:
return PONG;
case 0x05:
return RESOURCE_PACK_STATUS;
default:
return null;
}
}
@Override
public int getId() {
return this.id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
PLUGIN_MESSAGE(0x00),
DISCONNECT(0x01),
CONFIGURATION_END(0x02),
KEEP_ALIVE(0x03),
PING(0x04),
REGISTRY_DATA(0x05),
RESOURCE_PACK_SEND(0x06),
UPDATE_ENABLED_FEATURES(0x07),
UPDATE_TAGS(0x08);
private final int id;
Server(int id) {
this.id = id;
}
public static @Nullable PacketTypeCommon getById(int packetId) {
switch (packetId) {
case 0x00:
return PLUGIN_MESSAGE;
case 0x01:
return DISCONNECT;
case 0x02:
return CONFIGURATION_END;
case 0x03:
return KEEP_ALIVE;
case 0x04:
return PING;
case 0x05:
return REGISTRY_DATA;
case 0x06:
return RESOURCE_PACK_SEND;
case 0x07:
return UPDATE_ENABLED_FEATURES;
case 0x08:
return UPDATE_TAGS;
default:
return null;
}
}
@Override
public int getId() {
return this.id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
}
@@ -348,8 +494,11 @@ public final class PacketType {
//Added in 1.19.1
CHAT_ACK,
//Added in 1.19.3
CHAT_SESSION_UPDATE;
CHAT_SESSION_UPDATE,
//Added in 1.20.2
CHUNK_BATCH_ACK,
CONFIGURATION_ACK,
DEBUG_PING;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -400,6 +549,7 @@ public final class PacketType {
loadPacketIds(ServerboundPacketType_1_19_1.values());
loadPacketIds(ServerboundPacketType_1_19_3.values());
loadPacketIds(ServerboundPacketType_1_19_4.values());
loadPacketIds(ServerboundPacketType_1_20_2.values());
//TODO UPDATE Update packet type mappings (serverbound pt. 2)
}
@@ -410,6 +560,11 @@ public final class PacketType {
int index = SERVERBOUND_PLAY_VERSION_MAPPER.getIndex(version);
return ids[index];
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeCommon, ClientBoundPacket {
@@ -433,12 +588,13 @@ public final class PacketType {
PLAYER_CHAT_HEADER,
PLAYER_INFO,
DISPLAY_CHAT_PREVIEW,
UPDATE_ENABLED_FEATURES,
SPAWN_PLAYER,
//Okay these are normal ones
WINDOW_CONFIRMATION,
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
SPAWN_PLAYER,
ENTITY_ANIMATION,
STATISTICS,
BLOCK_BREAK_ANIMATION,
@@ -548,12 +704,16 @@ public final class PacketType {
DISGUISED_CHAT,
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
UPDATE_ENABLED_FEATURES,
// 1.19.4
//Added in 1.19.4
DAMAGE_EVENT,
HURT_ANIMATION,
BUNDLE,
CHUNK_BIOMES;
CHUNK_BIOMES,
//Added in 1.20.2
CHUNK_BATCH_END,
CHUNK_BATCH_BEGIN,
DEBUG_PONG,
CONFIGURATION_START;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -582,6 +742,11 @@ public final class PacketType {
return map.get(packetId);
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
private static void loadPacketIds(Enum<?>[] enumConstants) {
int index = INDEX;
for (Enum<?> constant : enumConstants) {
@@ -615,6 +780,7 @@ public final class PacketType {
loadPacketIds(ClientboundPacketType_1_19_1.values());
loadPacketIds(ClientboundPacketType_1_19_3.values());
loadPacketIds(ClientboundPacketType_1_19_4.values());
loadPacketIds(ClientboundPacketType_1_20_2.values());
//TODO UPDATE Update packet type mappings (clientbound pt. 2)
}
}
@@ -18,6 +18,7 @@
package com.github.retrooper.packetevents.protocol.packettype;
import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
public interface PacketTypeCommon {
@@ -27,4 +28,6 @@ public interface PacketTypeCommon {
}
int getId(ClientVersion version);
PacketSide getSide();
}
@@ -0,0 +1,137 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.packettype.clientbound;
public enum ClientboundPacketType_1_20_2 {
BUNDLE,
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
ENTITY_ANIMATION,
STATISTICS,
ACKNOWLEDGE_BLOCK_CHANGES,
BLOCK_BREAK_ANIMATION,
BLOCK_ENTITY_DATA,
BLOCK_ACTION,
BLOCK_CHANGE,
BOSS_BAR,
SERVER_DIFFICULTY,
CHUNK_BATCH_END, // New packet
CHUNK_BATCH_BEGIN, // New packet
CHUNK_BIOMES,
CLEAR_TITLES,
TAB_COMPLETE,
DECLARE_COMMANDS,
CLOSE_WINDOW,
WINDOW_ITEMS,
WINDOW_PROPERTY,
SET_SLOT,
SET_COOLDOWN,
CUSTOM_CHAT_COMPLETIONS,
PLUGIN_MESSAGE,
DAMAGE_EVENT,
DELETE_CHAT,
DISCONNECT,
DISGUISED_CHAT,
ENTITY_STATUS,
EXPLOSION,
UNLOAD_CHUNK,
CHANGE_GAME_STATE,
OPEN_HORSE_WINDOW,
HURT_ANIMATION,
INITIALIZE_WORLD_BORDER,
KEEP_ALIVE,
CHUNK_DATA,
EFFECT,
PARTICLE,
UPDATE_LIGHT,
JOIN_GAME,
MAP_DATA,
MERCHANT_OFFERS,
ENTITY_RELATIVE_MOVE,
ENTITY_RELATIVE_MOVE_AND_ROTATION,
ENTITY_ROTATION,
VEHICLE_MOVE,
OPEN_BOOK,
OPEN_WINDOW,
OPEN_SIGN_EDITOR,
PING,
DEBUG_PONG, // New packet
CRAFT_RECIPE_RESPONSE,
PLAYER_ABILITIES,
CHAT_MESSAGE,
END_COMBAT_EVENT,
ENTER_COMBAT_EVENT,
DEATH_COMBAT_EVENT,
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
FACE_PLAYER,
PLAYER_POSITION_AND_LOOK,
UNLOCK_RECIPES,
DESTROY_ENTITIES,
REMOVE_ENTITY_EFFECT,
RESOURCE_PACK_SEND,
RESPAWN,
ENTITY_HEAD_LOOK,
MULTI_BLOCK_CHANGE,
SELECT_ADVANCEMENTS_TAB,
SERVER_DATA,
ACTION_BAR,
WORLD_BORDER_CENTER,
WORLD_BORDER_LERP_SIZE,
WORLD_BORDER_SIZE,
WORLD_BORDER_WARNING_DELAY,
WORLD_BORDER_WARNING_REACH,
CAMERA,
HELD_ITEM_CHANGE,
UPDATE_VIEW_POSITION,
UPDATE_VIEW_DISTANCE,
SPAWN_POSITION,
DISPLAY_SCOREBOARD,
ENTITY_METADATA,
ATTACH_ENTITY,
ENTITY_VELOCITY,
ENTITY_EQUIPMENT,
SET_EXPERIENCE,
UPDATE_HEALTH,
SCOREBOARD_OBJECTIVE,
SET_PASSENGERS,
TEAMS,
UPDATE_SCORE,
UPDATE_SIMULATION_DISTANCE,
SET_TITLE_SUBTITLE,
TIME_UPDATE,
SET_TITLE_TEXT,
SET_TITLE_TIMES,
ENTITY_SOUND_EFFECT,
SOUND_EFFECT,
CONFIGURATION_START, // New packet
STOP_SOUND,
SYSTEM_CHAT_MESSAGE,
PLAYER_LIST_HEADER_AND_FOOTER,
NBT_QUERY_RESPONSE,
COLLECT_ITEM,
ENTITY_TELEPORT,
UPDATE_ADVANCEMENTS,
UPDATE_ATTRIBUTES,
// UPDATE_ENABLED_FEATURES, removed
ENTITY_EFFECT,
DECLARE_RECIPES,
TAGS,
}
@@ -0,0 +1,77 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.packettype.serverbound;
public enum ServerboundPacketType_1_20_2 {
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
CHAT_ACK,
CHAT_COMMAND,
CHAT_MESSAGE,
CHAT_SESSION_UPDATE,
CHUNK_BATCH_ACK, // New packet
CLIENT_STATUS,
CLIENT_SETTINGS,
TAB_COMPLETE,
CONFIGURATION_ACK, // New packet
CLICK_WINDOW_BUTTON,
CLICK_WINDOW,
CLOSE_WINDOW,
PLUGIN_MESSAGE,
EDIT_BOOK,
QUERY_ENTITY_NBT,
INTERACT_ENTITY,
GENERATE_STRUCTURE,
KEEP_ALIVE,
LOCK_DIFFICULTY,
PLAYER_POSITION,
PLAYER_POSITION_AND_ROTATION,
PLAYER_ROTATION,
PLAYER_FLYING,
VEHICLE_MOVE,
STEER_BOAT,
PICK_ITEM,
DEBUG_PING, // New packet
CRAFT_RECIPE_REQUEST,
PLAYER_ABILITIES,
PLAYER_DIGGING,
ENTITY_ACTION,
STEER_VEHICLE,
PONG,
SET_RECIPE_BOOK_STATE,
SET_DISPLAYED_RECIPE,
NAME_ITEM,
RESOURCE_PACK_STATUS,
ADVANCEMENT_TAB,
SELECT_TRADE,
SET_BEACON_EFFECT,
HELD_ITEM_CHANGE,
UPDATE_COMMAND_BLOCK,
UPDATE_COMMAND_BLOCK_MINECART,
CREATIVE_INVENTORY_ACTION,
UPDATE_JIGSAW_BLOCK,
UPDATE_STRUCTURE_BLOCK,
UPDATE_SIGN,
ANIMATION,
SPECTATE,
PLAYER_BLOCK_PLACEMENT,
USE_ITEM,
}
@@ -83,11 +83,12 @@ public enum ClientVersion {
V_1_19_3(761),
V_1_19_4(762),
V_1_20(763),
V_1_20_2(764),
//TODO UPDATE Add new protocol version field
LOWER_THAN_SUPPORTED_VERSIONS(V_1_7_10.protocolVersion - 1, true),
//TODO UPDATE Update HIGHER_THAN_SUPPORTED_VERSIONS field
HIGHER_THAN_SUPPORTED_VERSIONS(V_1_20.protocolVersion + 1, true),
HIGHER_THAN_SUPPORTED_VERSIONS(V_1_20_2.protocolVersion + 1, true),
UNKNOWN(-1, true);
@@ -276,4 +277,4 @@ public enum ClientVersion {
return false;
}
}
}
}
@@ -42,7 +42,8 @@ import java.util.UUID;
public class User {
private final Object channel;
private ConnectionState connectionState;
private ConnectionState decoderState;
private ConnectionState encoderState;
private ClientVersion clientVersion;
private final UserProfile profile;
private int entityId = -1;
@@ -55,7 +56,8 @@ public class User {
ConnectionState connectionState, ClientVersion clientVersion,
UserProfile profile) {
this.channel = channel;
this.connectionState = connectionState;
this.decoderState = connectionState;
this.encoderState = connectionState;
this.clientVersion = clientVersion;
this.profile = profile;
}
@@ -69,11 +71,37 @@ public class User {
}
public ConnectionState getConnectionState() {
return connectionState;
ConnectionState decoderState = this.decoderState;
ConnectionState encoderState = this.encoderState;
if (decoderState != encoderState) {
throw new IllegalArgumentException("Can't get common connection state: " + decoderState + " != " + encoderState);
}
return decoderState;
}
public void setConnectionState(ConnectionState connectionState) {
this.connectionState = connectionState;
this.setDecoderState(connectionState);
this.setEncoderState(connectionState);
}
public ConnectionState getDecoderState() {
return this.decoderState;
}
public void setDecoderState(ConnectionState decoderState) {
this.decoderState = decoderState;
PacketEvents.getAPI().getLogManager().debug(
"Transitioned " + this.getName() + "'s decoder into " + decoderState + " state!");
}
public ConnectionState getEncoderState() {
return this.encoderState;
}
public void setEncoderState(ConnectionState encoderState) {
this.encoderState = encoderState;
PacketEvents.getAPI().getLogManager().debug(
"Transitioned " + this.getName() + "'s encoder into " + encoderState + " state!");
}
public ClientVersion getClientVersion() {
@@ -150,7 +178,8 @@ public class User {
}
public void sendMessage(Component component, ChatType type) {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
ServerVersion version = PacketEvents.getAPI().getInjector().isProxy() ? getClientVersion().toServerVersion() :
PacketEvents.getAPI().getServerManager().getVersion();
PacketWrapper<?> chatPacket;
if (version.isNewerThanOrEquals(ServerVersion.V_1_19)) {
chatPacket = new WrapperPlayServerSystemChatMessage(false, component);
@@ -174,7 +203,9 @@ public class User {
}
public void sendTitle(Component title, Component subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) {
boolean modern = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17);
ServerVersion version = PacketEvents.getAPI().getInjector().isProxy() ? getClientVersion().toServerVersion() :
PacketEvents.getAPI().getServerManager().getVersion();
boolean modern = version.isNewerThanOrEquals(ServerVersion.V_1_17);
PacketWrapper<?> animation;
PacketWrapper<?> setTitle = null;
PacketWrapper<?> setSubtitle = null;
@@ -242,6 +273,9 @@ public class User {
@Nullable
public NBTCompound getWorldNBT(String worldName) {
if (worldNBT == null) {
return null;
}
for (NBTCompound compound : worldNBT) {
if (compound.getStringTagOrNull("name").getValue().equals(worldName)) {
return compound;
@@ -18,8 +18,8 @@
package com.github.retrooper.packetevents.protocol.potion;
import com.github.retrooper.packetevents.protocol.mapper.StaticMappedEntity;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
public interface PotionType extends StaticMappedEntity {
public interface PotionType extends MappedEntity {
}
@@ -18,6 +18,8 @@
package com.github.retrooper.packetevents.protocol.potion;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
@@ -37,14 +39,17 @@ public class PotionTypes {
}
@Override
public int getId() {
public int getId(ClientVersion version) {
if (version.isOlderThan(ClientVersion.V_1_20_2)) {
return id + 1;
}
return id;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PotionType) {
return getId() == ((PotionType)obj).getId();
return getName().equals(((PotionType)obj).getName());
}
return false;
}
@@ -52,7 +57,8 @@ public class PotionTypes {
//minecraft:speed would be a string for example
POTION_TYPE_MAP.put(potionType.getName().toString(), potionType);
POTION_TYPE_ID_MAP.put((byte) potionType.getId(), potionType);
//We map the 1.20.2 IDs
POTION_TYPE_ID_MAP.put((byte) potionType.getId(ClientVersion.V_1_20_2), potionType);
return potionType;
}
@@ -61,42 +67,55 @@ public class PotionTypes {
return POTION_TYPE_MAP.get(name);
}
@Nullable
public static PotionType getById(int id) {
@Deprecated
public static @Nullable PotionType getById(int id) {
return getById(id, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
}
public static @Nullable PotionType getById(int id, com.github.retrooper.packetevents.manager.server.ServerVersion version) {
return getById(id, version.toClientVersion());
}
public static @Nullable PotionType getById(int id, ClientVersion version) {
if (version.isOlderThan(ClientVersion.V_1_20_2)) {
//We map the 1.20.2 values (starting from 0)
//If the version is older than that, we must subtract one from the input ID (cause it starts from 1)
id--; // potion effects ids where shifted by -1 in 1.20.2
}
return POTION_TYPE_ID_MAP.get((byte)id);
}
public static final PotionType SPEED = define("speed", 1);
public static final PotionType SLOWNESS = define("slowness", 2);
public static final PotionType HASTE = define("haste", 3);
public static final PotionType MINING_FATIGUE = define("mining_fatigue", 4);
public static final PotionType STRENGTH = define("strength", 5);
public static final PotionType INSTANT_HEALTH = define("instant_health", 6);
public static final PotionType INSTANT_DAMAGE = define("instant_damage", 7);
public static final PotionType JUMP_BOOST = define("jump_boost", 8);
public static final PotionType NAUSEA = define("nausea", 9);
public static final PotionType REGENERATION = define("regeneration", 10);
public static final PotionType RESISTANCE = define("resistance", 11);
public static final PotionType FIRE_RESISTANCE = define("fire_resistance", 12);
public static final PotionType WATER_BREATHING = define("water_breathing", 13);
public static final PotionType INVISIBILITY = define("invisibility", 14);
public static final PotionType BLINDNESS = define("blindness", 15);
public static final PotionType NIGHT_VISION = define("night_vision", 16);
public static final PotionType HUNGER = define("hunger", 17);
public static final PotionType WEAKNESS = define("weakness", 18);
public static final PotionType POISON = define("poison", 19);
public static final PotionType WITHER = define("wither", 20);
public static final PotionType HEALTH_BOOST = define("health_boost", 21);
public static final PotionType ABSORPTION = define("absorption", 22);
public static final PotionType SATURATION = define("saturation", 23);
public static final PotionType GLOWING = define("glowing", 24);
public static final PotionType LEVITATION = define("levitation", 25);
public static final PotionType LUCK = define("luck", 26);
public static final PotionType UNLUCK = define("unluck", 27);
public static final PotionType SLOW_FALLING = define("slow_falling", 28);
public static final PotionType CONDUIT_POWER = define("conduit_power", 29);
public static final PotionType DOLPHINS_GRACE = define("dolphins_grace", 30);
public static final PotionType BAD_OMEN = define("bad_omen", 31);
public static final PotionType HERO_OF_THE_VILLAGE = define("hero_of_the_village", 32);
public static final PotionType DARKNESS = define("darkness", 33);
public static final PotionType SPEED = define("speed", 0);
public static final PotionType SLOWNESS = define("slowness", 1);
public static final PotionType HASTE = define("haste", 2);
public static final PotionType MINING_FATIGUE = define("mining_fatigue", 3);
public static final PotionType STRENGTH = define("strength", 4);
public static final PotionType INSTANT_HEALTH = define("instant_health", 5);
public static final PotionType INSTANT_DAMAGE = define("instant_damage", 6);
public static final PotionType JUMP_BOOST = define("jump_boost", 7);
public static final PotionType NAUSEA = define("nausea", 8);
public static final PotionType REGENERATION = define("regeneration", 9);
public static final PotionType RESISTANCE = define("resistance", 10);
public static final PotionType FIRE_RESISTANCE = define("fire_resistance", 11);
public static final PotionType WATER_BREATHING = define("water_breathing", 12);
public static final PotionType INVISIBILITY = define("invisibility", 13);
public static final PotionType BLINDNESS = define("blindness", 14);
public static final PotionType NIGHT_VISION = define("night_vision", 15);
public static final PotionType HUNGER = define("hunger", 16);
public static final PotionType WEAKNESS = define("weakness", 17);
public static final PotionType POISON = define("poison", 18);
public static final PotionType WITHER = define("wither", 19);
public static final PotionType HEALTH_BOOST = define("health_boost", 20);
public static final PotionType ABSORPTION = define("absorption", 21);
public static final PotionType SATURATION = define("saturation", 22);
public static final PotionType GLOWING = define("glowing", 23);
public static final PotionType LEVITATION = define("levitation", 24);
public static final PotionType LUCK = define("luck", 25);
public static final PotionType UNLUCK = define("unluck", 26);
public static final PotionType SLOW_FALLING = define("slow_falling", 27);
public static final PotionType CONDUIT_POWER = define("conduit_power", 28);
public static final PotionType DOLPHINS_GRACE = define("dolphins_grace", 29);
public static final PotionType BAD_OMEN = define("bad_omen", 30);
public static final PotionType HERO_OF_THE_VILLAGE = define("hero_of_the_village", 31);
public static final PotionType DARKNESS = define("darkness", 32);
}
@@ -32,7 +32,11 @@ import com.github.retrooper.packetevents.protocol.world.chunk.storage.LegacyFlex
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
public interface BaseChunk {
WrappedBlockState get(ClientVersion version, int x, int y, int z);
int getBlockId(int x, int y, int z);
default WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, getBlockId(x, y, z));
}
default WrappedBlockState get(int x, int y, int z) {
return get(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), x, y, z);
@@ -84,8 +84,8 @@ public class Chunk_v1_9 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, this.dataPalette.get(x, y, z));
public int getBlockId(int x, int y, int z) {
return this.dataPalette.get(x, y, z);
}
public void set(int x, int y, int z, int state) {
@@ -44,9 +44,8 @@ public class Chunk_v1_7 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
int combinedID = blocks.get(x, y, z) | (extendedBlocks.get(x, y, z) << 12);
return WrappedBlockState.getByGlobalId(version, combinedID);
public int getBlockId(int x, int y, int z) {
return blocks.get(x, y, z) | (extendedBlocks.get(x, y, z) << 12);
}
@Override
@@ -52,9 +52,8 @@ public class Chunk_v1_8 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
int combinedID = this.blocks.get(x, y, z);
return WrappedBlockState.getByGlobalId(version, combinedID);
public int getBlockId(int x, int y, int z) {
return this.blocks.get(x, y, z);
}
@Override
@@ -61,8 +61,8 @@ public class Chunk_v1_18 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, this.chunkData.get(x, y, z));
public int getBlockId(int x, int y, int z) {
return this.chunkData.get(x, y, z);
}
@Override
@@ -157,11 +157,12 @@ public class WrappedBlockState {
return 8;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_3)) {
return 9;
}
else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_4)) {
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_4)) {
return 10;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_20)) {
return 11;
}
return 11;
return 12;
}
private static void loadLegacy() {
@@ -27,7 +27,7 @@ import com.github.retrooper.packetevents.protocol.player.User;
public class EventCreationUtil {
public static PacketReceiveEvent createReceiveEvent(Object channel, User user, Object player, Object buffer,
boolean autoProtocolTranslation) throws PacketProcessException {
switch (user.getConnectionState()) {
switch (user.getDecoderState()) {
case HANDSHAKING:
return new PacketHandshakeReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
case STATUS:
@@ -36,13 +36,15 @@ public class EventCreationUtil {
return new PacketLoginReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
case PLAY:
return new PacketPlayReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
case CONFIGURATION:
return new PacketConfigReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
}
throw new RuntimeException("Unknown connection state " + user.getConnectionState() + "!");
throw new RuntimeException("Unknown connection state " + user.getDecoderState() + "!");
}
public static PacketSendEvent createSendEvent(Object channel, User user, Object player, Object buffer,
boolean autoProtocolTranslation) throws PacketProcessException{
switch (user.getConnectionState()) {
switch (user.getEncoderState()) {
case HANDSHAKING:
return new PacketHandshakeSendEvent(channel, user, player, buffer, autoProtocolTranslation);
case STATUS:
@@ -51,7 +53,9 @@ public class EventCreationUtil {
return new PacketLoginSendEvent(channel, user, player, buffer, autoProtocolTranslation);
case PLAY:
return new PacketPlaySendEvent(channel, user, player, buffer, autoProtocolTranslation);
case CONFIGURATION:
return new PacketConfigSendEvent(channel, user, player, buffer, autoProtocolTranslation);
}
throw new RuntimeException("Unknown connection state " + user.getConnectionState() + "!");
throw new RuntimeException("Unknown connection state " + user.getEncoderState() + "!");
}
}
@@ -32,6 +32,7 @@ import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.util.Codec;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.io.IOException;
import java.util.Locale;
@@ -43,8 +44,7 @@ import java.util.regex.Pattern;
public class HoverSerializer {
private static final TagStringIO SNBT_IO = TagStringIO.get();
// Have to change this in upcoming adventure version
private static final Codec<CompoundBinaryTag, String, IOException, IOException> SNBT_CODEC = Codec.of(SNBT_IO::asCompound, SNBT_IO::asString);
private static final Codec<CompoundBinaryTag, String, IOException, IOException> SNBT_CODEC = createCodec(SNBT_IO::asCompound, SNBT_IO::asString);
static final String ITEM_TYPE = "id";
static final String ITEM_COUNT = "Count";
@@ -61,7 +61,7 @@ public class HoverSerializer {
assertTextComponent(component);
final CompoundBinaryTag contents = SNBT_CODEC.decode(((TextComponent) component).content());
final CompoundBinaryTag tag = contents.getCompound(ITEM_TAG);
return HoverEvent.ShowItem.of(
return createShowItem(
Key.key(contents.getString(ITEM_TYPE)),
contents.getByte(ITEM_COUNT, (byte) 1),
tag == CompoundBinaryTag.empty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
@@ -86,7 +86,7 @@ public class HoverSerializer {
}
type = joiner.toString().toLowerCase(Locale.ROOT);
}
return HoverEvent.ShowEntity.of(
return createShowEntity(
Key.key(type),
UUID.fromString(contents.getString(ENTITY_ID)),
componentCodec.decode(contents.getString(ENTITY_NAME))
@@ -145,4 +145,29 @@ public class HoverSerializer {
}
// Backward Compatibility
private static HoverEvent.ShowItem createShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) {
try {
return HoverEvent.ShowItem.showItem(item, count, nbt);
} catch (final NoSuchMethodError ignored) {
return HoverEvent.ShowItem.of(item, count, nbt);
}
}
private static HoverEvent.ShowEntity createShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) {
try {
return HoverEvent.ShowEntity.showEntity(type, id, name);
} catch (final NoSuchMethodError ignored) {
return HoverEvent.ShowEntity.of(type, id, name);
}
}
private static <D, E, DX extends Throwable, EX extends Throwable> @NotNull Codec<D, E, DX, EX> createCodec(final @NotNull Codec.Decoder<D, E, DX> decoder, final @NotNull Codec.Encoder<D, E, EX> encoder) {
try {
return Codec.codec(decoder, encoder);
} catch (final NoSuchMethodError ignored) {
return Codec.of(decoder, encoder);
}
}
}
@@ -69,7 +69,7 @@ public class UpdateChecker {
+ ColorUtil.toString(NamedTextColor.YELLOW) + localVersion
+ ColorUtil.toString(NamedTextColor.WHITE) + ") | Latest released build: ("
+ ColorUtil.toString(NamedTextColor.GREEN) + newVersion
+ ColorUtil.toString(NamedTextColor.RED) + ")");
+ ColorUtil.toString(NamedTextColor.WHITE) + ")");
return UpdateCheckerStatus.OUTDATED;
} else if (newVersion != null && localVersion.isNewerThan(newVersion)) {
PacketEvents.getAPI().getLogManager().info("You are on a dev or pre released build of packetevents. Your build: ("
@@ -0,0 +1,48 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import org.jetbrains.annotations.Nullable;
public class PacketTypeData {
private @Nullable PacketTypeCommon packetType;
private int nativePacketId;
public PacketTypeData(@Nullable PacketTypeCommon packetType, int nativePacketId) {
this.packetType = packetType;
this.nativePacketId = nativePacketId;
}
public @Nullable PacketTypeCommon getPacketType() {
return packetType;
}
public int getNativePacketId() {
return nativePacketId;
}
public void setPacketType(@Nullable PacketTypeCommon packetType) {
this.packetType = packetType;
}
public void setNativePacketId(int nativePacketId) {
this.nativePacketId = nativePacketId;
}
}
@@ -26,6 +26,7 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.manager.server.VersionComparison;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.chat.*;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMaskType;
@@ -33,12 +34,14 @@ import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.codec.NBTCodec;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.GameMode;
@@ -55,6 +58,7 @@ import com.github.retrooper.packetevents.util.crypto.MinecraftEncryptionUtil;
import com.github.retrooper.packetevents.util.crypto.SaltSignature;
import com.github.retrooper.packetevents.util.crypto.SignatureData;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.ApiStatus.Experimental;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -73,7 +77,7 @@ public class PacketWrapper<T extends PacketWrapper> {
protected ClientVersion clientVersion;
protected ServerVersion serverVersion;
private int packetID;
private PacketTypeData packetTypeData;
// For sending chunk data packets, which need this data
@Nullable
protected User user;
@@ -88,7 +92,7 @@ public class PacketWrapper<T extends PacketWrapper> {
this.clientVersion = clientVersion;
this.serverVersion = serverVersion;
this.buffer = null;
this.packetID = packetID;
this.packetTypeData = new PacketTypeData(null, packetID);
}
public PacketWrapper(PacketReceiveEvent event) {
@@ -100,7 +104,7 @@ public class PacketWrapper<T extends PacketWrapper> {
this.serverVersion = event.getServerVersion();
this.user = event.getUser();
this.buffer = event.getByteBuf();
this.packetID = event.getPacketId();
this.packetTypeData = new PacketTypeData(event.getPacketType(), event.getPacketId());
if (readData) {
readEvent(event);
}
@@ -114,7 +118,7 @@ public class PacketWrapper<T extends PacketWrapper> {
this.clientVersion = event.getUser().getClientVersion();
this.serverVersion = event.getServerVersion();
this.buffer = event.getByteBuf();
this.packetID = event.getPacketId();
this.packetTypeData = new PacketTypeData(event.getPacketType(), event.getPacketId());
this.user = event.getUser();
if (readData) {
readEvent(event);
@@ -126,13 +130,21 @@ public class PacketWrapper<T extends PacketWrapper> {
}
public PacketWrapper(int packetID) {
this(ClientVersion.UNKNOWN,
PacketEvents.getAPI().getServerManager().getVersion(),
packetID);
if (packetID == -1) {
throw new IllegalArgumentException("Packet does not exist on this protocol version!");
}
this.clientVersion = ClientVersion.UNKNOWN;
this.serverVersion = PacketEvents.getAPI().getServerManager().getVersion();
this.buffer = null;
this.packetTypeData = new PacketTypeData(null, packetID);
}
public PacketWrapper(PacketTypeCommon packetType) {
this(packetType.getId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()));
this.clientVersion = ClientVersion.UNKNOWN;
this.serverVersion = PacketEvents.getAPI().getServerManager().getVersion();
this.buffer = null;
int id = packetType.getId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
this.packetTypeData = new PacketTypeData(packetType, id);
}
public static PacketWrapper<?> createUniversalPacketWrapper(Object byteBuf) {
@@ -141,14 +153,42 @@ public class PacketWrapper<T extends PacketWrapper> {
return wrapper;
}
public final void prepareForSend(Object channel) {
public static int getChunkX(long chunkKey) {
return (int) (chunkKey & 0xFFFFFFFFL);
}
public static int getChunkZ(long chunkKey) {
return (int) ((chunkKey >>> 32) & 0xFFFFFFFFL);
}
public static long getChunkKey(int chunkX, int chunkZ) {
return (long) chunkX & 0xFFFFFFFFL | ((long) chunkZ & 0xFFFFFFFFL) << 32;
}
@ApiStatus.Internal
public final void prepareForSend(Object channel, boolean outgoing) {
// Null means the packet was manually created and wasn't sent by the server itself
// A reference count of 0 means that the packet was freed (it was already sent)
if (buffer == null || ByteBufHelper.refCnt(buffer) == 0) {
buffer = ChannelHelper.pooledByteBuf(channel);
}
writeVarInt(packetID);
//On proxies, we must rewrite the packet ID in a format compatible for the targeted client version
if (PacketEvents.getAPI().getInjector().isProxy()) {
User user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
if (packetTypeData.getPacketType() == null) {
//Get the packet type with the local version packet type mappings.
packetTypeData.setPacketType(PacketType.getById(outgoing ? PacketSide.SERVER : PacketSide.CLIENT,
user.getConnectionState(), serverVersion.toClientVersion(), packetTypeData.getNativePacketId()));
}
//Change local version to user version so that the packet can be processed correctly.
serverVersion = user.getClientVersion().toServerVersion();
int id = packetTypeData.getPacketType().getId(user.getClientVersion());
writeVarInt(id);
}
else {
writeVarInt(packetTypeData.getNativePacketId());
}
write();
}
@@ -197,21 +237,50 @@ public class PacketWrapper<T extends PacketWrapper> {
return buffer;
}
/**
* Gets the Packet ID for the current platform version
* @deprecated Use {@link #getNativePacketId()}
* @return Packet ID
*/
@Deprecated
public int getPacketId() {
return packetID;
return getNativePacketId();
}
/**
* Sets the Packet ID for the current platform version
* @deprecated Use {@link #setNativePacketId(int)}
*/
@Deprecated
public void setPacketId(int packetID) {
this.packetID = packetID;
setNativePacketId(packetID);
}
public int getNativePacketId() {
return packetTypeData.getNativePacketId();
}
public void setNativePacketId(int nativePacketId) {
this.packetTypeData.setNativePacketId(nativePacketId);
}
@ApiStatus.Internal
public PacketTypeData getPacketTypeData() {
return packetTypeData;
}
public int getMaxMessageLength() {
return serverVersion.isNewerThanOrEquals(ServerVersion.V_1_13) ? MODERN_MESSAGE_LENGTH : LEGACY_MESSAGE_LENGTH;
}
@Deprecated
public void resetByteBuf() {
ByteBufHelper.clear(buffer);
writeVarInt(packetID);
}
public void resetBuffer() {
ByteBufHelper.clear(buffer);
}
public byte readByte() {
@@ -342,14 +411,11 @@ public class PacketWrapper<T extends PacketWrapper> {
writeNBT(itemStack.getNBT());
}
} else {
int typeID;
if (itemStack.isEmpty()) {
typeID = -1;
writeShort(-1);
} else {
typeID = itemStack.getType().getId(serverVersion.toClientVersion());
}
writeShort(typeID);
if (typeID >= 0) {
int typeID = itemStack.getType().getId(serverVersion.toClientVersion());
writeShort(typeID);
writeByte(itemStack.getAmount());
writeShort(itemStack.getLegacyData());
writeNBT(itemStack.getNBT());
@@ -668,9 +734,9 @@ public class PacketWrapper<T extends PacketWrapper> {
list.add(new EntityData(index, type, value));
}
} else {
for (byte data = readByte(); data != 127; data = readByte()) {
int typeID = (data & 224) >> 5;
int index = data & 31;
for (byte data = readByte(); data != Byte.MAX_VALUE; data = readByte()) {
int typeID = (data & 0xE0) >> 5;
int index = data & 0x1F;
EntityDataType<?> type = EntityDataTypes.getById(serverVersion.toClientVersion(), typeID);
Object value = type.getDataDeserializer().apply(this);
EntityData entityData = new EntityData(index, type, value);
@@ -708,6 +774,10 @@ public class PacketWrapper<T extends PacketWrapper> {
}
}
public void writeEntityMetadata(EntityMetadataProvider metadata) {
writeEntityMetadata(metadata.entityData());
}
public Dimension readDimension() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19)) {
Dimension dimension = new Dimension(new NBTCompound());
@@ -736,12 +806,10 @@ public class PacketWrapper<T extends PacketWrapper> {
//Read optional signature
if (readBoolean()) {
signature = readBytes(256);
}
else {
} else {
signature = new byte[0];
}
}
else {
} else {
signature = readByteArray(256);
}
return new SaltSignature(salt, signature);
@@ -756,8 +824,7 @@ public class PacketWrapper<T extends PacketWrapper> {
writeBytes(signature.getSignature());
}
}
else {
} else {
writeByteArray(signature.getSignature());
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientConfigurationEndAck extends PacketWrapper<WrapperConfigClientConfigurationEndAck> {
public WrapperConfigClientConfigurationEndAck(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientConfigurationEndAck() {
super(PacketType.Configuration.Client.CONFIGURATION_END_ACK);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientKeepAlive extends PacketWrapper<WrapperConfigClientKeepAlive> {
private long id;
public WrapperConfigClientKeepAlive(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientKeepAlive(long id) {
super(PacketType.Configuration.Client.KEEP_ALIVE);
this.id = id;
}
@Override
public void read() {
this.id = this.readLong();
}
@Override
public void write() {
this.writeLong(this.id);
}
@Override
public void copy(WrapperConfigClientKeepAlive wrapper) {
this.id = wrapper.id;
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
}
@@ -0,0 +1,82 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientPluginMessage extends PacketWrapper<WrapperConfigClientPluginMessage> {
private String channelName;
private byte[] data;
public WrapperConfigClientPluginMessage(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientPluginMessage(ResourceLocation channelName, byte[] data) {
this(channelName.toString(), data);
}
public WrapperConfigClientPluginMessage(String channelName, byte[] data) {
super(PacketType.Configuration.Client.PLUGIN_MESSAGE);
this.channelName = channelName;
this.data = data;
}
@Override
public void read() {
this.channelName = this.readString();
if (ByteBufHelper.readableBytes(this.buffer) > 32767) {
throw new RuntimeException("Payload may not be larger than 32767 bytes");
}
this.data = this.readRemainingBytes();
}
@Override
public void write() {
this.writeString(this.channelName);
this.writeBytes(this.data);
}
@Override
public void copy(WrapperConfigClientPluginMessage wrapper) {
this.channelName = wrapper.channelName;
this.data = wrapper.data;
}
public String getChannelName() {
return this.channelName;
}
public void setChannelName(String channelName) {
this.channelName = channelName;
}
public byte[] getData() {
return this.data;
}
public void setData(byte[] data) {
this.data = data;
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientPong extends PacketWrapper<WrapperConfigClientPong> {
private int id;
public WrapperConfigClientPong(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientPong(int id) {
super(PacketType.Configuration.Client.PONG);
this.id = id;
}
@Override
public void read() {
this.id = this.readInt();
}
@Override
public void write() {
this.writeInt(this.id);
}
@Override
public void copy(WrapperConfigClientPong wrapper) {
this.id = wrapper.id;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
@@ -0,0 +1,69 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientResourcePackStatus extends PacketWrapper<WrapperConfigClientResourcePackStatus> {
private Result result;
public WrapperConfigClientResourcePackStatus(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientResourcePackStatus(Result result) {
super(PacketType.Configuration.Client.RESOURCE_PACK_STATUS);
this.result = result;
}
@Override
public void read() {
this.result = Result.VALUES[this.readVarInt()];
}
@Override
public void write() {
this.writeVarInt(this.result.ordinal());
}
@Override
public void copy(WrapperConfigClientResourcePackStatus wrapper) {
this.result = wrapper.result;
}
public Result getResult() {
return this.result;
}
public void setResult(Result result) {
this.result = result;
}
public enum Result {
SUCCESSFULLY_LOADED,
DECLINED,
FAILED_DOWNLOAD,
ACCEPTED;
public static final Result[] VALUES = values();
}
}
@@ -0,0 +1,163 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.HumanoidArm;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigClientSettings extends PacketWrapper<WrapperConfigClientSettings> {
private String locale;
private int viewDistance;
private ChatVisibility visibility;
private boolean chatColorable;
private byte visibleSkinSectionMask;
private HumanoidArm hand;
private boolean textFilteringEnabled;
private boolean allowServerListings;
public WrapperConfigClientSettings(PacketReceiveEvent event) {
super(event);
}
public WrapperConfigClientSettings(String locale, int viewDistance, ChatVisibility visibility,
boolean chatColorable, byte visibleSkinSectionMask, HumanoidArm hand,
boolean textFilteringEnabled, boolean allowServerListings) {
super(PacketType.Configuration.Client.CLIENT_SETTINGS);
this.locale = locale;
this.viewDistance = viewDistance;
this.visibility = visibility;
this.chatColorable = chatColorable;
this.visibleSkinSectionMask = visibleSkinSectionMask;
this.hand = hand;
this.textFilteringEnabled = textFilteringEnabled;
this.allowServerListings = allowServerListings;
}
@Override
public void read() {
this.locale = this.readString(16);
this.viewDistance = this.readByte();
this.visibility = ChatVisibility.VALUES[this.readVarInt()];
this.chatColorable = this.readBoolean();
this.visibleSkinSectionMask = (byte) this.readUnsignedByte();
this.hand = HumanoidArm.VALUES[this.readVarInt()];
this.textFilteringEnabled = this.readBoolean();
this.allowServerListings = this.readBoolean();
}
@Override
public void write() {
this.writeString(this.locale, 16);
this.writeByte(this.viewDistance);
this.writeVarInt(this.visibility.ordinal());
this.writeBoolean(this.chatColorable);
this.writeByte(this.visibleSkinSectionMask);
this.writeVarInt(this.hand.ordinal());
this.writeBoolean(this.textFilteringEnabled);
this.writeBoolean(this.allowServerListings);
}
@Override
public void copy(WrapperConfigClientSettings wrapper) {
this.locale = wrapper.locale;
this.viewDistance = wrapper.viewDistance;
this.visibility = wrapper.visibility;
this.chatColorable = wrapper.chatColorable;
this.visibleSkinSectionMask = wrapper.visibleSkinSectionMask;
this.hand = wrapper.hand;
this.textFilteringEnabled = wrapper.textFilteringEnabled;
this.allowServerListings = wrapper.allowServerListings;
}
public String getLocale() {
return this.locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public int getViewDistance() {
return this.viewDistance;
}
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
}
public ChatVisibility getVisibility() {
return this.visibility;
}
public void setVisibility(ChatVisibility visibility) {
this.visibility = visibility;
}
public boolean isChatColorable() {
return this.chatColorable;
}
public void setChatColorable(boolean chatColorable) {
this.chatColorable = chatColorable;
}
public byte getVisibleSkinSectionMask() {
return this.visibleSkinSectionMask;
}
public void setVisibleSkinSectionMask(byte visibleSkinSectionMask) {
this.visibleSkinSectionMask = visibleSkinSectionMask;
}
public HumanoidArm getHand() {
return this.hand;
}
public void setHand(HumanoidArm hand) {
this.hand = hand;
}
public boolean isTextFilteringEnabled() {
return this.textFilteringEnabled;
}
public void setTextFilteringEnabled(boolean textFilteringEnabled) {
this.textFilteringEnabled = textFilteringEnabled;
}
public boolean isAllowServerListings() {
return this.allowServerListings;
}
public void setAllowServerListings(boolean allowServerListings) {
this.allowServerListings = allowServerListings;
}
public enum ChatVisibility {
FULL,
SYSTEM,
HIDDEN;
public static final ChatVisibility[] VALUES = values();
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigServerConfigurationEnd extends PacketWrapper<WrapperConfigServerConfigurationEnd> {
public WrapperConfigServerConfigurationEnd(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerConfigurationEnd() {
super(PacketType.Configuration.Server.CONFIGURATION_END);
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
public class WrapperConfigServerDisconnect extends PacketWrapper<WrapperConfigServerDisconnect> {
private Component reason;
public WrapperConfigServerDisconnect(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerDisconnect(Component reason) {
super(PacketType.Configuration.Server.DISCONNECT);
this.reason = reason;
}
@Override
public void read() {
this.reason = this.readComponent();
}
@Override
public void write() {
this.writeComponent(this.reason);
}
@Override
public void copy(WrapperConfigServerDisconnect wrapper) {
this.reason = wrapper.reason;
}
public Component getReason() {
return this.reason;
}
public void setReason(Component reason) {
this.reason = reason;
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigServerKeepAlive extends PacketWrapper<WrapperConfigServerKeepAlive> {
private long id;
public WrapperConfigServerKeepAlive(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerKeepAlive(long id) {
super(PacketType.Configuration.Server.KEEP_ALIVE);
this.id = id;
}
@Override
public void read() {
this.id = this.readLong();
}
@Override
public void write() {
this.writeLong(this.id);
}
@Override
public void copy(WrapperConfigServerKeepAlive wrapper) {
this.id = wrapper.id;
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
}
@@ -0,0 +1,82 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigServerPluginMessage extends PacketWrapper<WrapperConfigServerPluginMessage> {
private String channelName;
private byte[] data;
public WrapperConfigServerPluginMessage(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerPluginMessage(ResourceLocation channelName, byte[] data) {
this(channelName.toString(), data);
}
public WrapperConfigServerPluginMessage(String channelName, byte[] data) {
super(PacketType.Configuration.Server.PLUGIN_MESSAGE);
this.channelName = channelName;
this.data = data;
}
@Override
public void read() {
this.channelName = this.readString();
if (ByteBufHelper.readableBytes(this.buffer) > 32767) {
throw new RuntimeException("Payload may not be larger than 32767 bytes");
}
this.data = this.readRemainingBytes();
}
@Override
public void write() {
this.writeString(this.channelName);
this.writeBytes(this.data);
}
@Override
public void copy(WrapperConfigServerPluginMessage wrapper) {
this.channelName = wrapper.channelName;
this.data = wrapper.data;
}
public String getChannelName() {
return this.channelName;
}
public void setChannelName(String channelName) {
this.channelName = channelName;
}
public byte[] getData() {
return this.data;
}
public void setData(byte[] data) {
this.data = data;
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperConfigServerRegistryData extends PacketWrapper<WrapperConfigServerRegistryData> {
private NBTCompound registryData;
public WrapperConfigServerRegistryData(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerRegistryData(NBTCompound registryData) {
super(PacketType.Configuration.Server.REGISTRY_DATA);
this.registryData = registryData;
}
@Override
public void read() {
this.registryData = this.readNBT();
}
@Override
public void write() {
this.writeNBT(this.registryData);
}
@Override
public void copy(WrapperConfigServerRegistryData wrapper) {
this.registryData = wrapper.registryData;
}
public NBTCompound getRegistryData() {
return this.registryData;
}
public void setRegistryData(NBTCompound registryData) {
this.registryData = registryData;
}
}
@@ -0,0 +1,115 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
public class WrapperConfigServerResourcePackSend extends PacketWrapper<WrapperConfigServerResourcePackSend> {
public static final int MAX_HASH_LENGTH = 40;
private String url;
private String hash;
private boolean required;
private Component prompt;
public WrapperConfigServerResourcePackSend(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerResourcePackSend(String url, String hash, boolean required, @Nullable Component prompt) {
super(PacketType.Configuration.Server.RESOURCE_PACK_SEND);
if (hash.length() > MAX_HASH_LENGTH) {
throw new IllegalArgumentException("Hash is too long (max 40, was " + hash.length() + ")");
}
this.url = url;
this.hash = hash;
this.required = required;
this.prompt = prompt;
}
@Override
public void read() {
this.url = this.readString();
this.hash = this.readString(MAX_HASH_LENGTH);
this.required = this.readBoolean();
if (this.readBoolean()) {
this.prompt = this.readComponent();
}
}
@Override
public void write() {
this.writeString(this.url);
this.writeString(this.hash, MAX_HASH_LENGTH);
this.writeBoolean(this.required);
if (this.prompt != null) {
this.writeBoolean(true);
this.writeComponent(this.prompt);
} else {
this.writeBoolean(false);
}
}
@Override
public void copy(WrapperConfigServerResourcePackSend wrapper) {
this.url = wrapper.url;
this.hash = wrapper.hash;
this.required = wrapper.required;
this.prompt = wrapper.prompt;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHash() {
return this.hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public boolean isRequired() {
return this.required;
}
public void setRequired(boolean required) {
this.required = required;
}
public Component getPrompt() {
return this.prompt;
}
public void setPrompt(Component prompt) {
this.prompt = prompt;
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.configuration.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.HashSet;
import java.util.Set;
public class WrapperConfigServerUpdateEnabledFeatures extends PacketWrapper<WrapperConfigServerUpdateEnabledFeatures> {
private Set<ResourceLocation> features;
public WrapperConfigServerUpdateEnabledFeatures(PacketSendEvent event) {
super(event);
}
public WrapperConfigServerUpdateEnabledFeatures(Set<ResourceLocation> features) {
super(PacketType.Configuration.Server.UPDATE_ENABLED_FEATURES);
this.features = features;
}
@Override
public void read() {
this.features = this.readCollection(HashSet::new, PacketWrapper::readIdentifier);
}
@Override
public void write() {
this.writeCollection(this.features, PacketWrapper::writeIdentifier);
}
@Override
public void copy(WrapperConfigServerUpdateEnabledFeatures wrapper) {
this.features = wrapper.features;
}
public Set<ResourceLocation> getFeatures() {
return this.features;
}
public void setFeatures(Set<ResourceLocation> features) {
this.features = features;
}
}
@@ -57,12 +57,15 @@ public class WrapperLoginClientLoginStart extends PacketWrapper<WrapperLoginClie
@Override
public void read() {
this.username = readString(16);
if (clientVersion.isNewerThanOrEquals(ClientVersion.V_1_19)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) {
if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_19_3)) {
//Removed in 1.19.4
this.signatureData = readOptional(PacketWrapper::readSignatureData);
}
if (clientVersion.isNewerThanOrEquals(ClientVersion.V_1_19_1)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
this.playerUUID = readUUID();
} else if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19_1)) {
this.playerUUID = readOptional(PacketWrapper::readUUID);
}
}
@@ -71,12 +74,15 @@ public class WrapperLoginClientLoginStart extends PacketWrapper<WrapperLoginClie
@Override
public void write() {
writeString(username, 16);
if (clientVersion.isNewerThanOrEquals(ClientVersion.V_1_19)) {
if (clientVersion.isOlderThanOrEquals(ClientVersion.V_1_19_3)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) {
if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_19_3)) {
//Removed in 1.19.4
writeOptional(signatureData, PacketWrapper::writeSignatureData);
}
if (clientVersion.isNewerThanOrEquals(ClientVersion.V_1_19_1)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
writeUUID(java.util.Objects.requireNonNull(playerUUID, "playerUUID is required for >= 1.20.2"));
} else if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19_1)) {
writeOptional(playerUUID, PacketWrapper::writeUUID);
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.login.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperLoginClientLoginSuccessAck extends PacketWrapper<WrapperLoginClientLoginSuccessAck> {
public WrapperLoginClientLoginSuccessAck(PacketReceiveEvent event) {
super(event);
}
public WrapperLoginClientLoginSuccessAck() {
super(PacketType.Login.Client.LOGIN_SUCCESS_ACK);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayClientChunkBatchAck extends PacketWrapper<WrapperPlayClientChunkBatchAck> {
private float desiredChunksPerTick;
public WrapperPlayClientChunkBatchAck(PacketReceiveEvent event) {
super(event);
}
public WrapperPlayClientChunkBatchAck(float desiredChunksPerTick) {
super(PacketType.Play.Client.CHUNK_BATCH_ACK);
this.desiredChunksPerTick = desiredChunksPerTick;
}
@Override
public void read() {
this.desiredChunksPerTick = this.readFloat();
}
@Override
public void write() {
this.writeFloat(this.desiredChunksPerTick);
}
@Override
public void copy(WrapperPlayClientChunkBatchAck wrapper) {
this.desiredChunksPerTick = wrapper.desiredChunksPerTick;
}
public float getDesiredChunksPerTick() {
return this.desiredChunksPerTick;
}
public void setDesiredChunksPerTick(float desiredChunksPerTick) {
this.desiredChunksPerTick = desiredChunksPerTick;
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayClientConfigurationAck extends PacketWrapper<WrapperPlayClientConfigurationAck> {
public WrapperPlayClientConfigurationAck(PacketReceiveEvent event) {
super(event);
}
public WrapperPlayClientConfigurationAck() {
super(PacketType.Play.Client.CONFIGURATION_ACK);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.client;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayClientDebugPing extends PacketWrapper<WrapperPlayClientDebugPing> {
private long timestamp;
public WrapperPlayClientDebugPing(PacketReceiveEvent event) {
super(event);
}
public WrapperPlayClientDebugPing(long timestamp) {
super(PacketType.Play.Client.DEBUG_PING);
this.timestamp = timestamp;
}
@Override
public void read() {
this.timestamp = this.readLong();
}
@Override
public void write() {
this.writeLong(this.timestamp);
}
@Override
public void copy(WrapperPlayClientDebugPing wrapper) {
this.timestamp = wrapper.timestamp;
}
public long getTimestamp() {
return this.timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayServerChunkBatchBegin extends PacketWrapper<WrapperPlayServerChunkBatchBegin> {
public WrapperPlayServerChunkBatchBegin(PacketSendEvent event) {
super(event);
}
public WrapperPlayServerChunkBatchBegin() {
super(PacketType.Play.Server.CHUNK_BATCH_BEGIN);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayServerChunkBatchEnd extends PacketWrapper<WrapperPlayServerChunkBatchEnd> {
private int batchSize;
public WrapperPlayServerChunkBatchEnd(PacketSendEvent event) {
super(event);
}
public WrapperPlayServerChunkBatchEnd(int batchSize) {
super(PacketType.Play.Server.CHUNK_BATCH_END);
this.batchSize = batchSize;
}
@Override
public void read() {
this.batchSize = this.readVarInt();
}
@Override
public void write() {
this.writeVarInt(this.batchSize);
}
@Override
public void copy(WrapperPlayServerChunkBatchEnd wrapper) {
this.batchSize = wrapper.batchSize;
}
public int getBatchSize() {
return this.batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
}
@@ -59,14 +59,14 @@ public class WrapperPlayServerChunkData extends PacketWrapper<WrapperPlayServerC
// 1.18 only (lighting) - for writing data
// TODO: Make accessible?? Include in chunk data?? What do we do with this?
private boolean trustEdges;
private BitSet blockLightMask = new BitSet();
private BitSet skyLightMask = new BitSet();
private BitSet emptyBlockLightMask = new BitSet();
private BitSet emptySkyLightMask = new BitSet();
private BitSet blockLightMask;
private BitSet skyLightMask;
private BitSet emptyBlockLightMask;
private BitSet emptySkyLightMask;
private int skyLightCount;
private int blockLightCount;
private byte[][] skyLightArray = new byte[0][0];
private byte[][] blockLightArray = new byte[0][0];
private byte[][] skyLightArray;
private byte[][] blockLightArray;
public WrapperPlayServerChunkData(PacketSendEvent event) {
super(event);
@@ -0,0 +1,34 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayServerConfigurationStart extends PacketWrapper<WrapperPlayServerConfigurationStart> {
public WrapperPlayServerConfigurationStart(PacketSendEvent event) {
super(event);
}
public WrapperPlayServerConfigurationStart() {
super(PacketType.Play.Server.CONFIGURATION_START);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayServerDebugPong extends PacketWrapper<WrapperPlayServerDebugPong> {
private long timestamp;
public WrapperPlayServerDebugPong(PacketSendEvent event) {
super(event);
}
public WrapperPlayServerDebugPong(long timestamp) {
super(PacketType.Play.Server.DEBUG_PONG);
this.timestamp = timestamp;
}
@Override
public void read() {
this.timestamp = this.readLong();
}
@Override
public void write() {
this.writeLong(this.timestamp);
}
@Override
public void copy(WrapperPlayServerDebugPong wrapper) {
this.timestamp = wrapper.timestamp;
}
public long getTimestamp() {
return this.timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
@@ -38,13 +39,21 @@ public class WrapperPlayServerDisplayScoreboard extends PacketWrapper<WrapperPla
@Override
public void read() {
position = readByte();
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
position = readVarInt();
} else {
position = readByte();
}
scoreName = readString(16);
}
@Override
public void write() {
writeByte(position);
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
writeVarInt(position);
} else {
writeByte(position);
}
writeString(scoreName, 16);
}
@@ -45,7 +45,7 @@ public class WrapperPlayServerEntityEffect extends PacketWrapper<WrapperPlayServ
} else {
effectId = readByte();
}
this.potionType = PotionTypes.getById(effectId);
this.potionType = PotionTypes.getById(effectId, this.serverVersion);
this.effectAmplifier = readByte();
this.effectDurationTicks = readVarInt();
if (serverVersion.isNewerThan(ServerVersion.V_1_7_10)) {
@@ -60,9 +60,9 @@ public class WrapperPlayServerEntityEffect extends PacketWrapper<WrapperPlayServ
public void write() {
writeVarInt(entityID);
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_18_2)) {
writeVarInt(potionType.getId());
writeVarInt(potionType.getId(serverVersion.toClientVersion()));
} else {
writeByte(potionType.getId());
writeByte(potionType.getId(serverVersion.toClientVersion()));
}
writeByte(effectAmplifier);
writeVarInt(effectDurationTicks);
@@ -21,6 +21,7 @@ package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
@@ -40,6 +41,10 @@ public class WrapperPlayServerEntityMetadata extends PacketWrapper<WrapperPlaySe
this.entityMetadata = entityMetadata;
}
public WrapperPlayServerEntityMetadata(int entityID, EntityMetadataProvider metadata) {
this(entityID, metadata.entityData());
}
@Override
public void read() {
entityID = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8) ? readVarInt() : readInt();
@@ -77,4 +82,8 @@ public class WrapperPlayServerEntityMetadata extends PacketWrapper<WrapperPlaySe
public void setEntityMetadata(List<EntityData> entityMetadata) {
this.entityMetadata = entityMetadata;
}
public void setEntityMetadata(EntityMetadataProvider metadata) {
this.entityMetadata = metadata.entityData();
}
}
@@ -2,30 +2,53 @@ package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.event.PacketSendEvent;
public class WrapperPlayServerHurtAnimation extends PacketWrapper<WrapperPlayServerHurtAnimation> {
int entityId;
float hurtDir;
private int entityId;
private float yaw;
public WrapperPlayServerHurtAnimation() {
public WrapperPlayServerHurtAnimation(PacketSendEvent event) {
super(event);
}
public WrapperPlayServerHurtAnimation(int entityId, float yaw) {
super(PacketType.Play.Server.HURT_ANIMATION);
this.entityId = entityId;
this.yaw = yaw;
}
@Override
public void read() {
entityId = readVarInt();
hurtDir = readFloat();
yaw = readFloat();
}
@Override
public void write() {
writeVarInt(entityId);
writeFloat(hurtDir);
writeFloat(yaw);
}
@Override
public void copy(WrapperPlayServerHurtAnimation wrapper) {
this.entityId = wrapper.entityId;
this.hurtDir = wrapper.hurtDir;
this.yaw = wrapper.yaw;
}
public int getEntityId() {
return entityId;
}
public void setEntityId(int entityId) {
this.entityId = entityId;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
}
@@ -50,6 +50,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
private int simulationDistance;
private boolean reducedDebugInfo;
private boolean enableRespawnScreen;
private boolean limitedCrafting;
private boolean isDebug;
private boolean isFlat;
private WorldBlockPosition lastDeathPosition;
@@ -66,6 +67,18 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
int maxPlayers, int viewDistance, int simulationDistance,
boolean reducedDebugInfo, boolean enableRespawnScreen,
boolean isDebug, boolean isFlat, WorldBlockPosition lastDeathPosition, @Nullable Integer portalCooldown) {
this(entityID, hardcore, gameMode, previousGameMode, worldNames, dimensionCodec, dimension,
difficulty, worldName, hashedSeed, maxPlayers, viewDistance, simulationDistance, reducedDebugInfo, enableRespawnScreen,
false, isDebug, isFlat, lastDeathPosition, portalCooldown);
}
public WrapperPlayServerJoinGame(int entityID, boolean hardcore, GameMode gameMode,
@Nullable GameMode previousGameMode, List<String> worldNames,
NBTCompound dimensionCodec, Dimension dimension,
Difficulty difficulty, String worldName, long hashedSeed,
int maxPlayers, int viewDistance, int simulationDistance,
boolean reducedDebugInfo, boolean enableRespawnScreen, boolean limitedCrafting,
boolean isDebug, boolean isFlat, WorldBlockPosition lastDeathPosition, @Nullable Integer portalCooldown) {
super(PacketType.Play.Server.JOIN_GAME);
this.entityID = entityID;
this.hardcore = hardcore;
@@ -82,6 +95,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
this.simulationDistance = simulationDistance;
this.reducedDebugInfo = reducedDebugInfo;
this.enableRespawnScreen = enableRespawnScreen;
this.limitedCrafting = limitedCrafting;
this.isDebug = isDebug;
this.isFlat = isFlat;
this.lastDeathPosition = lastDeathPosition;
@@ -91,6 +105,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
@Override
public void read() {
entityID = readInt();
boolean v1_20_2 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2);
boolean v1_19 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19);
boolean v1_18 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_18);
boolean v1_16 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_16);
@@ -98,22 +113,28 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
boolean v1_14 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_14);
if (v1_16) {
hardcore = readBoolean();
gameMode = readGameMode();
if (!v1_20_2) {
gameMode = readGameMode();
}
} else {
int gameModeId = readUnsignedByte();
hardcore = (gameModeId & 0x8) == 0x8;
gameMode = GameMode.getById(gameModeId & -0x9);
}
if (v1_16) {
previousGameMode = readGameMode();
if (!v1_20_2) {
previousGameMode = readGameMode();
}
int worldCount = readVarInt();
worldNames = new ArrayList<>(worldCount);
for (int i = 0; i < worldCount; i++) {
worldNames.add(readString());
}
dimensionCodec = readNBT();
dimension = readDimension();
worldName = readString();
if (!v1_20_2) {
dimensionCodec = readNBT();
dimension = readDimension();
worldName = readString();
}
} else {
previousGameMode = gameMode;
dimensionCodec = new NBTCompound();
@@ -122,7 +143,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
difficulty = Difficulty.getById(readByte());
}
}
if (v1_15) {
if (v1_15 && !v1_20_2) {
hashedSeed = readLong();
}
if (v1_16) {
@@ -131,6 +152,14 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
if (v1_18) simulationDistance = readVarInt();
reducedDebugInfo = readBoolean();
enableRespawnScreen = readBoolean();
if (v1_20_2) {
limitedCrafting = readBoolean();
dimension = readDimension();
worldName = readString();
hashedSeed = readLong();
gameMode = readGameMode();
previousGameMode = readGameMode();
}
isDebug = readBoolean();
isFlat = readBoolean();
} else {
@@ -157,6 +186,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
@Override
public void write() {
writeInt(entityID);
boolean v1_20_2 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2);
boolean v1_19 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19);
boolean v1_18 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_18);
boolean v1_16 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_16);
@@ -164,7 +194,9 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
boolean v1_15 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_15);
if (v1_16) {
writeBoolean(hardcore);
writeGameMode(gameMode);
if (!v1_20_2) {
writeGameMode(gameMode);
}
} else {
int gameModeId = gameMode.getId();
if (hardcore) {
@@ -176,14 +208,18 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
if (previousGameMode == null) {
previousGameMode = gameMode;
}
writeGameMode(previousGameMode);
if (!v1_20_2) {
writeGameMode(previousGameMode);
}
writeVarInt(worldNames.size());
for (String name : worldNames) {
writeString(name);
}
writeNBT(dimensionCodec);
writeDimension(dimension);
writeString(worldName);
if (!v1_20_2) {
writeNBT(dimensionCodec);
writeDimension(dimension);
writeString(worldName);
}
} else {
previousGameMode = gameMode;
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_9)) {
@@ -195,7 +231,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
writeByte(difficulty.getId());
}
}
if (v1_15) {
if (v1_15 && !v1_20_2) {
writeLong(hashedSeed);
}
if (v1_16) {
@@ -204,6 +240,14 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
if (v1_18) writeVarInt(simulationDistance);
writeBoolean(reducedDebugInfo);
writeBoolean(enableRespawnScreen);
if (v1_20_2) {
writeBoolean(limitedCrafting);
writeDimension(dimension);
writeString(worldName);
writeLong(hashedSeed);
writeGameMode(gameMode);
writeGameMode(previousGameMode);
}
writeBoolean(isDebug);
writeBoolean(isFlat);
} else {
@@ -252,6 +296,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
simulationDistance = wrapper.simulationDistance;
reducedDebugInfo = wrapper.reducedDebugInfo;
enableRespawnScreen = wrapper.enableRespawnScreen;
limitedCrafting = wrapper.limitedCrafting;
isDebug = wrapper.isDebug;
isFlat = wrapper.isFlat;
lastDeathPosition = wrapper.lastDeathPosition;
@@ -367,7 +412,6 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
return reducedDebugInfo;
}
public void setReducedDebugInfo(boolean reducedDebugInfo) {
this.reducedDebugInfo = reducedDebugInfo;
}
@@ -380,6 +424,14 @@ public class WrapperPlayServerJoinGame extends PacketWrapper<WrapperPlayServerJo
this.enableRespawnScreen = enableRespawnScreen;
}
public boolean isLimitedCrafting() {
return this.limitedCrafting;
}
public void setLimitedCrafting(boolean limitedCrafting) {
this.limitedCrafting = limitedCrafting;
}
public boolean isDebug() {
return isDebug;
}
@@ -29,7 +29,7 @@ import java.util.List;
public class WrapperPlayServerMerchantOffers extends PacketWrapper<WrapperPlayServerMerchantOffers> {
private int containerId;
private List<MerchantOffer> merchantOffers = new ArrayList<>();
private List<MerchantOffer> merchantOffers;
private int villagerLevel;
private int villagerXp;
private boolean showProgress;
@@ -48,16 +48,16 @@ public class WrapperPlayServerRemoveEntityEffect extends PacketWrapper<WrapperPl
} else {
effectId = readByte();
}
this.potionType = PotionTypes.getById(effectId);
this.potionType = PotionTypes.getById(effectId, this.serverVersion);
}
@Override
public void write() {
writeVarInt(entityId);
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_18_2)) {
writeVarInt(potionType.getId());
writeVarInt(potionType.getId(serverVersion.toClientVersion()));
} else {
writeByte(potionType.getId());
writeByte(potionType.getId(serverVersion.toClientVersion()));
}
}
@@ -30,6 +30,12 @@ import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRespawn> {
public static final byte KEEP_NOTHING = 0;
public static final byte KEEP_ATTRIBUTES = 0b01;
public static final byte KEEP_ENTITY_DATA = 0b10;
public static final byte KEEP_ALL_DATA = KEEP_ATTRIBUTES | KEEP_ENTITY_DATA;
private Dimension dimension;
private Optional<String> worldName;
private Difficulty difficulty;
@@ -38,7 +44,7 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
private @Nullable GameMode previousGameMode;
private boolean worldDebug;
private boolean worldFlat;
private boolean keepingAllPlayerData;
private byte keptData;
private WorldBlockPosition lastDeathPosition;
private Integer portalCooldown;
@@ -53,6 +59,13 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
@Nullable GameMode previousGameMode, boolean worldDebug, boolean worldFlat, boolean keepingAllPlayerData,
@Nullable ResourceLocation deathDimensionName, @Nullable WorldBlockPosition lastDeathPosition,
@Nullable Integer portalCooldown) {
this(dimension, worldName, difficulty, hashedSeed, gameMode, previousGameMode, worldDebug, worldFlat,
keepingAllPlayerData ? KEEP_ALL_DATA : KEEP_NOTHING, lastDeathPosition, portalCooldown);
}
public WrapperPlayServerRespawn(Dimension dimension, @Nullable String worldName, Difficulty difficulty, long hashedSeed, GameMode gameMode,
@Nullable GameMode previousGameMode, boolean worldDebug, boolean worldFlat, byte keptData,
@Nullable WorldBlockPosition lastDeathPosition, @Nullable Integer portalCooldown) {
super(PacketType.Play.Server.RESPAWN);
this.dimension = dimension;
setWorldName(worldName);
@@ -62,7 +75,7 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
this.previousGameMode = previousGameMode;
this.worldDebug = worldDebug;
this.worldFlat = worldFlat;
this.keepingAllPlayerData = keepingAllPlayerData;
this.keptData = keptData;
this.lastDeathPosition = lastDeathPosition;
this.portalCooldown = portalCooldown;
}
@@ -73,23 +86,37 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
boolean v1_15_0 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_15);
boolean v1_16_0 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_16);
boolean v1_19 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19);
boolean v1_19_3 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19_3);
boolean v1_20_2 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2);
if (v1_16_0) {
dimension = readDimension();
worldName = Optional.of(readString());
hashedSeed = readLong();
gameMode = GameMode.getById(readUnsignedByte());
int previousMode = readByte();
previousGameMode = previousMode == -1 ? null : GameMode.getById(previousMode);
if (v1_20_2) {
gameMode = readGameMode();
} else {
gameMode = GameMode.getById(readUnsignedByte());
}
previousGameMode = readGameMode();
worldDebug = readBoolean();
worldFlat = readBoolean();
keepingAllPlayerData = readBoolean();
if (v1_19_3) {
if (!v1_20_2) {
keptData = readByte();
}
} else {
keptData = readBoolean() ? KEEP_ALL_DATA : KEEP_ENTITY_DATA;
}
if (v1_19) {
lastDeathPosition = readOptional(PacketWrapper::readWorldBlockPosition);
}
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20)) {
portalCooldown = readVarInt();
}
if (v1_20_2) {
keptData = readByte();
}
} else {
dimension = new Dimension(readInt());
@@ -115,16 +142,24 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
boolean v1_15_0 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_15);
boolean v1_16_0 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_16);
boolean v1_19 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19);
boolean v1_19_3 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19_3);
boolean v1_20_2 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_2);
if (v1_16_0) {
writeDimension(dimension);
writeString(worldName.orElse(""));
writeLong(hashedSeed);
writeByte(gameMode.ordinal());
writeByte(previousGameMode == null ? -1 : previousGameMode.ordinal());
writeGameMode(gameMode);
writeGameMode(previousGameMode);
writeBoolean(worldDebug);
writeBoolean(worldFlat);
writeBoolean(keepingAllPlayerData);
if (v1_19_3) {
if (!v1_20_2) {
writeByte(keptData);
}
} else {
writeBoolean((keptData & KEEP_ATTRIBUTES) != 0);
}
if (v1_19) {
writeOptional(lastDeathPosition, PacketWrapper::writeWorldBlockPosition);
}
@@ -132,6 +167,9 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
int pCooldown = portalCooldown != null ? portalCooldown : 0;
writeVarInt(pCooldown);
}
if (v1_20_2) {
writeByte(keptData);
}
} else {
writeInt(dimension.getId());
if (v1_15_0) {
@@ -165,7 +203,7 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
previousGameMode = wrapper.previousGameMode;
worldDebug = wrapper.worldDebug;
worldFlat = wrapper.worldFlat;
keepingAllPlayerData = wrapper.keepingAllPlayerData;
keptData = wrapper.keptData;
lastDeathPosition = wrapper.lastDeathPosition;
}
@@ -235,11 +273,19 @@ public class WrapperPlayServerRespawn extends PacketWrapper<WrapperPlayServerRes
}
public boolean isKeepingAllPlayerData() {
return keepingAllPlayerData;
return (keptData & KEEP_ATTRIBUTES) != 0;
}
public void setKeepingAllPlayerData(boolean keepAllPlayerData) {
this.keepingAllPlayerData = keepAllPlayerData;
this.keptData = keepAllPlayerData ? KEEP_ALL_DATA : KEEP_ENTITY_DATA;
}
public byte getKeptData() {
return keptData;
}
public void setKeptData(byte keptData) {
this.keptData = keptData;
}
public @Nullable WorldBlockPosition getLastDeathPosition() {
@@ -21,6 +21,7 @@ package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
@@ -64,6 +65,10 @@ public class WrapperPlayServerSpawnLivingEntity extends PacketWrapper<WrapperPla
this.entityMetadata = entityMetadata;
}
public WrapperPlayServerSpawnLivingEntity(int entityID, UUID entityUUID, EntityType entityType, Vector3d position, float yaw, float pitch, float headPitch, Vector3d velocity, EntityMetadataProvider metadata) {
this(entityID, entityUUID, entityType, position, yaw, pitch, headPitch, velocity, metadata.entityData());
}
public WrapperPlayServerSpawnLivingEntity(int entityId, UUID entityUUID,
EntityType entityType, Location location, float headPitch,
Vector3d velocity,
@@ -72,6 +77,14 @@ public class WrapperPlayServerSpawnLivingEntity extends PacketWrapper<WrapperPla
headPitch, velocity, entityMetadata);
}
public WrapperPlayServerSpawnLivingEntity(int entityId, UUID entityUUID,
EntityType entityType, Location location, float headPitch,
Vector3d velocity,
EntityMetadataProvider metadata) {
this(entityId, entityUUID, entityType, location.getPosition(), location.getYaw(), location.getPitch(),
headPitch, velocity, metadata.entityData());
}
@Override
public void read() {
this.entityID = readVarInt();
@@ -220,4 +233,8 @@ public class WrapperPlayServerSpawnLivingEntity extends PacketWrapper<WrapperPla
public void setEntityMetadata(List<EntityData> entityMetadata) {
this.entityMetadata = entityMetadata;
}
public void setEntityMetadata(EntityMetadataProvider metadata) {
this.entityMetadata = metadata.entityData();
}
}
@@ -21,6 +21,7 @@ package com.github.retrooper.packetevents.wrapper.play.server;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
@@ -50,6 +51,10 @@ public class WrapperPlayServerSpawnPlayer extends PacketWrapper<WrapperPlayServe
super(event);
}
public WrapperPlayServerSpawnPlayer(int entityId, UUID uuid, Location location, EntityMetadataProvider metadata) {
this(entityId, uuid, location.getPosition(), location.getYaw(), location.getPitch(), metadata.entityData());
}
public WrapperPlayServerSpawnPlayer(int entityId, UUID uuid, Location location, List<EntityData> entityMetadata) {
this(entityId, uuid, location.getPosition(), location.getYaw(), location.getPitch(), entityMetadata);
}
@@ -69,6 +74,10 @@ public class WrapperPlayServerSpawnPlayer extends PacketWrapper<WrapperPlayServe
this.item = ItemTypes.AIR;
}
public WrapperPlayServerSpawnPlayer(int entityID, UUID uuid, Vector3d position, float yaw, float pitch, EntityMetadataProvider metadata) {
this(entityID, uuid, position, yaw, pitch, metadata.entityData());
}
@Override
public void read() {
entityID = readVarInt();
@@ -176,6 +185,11 @@ public class WrapperPlayServerSpawnPlayer extends PacketWrapper<WrapperPlayServe
this.entityMetadata = entityMetadata;
}
@Deprecated
public void setEntityMetadata(EntityMetadataProvider metadata) {
this.entityMetadata = metadata.entityData();
}
@Deprecated
public ItemType getItem() {
return item;
@@ -27,6 +27,8 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class WrapperPlayServerTitle extends PacketWrapper<WrapperPlayServerTitle> {
public static boolean HANDLE_JSON = true;
private TitleAction action;
@@ -77,15 +79,14 @@ public class WrapperPlayServerTitle extends PacketWrapper<WrapperPlayServerTitle
@Override
public void read() {
boolean modern = PacketEvents.getAPI().getServerManager()
.getVersion().isNewerThanOrEquals(ServerVersion.V_1_11);
boolean modern = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_11);
int id = readVarInt();
if (modern) {
action = TitleAction.fromId(id);
} else {
action = TitleAction.fromLegacyId(id);
}
switch (action) {
switch (Objects.requireNonNull(action)) {
case SET_TITLE:
titleJson = readComponentJSON();
if (HANDLE_JSON) {
@@ -128,8 +129,7 @@ public class WrapperPlayServerTitle extends PacketWrapper<WrapperPlayServerTitle
@Override
public void write() {
boolean modern = PacketEvents.getAPI().getServerManager()
.getVersion().isNewerThanOrEquals(ServerVersion.V_1_11);
boolean modern = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_11);
int id = modern ? action.getId() : action.getLegacyId();
writeVarInt(id);
switch (action) {
@@ -38,14 +38,24 @@ public class WrapperPlayServerUnloadChunk extends PacketWrapper<WrapperPlayServe
@Override
public void read() {
this.chunkX = readInt();
this.chunkZ = readInt();
if (this.serverVersion.isNewerThanOrEquals(com.github.retrooper.packetevents.manager.server.ServerVersion.V_1_20_2)) {
long chunkKey = readLong();
this.chunkX = getChunkX(chunkKey);
this.chunkZ = getChunkZ(chunkKey);
} else {
this.chunkX = readInt();
this.chunkZ = readInt();
}
}
@Override
public void write() {
writeInt(chunkX);
writeInt(chunkZ);
if (this.serverVersion.isNewerThanOrEquals(com.github.retrooper.packetevents.manager.server.ServerVersion.V_1_20_2)) {
writeLong(getChunkKey(this.chunkX, this.chunkZ));
} else {
writeInt(this.chunkX);
writeInt(this.chunkZ);
}
}
@Override
@@ -47,7 +47,7 @@ public class WrapperPlayServerUseBed extends PacketWrapper<WrapperPlayServerUseB
@Override
public void read() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
entityId = readVarInt();
position = readBlockPosition();
} else {
@@ -61,7 +61,7 @@ public class WrapperPlayServerUseBed extends PacketWrapper<WrapperPlayServerUseB
@Override
public void write() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8)) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
writeVarInt(entityId);
writeBlockPosition(position);
} else {
File diff suppressed because it is too large. Load diff
@@ -12290,6 +12290,7 @@
"stone_pressure_plate": "70",
"oak_pressure_plate": "72",
"redstone_ore": "73",
"redstone_torch": "76",
"stone_button": "77",
"snow": "78",
"ice": "79",
+1 -2
View File
@@ -19,8 +19,7 @@ subprojects {
group = 'com.github.retrooper'
description = project.name
version = '2.0.0'//TODO UPDATE - ADD "-SNAPSHOT" if we are dealing with snapshot versions
version = '2.1.0'//TODO UPDATE - ADD "-SNAPSHOT" if we are dealing with snapshot versions
project.ext.nettyVersion = '4.1.72.Final'
project.ext.adventureVersion = '4.14.0'
project.ext.adventureDependencies=["net.kyori:adventure-api:${adventureVersion}",
+3 -2
View File
@@ -6,9 +6,10 @@ dependencies {
}
shadowJar {
relocate 'net.kyori.adventure.text.serializer', 'io.github.retrooper.packetevents.adventure.serializer'
relocate 'net.kyori.adventure.text.serializer.gson', 'io.github.retrooper.packetevents.adventure.serializer.gson'
relocate 'net.kyori.adventure.text.serializer.legacy', 'io.github.retrooper.packetevents.adventure.serializer.legacy'
relocate 'net.kyori.adventure.util.Codec', 'io.github.retrooper.packetevents.adventure.util.Codec'
dependencies {
exclude(dependency('com.google.code.gson:gson:2.8.0'))
}
}
}
@@ -20,8 +20,15 @@ package io.github.retrooper.packetevents;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.*;
import com.github.retrooper.packetevents.protocol.chat.ChatTypes;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessageLegacy;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.util.TimeStampMode;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChatMessage;
import io.github.retrooper.packetevents.bungee.factory.BungeePacketEventsBuilder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.md_5.bungee.api.plugin.Plugin;
public final class PacketEventsPlugin extends Plugin {
@@ -41,6 +48,16 @@ public final class PacketEventsPlugin extends Plugin {
public void onPacketReceive(PacketReceiveEvent event) {
//System.out.println("Pipe: " + ChannelHelper.pipelineHandlerNamesAsString(event.getChannel()));
//System.out.println("In type: " + event.getPacketType().getName());
//Testing sending packets to users on proxies!
/*if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
if (new WrapperPlayClientInteractEntity(event).getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
event.getUser().sendMessage(Component.text("Test message").color(NamedTextColor.RED));
event.getUser().sendTitle(Component.text("Test title").color(NamedTextColor.GREEN),
Component.text("subtitle test").color(NamedTextColor.RED),
3, 3, 5);
}
}*/
}
@Override
@@ -49,7 +66,7 @@ public final class PacketEventsPlugin extends Plugin {
//System.out.println("Out type: " + event.getPacketType().getName());
}
};
PacketEvents.getAPI().getEventManager().registerListener(listener);
//PacketEvents.getAPI().getEventManager().registerListener(listener);
}
@Override
@@ -56,7 +56,9 @@ public class PacketEventsDecoder extends MessageToMessageDecoder<ByteBuf> {
packetReceiveEvent.getLastUsedWrapper().writeVarInt(packetReceiveEvent.getPacketId());
packetReceiveEvent.getLastUsedWrapper().write();
}
transformed.readerIndex(firstReaderIndex);
else {
transformed.readerIndex(firstReaderIndex);
}
output.add(transformed.retain());
}
if (packetReceiveEvent.hasPostTasks()) {
@@ -21,7 +21,6 @@ package io.github.retrooper.packetevents.handlers;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import io.github.retrooper.packetevents.injector.CustomPipelineUtil;
@@ -58,7 +57,9 @@ public class PacketEventsEncoder extends MessageToByteEncoder<ByteBuf> {
packetSendEvent.getLastUsedWrapper().writeVarInt(packetSendEvent.getPacketId());
packetSendEvent.getLastUsedWrapper().write();
}
buffer.readerIndex(firstReaderIndex);
else {
buffer.readerIndex(firstReaderIndex);
}
if (doCompression) {
recompress(ctx, buffer);
}
@@ -110,7 +111,7 @@ public class PacketEventsEncoder extends MessageToByteEncoder<ByteBuf> {
PacketEventsEncoder encoder = (PacketEventsEncoder) pipe.remove(PacketEvents.ENCODER_NAME);
pipe.addAfter("decompress", PacketEvents.DECODER_NAME, decoder);
pipe.addAfter("compress", PacketEvents.ENCODER_NAME, encoder);
System.out.println("Pipe: " + ChannelHelper.pipelineHandlerNamesAsString(ctx.channel()));
//System.out.println("Pipe: " + ChannelHelper.pipelineHandlerNamesAsString(ctx.channel()));
handledCompression = true;
return true;
} catch (InvocationTargetException e) {
@@ -126,4 +126,9 @@ public class BungeePipelineInjector implements ChannelInjector {
PacketEventsEncoder encoder = (PacketEventsEncoder) channel.pipeline().get(PacketEvents.ENCODER_NAME);
encoder.user = user;
}
@Override
public boolean isProxy() {
return true;
}
}
+5 -5
View File
@@ -1,7 +1,6 @@
repositories {
maven { url 'https://jitpack.io' }
maven { url 'https://repo.viaversion.com/' }
maven { url 'https://nexus.funkemunky.cc/content/repositories/releases/' }
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
}
@@ -9,7 +8,8 @@ java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
shadowJar {
relocate 'net.kyori.adventure.text.serializer', 'io.github.retrooper.packetevents.adventure.serializer'
relocate 'net.kyori.adventure.text.serializer.gson', 'io.github.retrooper.packetevents.adventure.serializer.gson'
relocate 'net.kyori.adventure.text.serializer.legacy', 'io.github.retrooper.packetevents.adventure.serializer.legacy'
dependencies {
exclude(dependency('com.google.code.gson:gson:2.8.0'))
exclude(dependency('com.google.code.gson:gson:2.8.5'))
@@ -18,12 +18,12 @@ shadowJar {
}
dependencies {
compileOnly 'io.netty:netty-all:4.1.75.Final'
api project(':api')
api project(':netty-common')
api(adventureDependencies)
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
compileOnly 'com.viaversion:viaversion:4.5.0'
compileOnly 'com.github.ProtocolSupport:ProtocolSupport:3d24efeda6'
compileOnly 'org.github.spigot:1.8:1.8'
}
}
@@ -20,9 +20,7 @@ package io.github.retrooper.packetevents;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.*;
import com.github.retrooper.packetevents.event.simple.PacketLoginSendEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlayReceiveEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
import com.github.retrooper.packetevents.event.simple.*;
import com.github.retrooper.packetevents.util.TimeStampMode;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import org.bukkit.plugin.java.JavaPlugin;
@@ -42,18 +40,22 @@ public class PacketEventsPlugin extends JavaPlugin {
SimplePacketListenerAbstract listener = new SimplePacketListenerAbstract(PacketListenerPriority.HIGH) {
@Override
public void onPacketLoginSend(PacketLoginSendEvent event) {
}
@Override
public void onPacketConfigReceive(PacketConfigReceiveEvent event) {
}
@Override
public void onPacketConfigSend(PacketConfigSendEvent event) {
}
@Override
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
}
@Override
public void onPacketPlaySend(PacketPlaySendEvent event) {
}
@Override
@@ -140,10 +140,8 @@ public class SpigotPacketEventsBuilder {
if (settings.isbStatsEnabled()) {
Metrics metrics = new Metrics((JavaPlugin) plugin, 11327);
//Just to have an idea what versions of packetevents people use
//TODO UPDATE
boolean snapshot = false;
metrics.addCustomChart(new Metrics.SimplePie("packetevents_version", () -> {
return getVersion().toString() + (snapshot ? "-SNAPSHOT" : "");//TODO Cut off "-beta" once 2.0 releases
return getVersion().toString();
}));
}
@@ -227,4 +227,9 @@ public class SpigotChannelInjector implements ChannelInjector {
private PacketEventsDecoder getDecoder(Channel channel) {
return (PacketEventsDecoder) channel.pipeline().get(PacketEvents.DECODER_NAME);
}
@Override
public boolean isProxy() {
return false;
}
}
@@ -66,7 +66,7 @@ public class PacketEventsDecoder extends MessageToMessageDecoder<ByteBuf> {
//Don't print errors during handshake
if (ExceptionUtil.isException(cause, PacketProcessException.class)
&& !SpigotReflectionUtil.isMinecraftServerInstanceDebugging()
&& (user != null && user.getConnectionState() != ConnectionState.HANDSHAKING)) {
&& (user != null && user.getDecoderState() != ConnectionState.HANDSHAKING)) {
cause.printStackTrace();
}
}
@@ -115,7 +115,7 @@ public class PacketEventsEncoder extends MessageToMessageEncoder<ByteBuf> {
boolean didWeCauseThis = ExceptionUtil.isException(cause, PacketProcessException.class);
if (didWeCauseThis && user != null && user.getConnectionState() != ConnectionState.HANDSHAKING) {
if (didWeCauseThis && user != null && user.getEncoderState() != ConnectionState.HANDSHAKING) {
// Ignore handshaking exceptions
cause.printStackTrace();
return;
@@ -16,6 +16,7 @@ public class InternalBukkitPacketListener extends com.github.retrooper.packeteve
@Override
public void onPacketReceive(PacketReceiveEvent event) {
User user = event.getUser();
//Only handle Handshake uniquely on Bukkit
if (event.getPacketType() == PacketType.Handshaking.Client.HANDSHAKE) {
InetSocketAddress address = event.getSocketAddress();
WrapperHandshakingClientHandshake handshake = new WrapperHandshakingClientHandshake(event);
@@ -39,7 +40,8 @@ public class InternalBukkitPacketListener extends com.github.retrooper.packeteve
PacketEvents.getAPI().getLogManager().debug("Processed " + address.getHostString() + ":" + address.getPort() + "'s client version. Client Version: " + clientVersion.getReleaseName());
//Transition into LOGIN or STATUS connection state immediately, to remain in sync with vanilla
user.setConnectionState(nextState);
PacketEvents.getAPI().getLogManager().debug("Transitioned " + address.getHostString() + ":" + address.getPort() + " into the " + nextState + " state!");
} else {
super.onPacketReceive(event);
}
}
}
@@ -45,11 +45,11 @@ public class SpigotConversionUtil {
}
public static PotionType fromBukkitPotionEffectType(org.bukkit.potion.PotionEffectType potionEffectType) {
return PotionTypes.getById(potionEffectType.getId());
return PotionTypes.getById(potionEffectType.getId(), PacketEvents.getAPI().getServerManager().getVersion());
}
public static org.bukkit.potion.PotionEffectType toBukkitPotionEffectType(PotionType potionType) {
return org.bukkit.potion.PotionEffectType.getById(potionType.getId());
return org.bukkit.potion.PotionEffectType.getById(potionType.getId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()));
}
public static GameMode fromBukkitGameMode(org.bukkit.GameMode gameMode) {
@@ -33,7 +33,6 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.MapMaker;
import io.netty.buffer.PooledByteBufAllocator;
import org.bukkit.Bukkit;
import org.bukkit.Particle;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
@@ -65,7 +64,7 @@ public final class SpigotReflectionUtil {
//Minecraft classes
public static Class<?> MINECRAFT_SERVER_CLASS, NMS_PACKET_DATA_SERIALIZER_CLASS, NMS_ITEM_STACK_CLASS,
NMS_IMATERIAL_CLASS, NMS_ENTITY_CLASS, ENTITY_PLAYER_CLASS, BOUNDING_BOX_CLASS, NMS_MINECRAFT_KEY_CLASS,
ENTITY_HUMAN_CLASS, PLAYER_CONNECTION_CLASS, SERVER_CONNECTION_CLASS, NETWORK_MANAGER_CLASS, NMS_ENUM_PARTICLE_CLASS,
ENTITY_HUMAN_CLASS, PLAYER_CONNECTION_CLASS, SERVER_COMMON_PACKETLISTENER_IMPL_CLASS, SERVER_CONNECTION_CLASS, NETWORK_MANAGER_CLASS, NMS_ENUM_PARTICLE_CLASS,
MOB_EFFECT_LIST_CLASS, NMS_ITEM_CLASS, DEDICATED_SERVER_CLASS, NMS_WORLD_CLASS, WORLD_SERVER_CLASS, ENUM_PROTOCOL_DIRECTION_CLASS,
GAME_PROFILE_CLASS, CRAFT_WORLD_CLASS, CRAFT_SERVER_CLASS, CRAFT_PLAYER_CLASS, CRAFT_ENTITY_CLASS, CRAFT_ITEM_STACK_CLASS, CRAFT_PARTICLE_CLASS,
LEVEL_ENTITY_GETTER_CLASS, PERSISTENT_ENTITY_SECTION_MANAGER_CLASS, CRAFT_MAGIC_NUMBERS_CLASS, IBLOCK_DATA_CLASS,
@@ -128,7 +127,7 @@ public final class SpigotReflectionUtil {
}
if (DIMENSION_MANAGER_CLASS != null) {
if (PacketEvents.getAPI().getServerManager().getVersion() == ServerVersion.V_1_16
|| PacketEvents.getAPI().getServerManager().getVersion() == ServerVersion.V_1_16_1) {
|| PacketEvents.getAPI().getServerManager().getVersion() == ServerVersion.V_1_16_1) {
GET_DIMENSION_KEY = Reflection.getMethod(NMS_WORLD_CLASS, "getTypeKey", 0);
}
GET_DIMENSION_MANAGER = Reflection.getMethod(NMS_WORLD_CLASS, DIMENSION_MANAGER_CLASS, 0);
@@ -204,9 +203,13 @@ public final class SpigotReflectionUtil {
NMS_ENTITY_CLASS = getServerClass("world.entity.Entity", "Entity");
ENTITY_PLAYER_CLASS = getServerClass("server.level.EntityPlayer", "EntityPlayer");
BOUNDING_BOX_CLASS = getServerClass("world.phys.AxisAlignedBB", "AxisAlignedBB");
NMS_MINECRAFT_KEY_CLASS = getServerClass("resources.MinecraftKey" ,"MinecraftKey");
NMS_MINECRAFT_KEY_CLASS = getServerClass("resources.MinecraftKey", "MinecraftKey");
ENTITY_HUMAN_CLASS = getServerClass("world.entity.player.EntityHuman", "EntityHuman");
PLAYER_CONNECTION_CLASS = getServerClass("server.network.PlayerConnection", "PlayerConnection");
//Only on 1.20.2
SERVER_COMMON_PACKETLISTENER_IMPL_CLASS = getServerClass("server.network.ServerCommonPacketListenerImpl", "ServerCommonPacketListenerImpl");
SERVER_CONNECTION_CLASS = getServerClass("server.network.ServerConnection", "ServerConnection");
NETWORK_MANAGER_CLASS = getServerClass("network.NetworkManager", "NetworkManager");
MOB_EFFECT_LIST_CLASS = getServerClass("world.effect.MobEffectList", "MobEffectList");
@@ -429,21 +432,24 @@ public final class SpigotReflectionUtil {
if (playerConnection == null) {
return null;
}
ReflectionObject wrapper = new ReflectionObject(playerConnection, PLAYER_CONNECTION_CLASS);
Class<?> playerConnectionClass = SERVER_COMMON_PACKETLISTENER_IMPL_CLASS != null ?
SERVER_COMMON_PACKETLISTENER_IMPL_CLASS : PLAYER_CONNECTION_CLASS;
ReflectionObject wrapper = new ReflectionObject(playerConnection, playerConnectionClass);
try {
return wrapper.readObject(0, NETWORK_MANAGER_CLASS);
} catch (Exception ex) {
//Don't ask me why I do this, but this is terrible.
wrapper = new ReflectionObject(playerConnection);
//Support for some weird custom plugins.
try {
return wrapper.readObject(0, NETWORK_MANAGER_CLASS);
} catch (Exception ex2) {
//Support for some custom plugins.
playerConnection = wrapper.read(0, PLAYER_CONNECTION_CLASS);
wrapper = new ReflectionObject(playerConnection, PLAYER_CONNECTION_CLASS);
return wrapper.readObject(0, NETWORK_MANAGER_CLASS);
}
catch (Exception ex2) {
//Print the original error!
ex.printStackTrace();
}
}
return null;
}
public static Object getChannel(Player player) {
+5 -2
View File
@@ -3,6 +3,9 @@ repositories {
maven {
url 'https://papermc.io/repo/repository/maven-public/'
}
maven {
url 'https://repo.papermc.io/repository/maven-public/'
}
}
shadowJar {
@@ -13,8 +16,8 @@ shadowJar {
dependencies {
compileOnly 'io.netty:netty-all:4.1.75.Final'
compileOnly 'com.velocitypowered:velocity-api:1.0.0-SNAPSHOT'
annotationProcessor 'com.velocitypowered:velocity-api:1.0.0-SNAPSHOT'
compileOnly 'com.velocitypowered:velocity-api:3.1.0'
annotationProcessor 'com.velocitypowered:velocity-api:3.1.0'
api project(':api')
implementation project(':netty-common')
//Velocity ships with adventure & gson
@@ -23,7 +23,6 @@ import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.google.inject.Inject;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
@@ -34,33 +33,56 @@ import io.github.retrooper.packetevents.velocity.factory.VelocityPacketEventsBui
import java.util.logging.Logger;
@Plugin(id = "packetevents", name = "PacketEvents", version = "2.0.0")
@Plugin(id = "packetevents", name = "PacketEvents", version = "2.0.2")
public class PacketEventsPlugin {
private final ProxyServer server;
private final Logger logger;
private final PluginContainer pluginContainer;
@Inject
public PacketEventsPlugin(ProxyServer server, Logger logger) {
public PacketEventsPlugin(
final ProxyServer server,
final Logger logger,
final PluginContainer pluginContainer
) {
this.server = server;
this.logger = logger;
logger.info("Plugin started?");
this.pluginContainer = pluginContainer;
logger.info("Plugin started");
}
@Subscribe(order = PostOrder.LATE)
@Subscribe
public void onProxyInitialize(ProxyInitializeEvent event) {
logger.info("Injecting packetevents...");
PluginContainer plugin = server.getPluginManager().getPlugin("packetevents").orElse(null);
PacketEvents.setAPI(VelocityPacketEventsBuilder.build(server, plugin));
PacketEvents.setAPI(VelocityPacketEventsBuilder.build(server, pluginContainer));
PacketEvents.getAPI().load();
PacketEvents.getAPI().getSettings().debug(true);
PacketEvents.getAPI().getSettings().reEncodeByDefault(false);
// It should only be enabled in a development environment, not globally
// PacketEvents.getAPI().getSettings().debug(true);
PacketEvents.getAPI().getEventManager().registerListener(new PacketListenerAbstract() {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
//System.out.println("Incoming: " + event.getPacketType().getName());
//Testing sending packets to users on proxies!
/*if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
if (new WrapperPlayClientInteractEntity(event).getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
event.getUser().sendMessage(Component.text("Test message").color(NamedTextColor.RED));
event.getUser().sendTitle(Component.text("Test title").color(NamedTextColor.GREEN),
Component.text("subtitle test").color(NamedTextColor.RED),
3, 3, 5);
}
}*/
}
@Override
public void onPacketSend(PacketSendEvent event) {
//System.out.println("Outgoing: " + event.getPacketType().getName());
/*if (event.getPacketType() == PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) {
System.out.println("Before processing, pipe: " + ChannelHelper.pipelineHandlerNamesAsString(event.getChannel()));
WrapperPlayServerSystemChatMessage msg = new WrapperPlayServerSystemChatMessage(event);
System.out.println("After processing: " + msg.getMessage());
}*/
}
});
PacketEvents.getAPI().init();
@@ -89,13 +89,12 @@ public class PacketEventsDecoder extends MessageToMessageDecoder<ByteBuf> {
}
//We can use == as it is an enum constant
if (event == VELOCITY_CONNECTION_EVENT_CONSTANT && !handledCompression) {
System.out.println("constant: " + VELOCITY_CONNECTION_EVENT_CONSTANT.name());
ChannelPipeline pipe = ctx.pipeline();
PacketEventsEncoder encoder = (PacketEventsEncoder) pipe.remove(PacketEvents.ENCODER_NAME);
pipe.addBefore("minecraft-encoder", PacketEvents.ENCODER_NAME, encoder);
PacketEventsDecoder decoder = (PacketEventsDecoder) pipe.remove(PacketEvents.DECODER_NAME);
pipe.addBefore("minecraft-decoder", PacketEvents.DECODER_NAME, decoder);
System.out.println("Pipe: " + ChannelHelper.pipelineHandlerNamesAsString(ctx.channel()));
//System.out.println("Pipe: " + ChannelHelper.pipelineHandlerNamesAsString(ctx.channel()));
handledCompression = true;
}
super.userEventTriggered(ctx, event);
@@ -103,4 +103,9 @@ public class VelocityPipelineInjector implements ChannelInjector {
PacketEventsEncoder encoder = (PacketEventsEncoder) channel.pipeline().get(PacketEvents.ENCODER_NAME);
encoder.player = player;
}
@Override
public boolean isProxy() {
return true;
}
}
@@ -94,7 +94,7 @@ public class VelocityPacketEventsBuilder {
public ServerVersion getVersion() {
if (version == null) {
String velocityVersion = com.velocitypowered.api.network.ProtocolVersion.MAXIMUM_VERSION
.getName();
.getVersionIntroducedIn();
for (final ServerVersion val : ServerVersion.values()) {
if (val.getReleaseName().contains(velocityVersion)) {
@@ -169,7 +169,7 @@ public class VelocityPacketEventsBuilder {
}
if (settings.isbStatsEnabled()) {
// TODO Cross-platform metrics?
// TODO: Velocity bstats
}
PacketType.Play.Client.load();