Compare commits

..
9 Commits
7 changed files with 152 additions and 63 deletions

No files matched your search

+54
View File
@@ -1,3 +1,57 @@
!!!!! v2.9.4
# PacketEvents 2.9.4 is out now! 🎉
This update includes minor bug fixes & minor additions to the API.
# Brief Announcement 📢⚠️
### We have our very own website: https://packetevents.com
### Documentation: https://docs.packetevents.com
### JavaDocs: https://javadocs.packetevents.com
## What's Changed (Summary)
* Added SpigotConversionUtil#getEntityMetadata to retrieve metadata from a Bukkit entity.
* Fixed outdated 1.8 Spigot forks from being unable to load on PacketEvents.
* Fixed WrapperPlayServerWorldBorder for versions lower than 1.12.
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.3...v2.9.4
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
## Maven/Gradle Dependency
### **Check out**: https://docs.packetevents.com/getting-started
!!!!! v2.9.3
# PacketEvents 2.9.3 is out now! 🎉
This is an update that adds support for Minecraft 1.21.8 server builds.
# Brief Announcement 📢⚠️
### We have our very own website: https://packetevents.com
### Documentation: https://docs.packetevents.com
### JavaDocs: https://javadocs.packetevents.com
## What's Changed (Summary)
* Added support for 1.21.8 Minecraft server builds.
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.2...v2.9.3
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
## Maven/Gradle Dependency
### **Check out**: https://docs.packetevents.com/getting-started
!!!!! v2.9.2
# PacketEvents 2.9.2 is out now! 🎉
@@ -51,7 +51,7 @@ public enum ServerVersion {
//1.20 and 1.20.1 have the same protocol version. 1.20.3 and 1.20.4 have the same protocol version. 1.20.5 and 1.20.6 have the same protocol version
V_1_20(763), V_1_20_1(763), V_1_20_2(764), V_1_20_3(765), V_1_20_4(765), V_1_20_5(766), V_1_20_6(766),
//1.21 and 1.21.1 have the same protocol version. 1.21.2 and 1.21.3 have the same protocol version
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769), V_1_21_5(770), V_1_21_6(771), V_1_21_7(772),
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769), V_1_21_5(770), V_1_21_6(771), V_1_21_7(772), V_1_21_8(772),
//TODO UPDATE Add server version constant
ERROR(-1, true);
@@ -93,9 +93,7 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
@Override
public void read() {
int actionId = readVarInt();
action = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_12) ? WorldBorderAction.fromId(actionId)
: WorldBorderAction.fromLegacyId(actionId);
action = readEnum(WorldBorderAction.class);
if (this.action == WorldBorderAction.SET_SIZE) {
this.radius = readDouble();
} else if (this.action == WorldBorderAction.LERP_SIZE) {
@@ -123,8 +121,7 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
@Override
public void write() {
int actionId = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_12) ? action.getId() : action.getLegacyId();
writeVarInt(actionId);
writeEnum(action);
if (this.action == WorldBorderAction.SET_SIZE) {
writeDouble(this.radius);
} else if (this.action == WorldBorderAction.LERP_SIZE) {
@@ -245,38 +242,20 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
}
public enum WorldBorderAction {
SET_SIZE(1),
LERP_SIZE(2),
SET_CENTER(3),
INITIALIZE(6),
SET_WARNING_TIME(5),
SET_WARNING_BLOCKS(4);
SET_SIZE,
LERP_SIZE,
SET_CENTER,
INITIALIZE,
SET_WARNING_TIME,
SET_WARNING_BLOCKS;
private final int legacyId;
WorldBorderAction(int legacyId) {
this.legacyId = legacyId;
}
public int getId() {
return ordinal();
}
public int getLegacyId() {
return legacyId;
}
public static WorldBorderAction fromId(int id) {
return WorldBorderAction.values()[id];
}
public static WorldBorderAction fromLegacyId(int legacyId) {
for (WorldBorderAction action : WorldBorderAction.values()) {
if (action.legacyId == legacyId) {
return action;
}
}
return null;
}
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
org.gradle.jvmargs=-Xmx2000m
# TODO UPDATE
fullVersion=2.9.2
fullVersion=2.9.4
snapshot=false
publishing.display_name=PacketEvents
@@ -144,16 +144,23 @@ public class SpigotPacketEventsBuilder {
if (!initialized) {
Plugin plugin = (Plugin) PacketEvents.getAPI().getPlugin();
String bukkitVersion = Bukkit.getBukkitVersion();
// Our PEVersion class can parse this version and detect if it is a newer version than what is currently supported
PEVersion bukkitServerVersion = PEVersion.fromString(bukkitVersion.substring(0, bukkitVersion.indexOf("-")));
PEVersion latestSupportedVersion = PEVersion.fromString(ServerVersion.getLatest().getReleaseName());
if (bukkitServerVersion.isNewerThan(latestSupportedVersion)) {
//We do not support this version yet, so let us warn the user
plugin.getLogger().warning("Your build of PacketEvents does not support the Minecraft version "
+ bukkitServerVersion + "! The latest Minecraft version supported by your build of PacketEvents is " + latestSupportedVersion
+ ". Please test the development builds, as they may already have support for your Minecraft version (hint: select the build that contains 'spigot'): https://ci.codemc.io/job/retrooper/job/packetevents/ If you're in need of any help, join our Discord server: https://discord.gg/DVHxPPxHZc");
Bukkit.getPluginManager().disablePlugin(plugin);
return;
if (bukkitVersion.contains("Unknown")) {
ServerVersion fallbackVersion = ServerVersion.V_1_8_8;
String failureToDetectVersionMsg = "Your server software is preventing us from checking the Minecraft Server version. This is what we found: " + bukkitVersion + ". We will assume the Server version is " + fallbackVersion.name() + "...\n If you need assistance, join our Discord server: https://discord.gg/DVHxPPxHZc";
plugin.getLogger().warning(failureToDetectVersionMsg);
} else {
// Our PEVersion class can parse this version and detect if it is a newer version than what is currently supported
PEVersion bukkitServerVersion = PEVersion.fromString(bukkitVersion.substring(0, bukkitVersion.indexOf("-")));
PEVersion latestSupportedVersion = PEVersion.fromString(ServerVersion.getLatest().getReleaseName());
if (bukkitServerVersion.isNewerThan(latestSupportedVersion)) {
//We do not support this version yet, so let us warn the user
plugin.getLogger().warning("Your build of PacketEvents does not support the Minecraft version "
+ bukkitServerVersion + "! The latest Minecraft version supported by your build of PacketEvents is " + latestSupportedVersion
+ ". Please test the development builds, as they may already have support for your Minecraft version (hint: select the build that contains 'spigot'): https://ci.codemc.io/job/retrooper/job/packetevents/ If you're in need of any help, join our Discord server: https://discord.gg/DVHxPPxHZc");
Bukkit.getPluginManager().disablePlugin(plugin);
return;
}
}
if (settings.shouldCheckForUpdates()) {
getUpdateChecker().handleUpdateCheck();
@@ -20,6 +20,7 @@ package io.github.retrooper.packetevents.util;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
@@ -41,10 +42,13 @@ import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.SimpleTypesBuilderData;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Pose;
import org.bukkit.inventory.MainHand;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SpigotConversionUtil {
public static Location fromBukkitLocation(org.bukkit.Location location) {
return new Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
@@ -233,4 +237,16 @@ public class SpigotConversionUtil {
public static MainHand toBukkitHand(HumanoidArm arm) {
return MainHand.values()[arm.ordinal()];
}
/**
* Retrieves the metadata of a given Bukkit {@link org.bukkit.entity.Entity},
* returned as a list of {@link com.github.retrooper.packetevents.protocol.entity.data.EntityData}
* compatible with PacketEvents.
*
* @param entity the Bukkit entity to extract metadata from
* @return a list of the entity's metadata values
*/
public static List<EntityData<?>> getEntityMetadata(Entity entity) {
return SpigotReflectionUtil.getEntityMetadata(entity);
}
}
@@ -22,46 +22,33 @@ import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.reflection.NestedClassUtil;
import com.github.retrooper.packetevents.util.reflection.Reflection;
import com.github.retrooper.packetevents.util.reflection.ReflectionObject;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.google.common.collect.BiMap;
import com.google.common.collect.MapMaker;
import io.netty.buffer.PooledByteBufAllocator;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
@@ -103,7 +90,8 @@ public final class SpigotReflectionUtil {
DYNAMIC_OPS_NBT_CLASS, NMS_NBT_COMPOUND_CLASS, NMS_NBT_BASE_CLASS, NBT_COMPRESSION_STREAM_TOOLS_CLASS,
STREAM_CODEC, STREAM_DECODER, STREAM_ENCODER, REGISTRY_FRIENDLY_BYTE_BUF, REGISTRY_ACCESS, REGISTRY_ACCESS_FROZEN,
RESOURCE_KEY, REGISTRY, WRITABLE_REGISTRY, NBT_ACCOUNTER, CHUNK_PROVIDER_SERVER_CLASS, ICHUNKPROVIDER_CLASS, CHUNK_STATUS_CLASS,
BLOCK_POSITION_CLASS, PLAYER_CHUNK_MAP_CLASS, PLAYER_CHUNK_CLASS, CHUNK_CLASS, IBLOCKACCESS_CLASS, ICHUNKACCESS_CLASS, REMOTE_CHAT_SESSION_CLASS;
BLOCK_POSITION_CLASS, PLAYER_CHUNK_MAP_CLASS, PLAYER_CHUNK_CLASS, CHUNK_CLASS, IBLOCKACCESS_CLASS, ICHUNKACCESS_CLASS, REMOTE_CHAT_SESSION_CLASS,
DATA_WATCHER_CLASS, CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS, DATA_WATCHER_ITEM_CLASS, DATA_WATCHER_VALUE_CLASS;
//Netty classes
public static Class<?> CHANNEL_CLASS, BYTE_BUF_CLASS, BYTE_TO_MESSAGE_DECODER, MESSAGE_TO_BYTE_ENCODER;
@@ -111,7 +99,7 @@ public final class SpigotReflectionUtil {
//Fields
public static Field ENTITY_PLAYER_PING_FIELD, ENTITY_BOUNDING_BOX_FIELD, BYTE_BUF_IN_PACKET_DATA_SERIALIZER, DIMENSION_CODEC_FIELD,
DYNAMIC_OPS_NBT_INSTANCE_FIELD, CHUNK_PROVIDER_SERVER_FIELD, CRAFT_PARTICLE_PARTICLES_FIELD, NMS_MK_KEY_FIELD, LEGACY_NMS_PARTICLE_KEY_FIELD, LEGACY_NMS_KEY_TO_NMS_PARTICLE,
REMOTE_CHAT_SESSION_FIELD, REGISTRY_KEY_LOCATION_FIELD;
REMOTE_CHAT_SESSION_FIELD, REGISTRY_KEY_LOCATION_FIELD, DATA_WATCHER_FIELD;
//Methods
public static Method IS_DEBUGGING, GET_CRAFT_PLAYER_HANDLE_METHOD, GET_CRAFT_ENTITY_HANDLE_METHOD, GET_CRAFT_WORLD_HANDLE_METHOD,
@@ -125,7 +113,8 @@ public final class SpigotReflectionUtil {
READ_NBT_FROM_STREAM_METHOD, WRITE_NBT_TO_STREAM_METHOD, STREAM_DECODER_DECODE, STREAM_ENCODER_ENCODE,
CREATE_REGISTRY_RESOURCE_KEY, GET_REGISTRY_OR_THROW, GET_DIMENSION_TYPES, GET_REGISTRY_ID,
NBT_ACCOUNTER_UNLIMITED_HEAP, CHUNK_CACHE_GET_IBLOCKACCESS, CHUNK_CACHE_GET_ICHUNKACCESS,
IBLOCKACCESS_GET_BLOCK_DATA, CHUNK_GET_BLOCK_DATA, PLAYER_CHUNK_MAP_GET_PLAYER_CHUNK, PLAYER_CHUNK_GET_CHUNK;
IBLOCKACCESS_GET_BLOCK_DATA, CHUNK_GET_BLOCK_DATA, PLAYER_CHUNK_MAP_GET_PLAYER_CHUNK, PLAYER_CHUNK_GET_CHUNK,
LEGACY_DATA_WATCHER_WRITE_METHOD, CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD, GET_DATA_VALUE_FROM_DATA_ITEM_METHOD;
//Constructors
private static Constructor<?> NMS_ITEM_STACK_CONSTRUCTOR, NMS_PACKET_DATA_SERIALIZER_CONSTRUCTOR,
@@ -275,6 +264,10 @@ public final class SpigotReflectionUtil {
if (CHUNK_CLASS != null) {
PLAYER_CHUNK_GET_CHUNK = Reflection.getMethod(SpigotReflectionUtil.PLAYER_CHUNK_CLASS, SpigotReflectionUtil.CHUNK_CLASS, 0);
}
LEGACY_DATA_WATCHER_WRITE_METHOD = Reflection.getMethod(DATA_WATCHER_CLASS, void.class, 0, NMS_PACKET_DATA_SERIALIZER_CLASS);
CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD = Reflection.getMethod(CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS, 0, List.class, REGISTRY_FRIENDLY_BYTE_BUF);
GET_DATA_VALUE_FROM_DATA_ITEM_METHOD = Reflection.getMethod(DATA_WATCHER_ITEM_CLASS, DATA_WATCHER_VALUE_CLASS, 0);
}
private static void initFields() {
@@ -302,6 +295,7 @@ public final class SpigotReflectionUtil {
REMOTE_CHAT_SESSION_FIELD = Reflection.getField(ENTITY_PLAYER_CLASS, REMOTE_CHAT_SESSION_CLASS, 0);
REGISTRY_KEY_LOCATION_FIELD = Reflection.getField(RESOURCE_KEY, NMS_MINECRAFT_KEY_CLASS, 1);
DATA_WATCHER_FIELD = Reflection.getField(NMS_ENTITY_CLASS, DATA_WATCHER_CLASS, 0, true);
}
private static void initClasses() {
@@ -402,6 +396,14 @@ public final class SpigotReflectionUtil {
WRITABLE_REGISTRY = getServerClass(IS_OBFUSCATED ? "core.IRegistryWritable" : "core.WritableRegistry", "IRegistryWritable");
REMOTE_CHAT_SESSION_CLASS = Reflection.getClassByNameWithoutException("net.minecraft.network.chat.RemoteChatSession");
DATA_WATCHER_CLASS = SpigotReflectionUtil.getServerClass("network.syncher.DataWatcher", "DataWatcher");
if (DATA_WATCHER_CLASS == null) {
DATA_WATCHER_CLASS = SpigotReflectionUtil.getServerClass("network.syncher.SynchedEntityData", "DataWatcher");
}
CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS = SpigotReflectionUtil.getServerClass("network.protocol.game.ClientboundSetEntityDataPacket", "PacketPlayOutEntityMetadata");
DATA_WATCHER_ITEM_CLASS = NestedClassUtil.getNestedClass(DATA_WATCHER_CLASS, 0);
DATA_WATCHER_VALUE_CLASS = NestedClassUtil.getNestedClass(DATA_WATCHER_CLASS, 1);
}
private static void initObjects() {
@@ -1207,4 +1209,35 @@ public final class SpigotReflectionUtil {
return null;
}
}
public static List<EntityData<?>> getEntityMetadata(@NotNull Entity entity) {
Object byteBuf = PacketEvents.getAPI().getNettyManager().getByteBufAllocationOperator().buffer();
try {
Object handle = SpigotReflectionUtil.getNMSEntity(entity);
Object dataWatcher = DATA_WATCHER_FIELD.get(handle);
Object packetDataSerializer = createPacketDataSerializer(byteBuf);
if (LEGACY_DATA_WATCHER_WRITE_METHOD != null) {
// Legacy Minecraft versions have the DataWatcher class with a method to write to the PacketDataSerializer
LEGACY_DATA_WATCHER_WRITE_METHOD.invoke(dataWatcher, packetDataSerializer);
}
else {
// Modern Minecraft versions require the use of the pack method in the ClientboundSetEntityDataPacket class.
Object[] dataItems = new ReflectionObject(dataWatcher).readObjectArray(0, DATA_WATCHER_ITEM_CLASS);
List<Object> dataValues = new ArrayList<>(dataItems.length);
for (Object dataItem : dataItems) {
dataValues.add(GET_DATA_VALUE_FROM_DATA_ITEM_METHOD.invoke(dataItem));
}
CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD.invoke(null, dataValues, packetDataSerializer);
}
PacketWrapper<?> packetWrapper = PacketWrapper.createUniversalPacketWrapper(byteBuf);
return packetWrapper.readEntityMetadata();
} catch (Exception e) {
throw new RuntimeException(e);
}
finally {
ByteBufHelper.release(byteBuf);
}
}
}