Drop support for less used minor Minecraft versions (1.16.0 to 1.16.3)

This commit is contained in:
filoghost 2023-03-19 16:49:08 +01:00
parent 27ebb9d2d8
commit d057dd750c
36 changed files with 2 additions and 1727 deletions

View File

@ -32,8 +32,8 @@ public enum NMSVersion {
/* 1.13.1 - 1.13.2 */ v1_13_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_13_R2.VersionNMSManager(errorCollector)),
/* 1.14 - 1.14.4 */ v1_14_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_14_R1.VersionNMSManager(errorCollector)),
/* 1.15 - 1.15.2 */ v1_15_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_15_R1.VersionNMSManager(errorCollector)),
/* 1.16 - 1.16.1 */ v1_16_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R1.VersionNMSManager(errorCollector)),
/* 1.16.2 - 1.16.3 */ v1_16_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R2.VersionNMSManager(errorCollector)),
/* 1.16 - 1.16.1 */ v1_16_R1(NMSManagerFactory.outdatedVersion("1.16.4")),
/* 1.16.2 - 1.16.3 */ v1_16_R2(NMSManagerFactory.outdatedVersion("1.16.4")),
/* 1.16.4 - 1.16.5 */ v1_16_R3(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R3.VersionNMSManager(errorCollector)),
/* 1.17 */ v1_17_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_17_R1.VersionNMSManager(errorCollector)),
/* 1.18 - 1.18.1 */ v1_18_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_18_R1.VersionNMSManager(errorCollector)),

View File

@ -23,8 +23,6 @@
<module>v1_13_r2</module>
<module>v1_14_r1</module>
<module>v1_15_r1</module>
<module>v1_16_r1</module>
<module>v1_16_r2</module>
<module>v1_16_r3</module>
<module>v1_17_r1</module>
<module>v1_18_r1</module>

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.2-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_16_r1</artifactId>
<name>HolographicDisplays NMS v1_16_R1</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-common</artifactId>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import io.netty.handler.codec.EncoderException;
import net.minecraft.server.v1_16_R1.DataWatcherRegistry;
import net.minecraft.server.v1_16_R1.DataWatcherSerializer;
import net.minecraft.server.v1_16_R1.IChatBaseComponent;
import net.minecraft.server.v1_16_R1.ItemStack;
import java.util.Optional;
class DataWatcherKey<T> {
private static final DataWatcherSerializer<Byte> BYTE_SERIALIZER = DataWatcherRegistry.a;
private static final DataWatcherSerializer<Integer> INT_SERIALIZER = DataWatcherRegistry.b;
private static final DataWatcherSerializer<Boolean> BOOLEAN_SERIALIZER = DataWatcherRegistry.i;
private static final DataWatcherSerializer<ItemStack> ITEM_STACK_SERIALIZER = DataWatcherRegistry.g;
private static final DataWatcherSerializer<Optional<IChatBaseComponent>> OPTIONAL_CHAT_COMPONENT_SERIALIZER = DataWatcherRegistry.f;
static final DataWatcherKey<Byte> ENTITY_STATUS = new DataWatcherKey<>(0, BYTE_SERIALIZER);
static final DataWatcherKey<Optional<IChatBaseComponent>> CUSTOM_NAME = new DataWatcherKey<>(2, OPTIONAL_CHAT_COMPONENT_SERIALIZER);
static final DataWatcherKey<Boolean> CUSTOM_NAME_VISIBILITY = new DataWatcherKey<>(3, BOOLEAN_SERIALIZER);
static final DataWatcherKey<ItemStack> ITEM_STACK = new DataWatcherKey<>(7, ITEM_STACK_SERIALIZER);
static final DataWatcherKey<Byte> ARMOR_STAND_STATUS = new DataWatcherKey<>(14, BYTE_SERIALIZER);
static final DataWatcherKey<Integer> SLIME_SIZE = new DataWatcherKey<>(15, INT_SERIALIZER);
private final int index;
private final DataWatcherSerializer<T> serializer;
private final int serializerTypeID;
private DataWatcherKey(int index, DataWatcherSerializer<T> serializer) {
this.index = index;
this.serializer = serializer;
this.serializerTypeID = DataWatcherRegistry.b(serializer);
if (serializerTypeID < 0) {
throw new EncoderException("Could not find serializer ID of " + serializer);
}
}
int getIndex() {
return index;
}
DataWatcherSerializer<T> getSerializer() {
return serializer;
}
int getSerializerTypeID() {
return serializerTypeID;
}
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.fcommons.Strings;
import net.minecraft.server.v1_16_R1.IChatBaseComponent;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_16_R1.util.CraftChatMessage;
import org.bukkit.inventory.ItemStack;
import java.util.Optional;
abstract class DataWatcherPacketBuilder<T> {
private static final int MAX_CUSTOM_NAME_LENGTH = 5000;
private final PacketByteBuffer packetByteBuffer;
DataWatcherPacketBuilder(PacketByteBuffer packetByteBuffer) {
this.packetByteBuffer = packetByteBuffer;
}
DataWatcherPacketBuilder<T> setInvisible() {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ENTITY_STATUS, (byte) 0x20); // Invisible
return this;
}
DataWatcherPacketBuilder<T> setArmorStandMarker() {
setInvisible();
packetByteBuffer.writeDataWatcherEntry(
DataWatcherKey.ARMOR_STAND_STATUS, (byte) (0x01 | 0x02 | 0x08 | 0x10)); // Small, no gravity, no base plate, marker
return this;
}
DataWatcherPacketBuilder<T> setCustomName(String customName) {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.CUSTOM_NAME, getCustomNameDataWatcherValue(customName));
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.CUSTOM_NAME_VISIBILITY, !Strings.isEmpty(customName));
return this;
}
private Optional<IChatBaseComponent> getCustomNameDataWatcherValue(String customName) {
customName = Strings.truncate(customName, MAX_CUSTOM_NAME_LENGTH);
if (!Strings.isEmpty(customName)) {
return Optional.of(CraftChatMessage.fromString(customName, false)[0]);
} else {
return Optional.empty();
}
}
DataWatcherPacketBuilder<T> setItemStack(ItemStack itemStack) {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack));
return this;
}
DataWatcherPacketBuilder<T> setSlimeSmall() {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.SLIME_SIZE, 1);
return this;
}
T build() {
packetByteBuffer.writeDataWatcherEntriesEnd();
return createPacket(packetByteBuffer);
}
abstract T createPacket(PacketByteBuffer packetByteBuffer);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutEntityDestroy;
class EntityDestroyNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityDestroyNMSPacket(EntityID entityID) {
this.rawPacket = new PacketPlayOutEntityDestroy(entityID.getNumericID());
}
EntityDestroyNMSPacket(EntityID entityID1, EntityID entityID2) {
this.rawPacket = new PacketPlayOutEntityDestroy(entityID1.getNumericID(), entityID2.getNumericID());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutSpawnEntityLiving;
class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityLivingSpawnNMSPacket(EntityID entityID, int entityTypeID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
packetByteBuffer.writeUUID(entityID.getUUID());
packetByteBuffer.writeVarInt(entityTypeID);
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// Head rotation
packetByteBuffer.writeByte(0);
// Velocity
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutEntityMetadata;
class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
public static DataWatcherPacketBuilder<EntityMetadataNMSPacket> builder(EntityID entityID) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
return new Builder(packetByteBuffer);
}
private static class Builder extends DataWatcherPacketBuilder<EntityMetadataNMSPacket> {
private Builder(PacketByteBuffer packetByteBuffer) {
super(packetByteBuffer);
}
@Override
EntityMetadataNMSPacket createPacket(PacketByteBuffer packetByteBuffer) {
return new EntityMetadataNMSPacket(packetByteBuffer);
}
}
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutMount;
class EntityMountNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityMountNMSPacket(EntityID vehicleEntityID, EntityID passengerEntityID) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutSpawnEntity;
class EntitySpawnNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntitySpawnNMSPacket(EntityID entityID, int entityTypeID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
packetByteBuffer.writeUUID(entityID.getUUID());
packetByteBuffer.writeVarInt(entityTypeID);
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// Object data
if (entityTypeID == EntityTypeID.ITEM) {
packetByteBuffer.writeInt(1); // Velocity is present and zero (otherwise by default a random velocity is applied)
} else {
packetByteBuffer.writeInt(0);
}
// Velocity
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketPlayOutEntityTeleport;
class EntityTeleportNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityTeleportNMSPacket(EntityID entityID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
class EntityTypeID {
static final int ARMOR_STAND = 1;
static final int ITEM = 37;
static final int SLIME = 75;
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
import me.filoghost.holographicdisplays.nms.common.NMSErrors;
import me.filoghost.holographicdisplays.nms.common.PacketListener;
import net.minecraft.server.v1_16_R1.PacketPlayInUseEntity;
import org.bukkit.entity.Player;
class InboundPacketHandler extends ChannelInboundHandlerAdapter {
public static final String HANDLER_NAME = "holographic_displays_listener";
private static final ReflectField<Integer> ENTITY_ID_FIELD = ReflectField.lookup(int.class, PacketPlayInUseEntity.class, "a");
private final Player player;
private final PacketListener packetListener;
InboundPacketHandler(Player player, PacketListener packetListener) {
this.player = player;
this.packetListener = packetListener;
}
@Override
public void channelRead(ChannelHandlerContext context, Object packet) throws Exception {
try {
if (packet instanceof PacketPlayInUseEntity) {
int entityID = ENTITY_ID_FIELD.get(packet);
boolean cancel = packetListener.onAsyncEntityInteract(player, entityID);
if (cancel) {
return;
}
}
} catch (Throwable t) {
Log.warning(NMSErrors.EXCEPTION_ON_PACKET_READ, t);
}
super.channelRead(context, packet);
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_16_R1.Packet;
import net.minecraft.server.v1_16_R1.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
}
private PacketByteBuffer() {
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
serializer.d(i);
}
void writeVarIntArray(int i1) {
writeVarInt(1);
writeVarInt(i1);
}
void writeUUID(UUID uuid) {
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.ClickableNMSPacketEntity;
class VersionClickableNMSPacketEntity implements ClickableNMSPacketEntity {
private final EntityID slimeID;
VersionClickableNMSPacketEntity(EntityID slimeID) {
this.slimeID = slimeID;
}
@Override
public EntityID getID() {
return slimeID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(slimeID, EntityTypeID.SLIME, position, SLIME_Y_OFFSET),
EntityMetadataNMSPacket.builder(slimeID)
.setInvisible()
.setSlimeSmall() // Required for a correct client-side collision box
.build()
);
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(slimeID, position, SLIME_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(slimeID);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import org.bukkit.inventory.ItemStack;
class VersionItemNMSPacketEntity implements ItemNMSPacketEntity {
private final EntityID itemID;
private final EntityID vehicleID;
VersionItemNMSPacketEntity(EntityID itemID, EntityID vehicleID) {
this.itemID = itemID;
this.vehicleID = vehicleID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position, ItemStack itemStack) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(vehicleID, EntityTypeID.ARMOR_STAND, position, ITEM_Y_OFFSET),
EntityMetadataNMSPacket.builder(vehicleID)
.setArmorStandMarker()
.build(),
new EntitySpawnNMSPacket(itemID, EntityTypeID.ITEM, position, ITEM_Y_OFFSET),
EntityMetadataNMSPacket.builder(itemID)
.setItemStack(itemStack)
.build(),
new EntityMountNMSPacket(vehicleID, itemID)
);
}
@Override
public PacketGroup newChangePackets(ItemStack itemStack) {
return EntityMetadataNMSPacket.builder(itemID)
.setItemStack(itemStack)
.build();
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(vehicleID, position, ITEM_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(itemID, vehicleID);
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.FallbackEntityIDGenerator;
import me.filoghost.holographicdisplays.nms.common.NMSErrors;
import me.filoghost.holographicdisplays.nms.common.NMSManager;
import me.filoghost.holographicdisplays.nms.common.PacketListener;
import me.filoghost.holographicdisplays.nms.common.entity.ClickableNMSPacketEntity;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
import net.minecraft.server.v1_16_R1.Entity;
import net.minecraft.server.v1_16_R1.NetworkManager;
import net.minecraft.server.v1_16_R1.PlayerConnection;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class VersionNMSManager implements NMSManager {
private static final ReflectField<AtomicInteger> ENTITY_ID_COUNTER_FIELD =
ReflectField.lookup(AtomicInteger.class, Entity.class, "entityCount");
private final Supplier<Integer> entityIDGenerator;
public VersionNMSManager(ErrorCollector errorCollector) {
this.entityIDGenerator = getEntityIDGenerator(errorCollector);
// Force initialization of class to eventually throw exceptions early
DataWatcherKey.ENTITY_STATUS.getIndex();
}
private Supplier<Integer> getEntityIDGenerator(ErrorCollector errorCollector) {
try {
AtomicInteger nmsEntityIDCounter = ENTITY_ID_COUNTER_FIELD.getStatic();
return nmsEntityIDCounter::incrementAndGet;
} catch (ReflectiveOperationException e) {
errorCollector.add(e, NMSErrors.EXCEPTION_GETTING_ENTITY_ID_GENERATOR);
return new FallbackEntityIDGenerator();
}
}
private EntityID newEntityID() {
return new EntityID(entityIDGenerator);
}
@Override
public TextNMSPacketEntity newTextPacketEntity() {
return new VersionTextNMSPacketEntity(newEntityID());
}
@Override
public ItemNMSPacketEntity newItemPacketEntity() {
return new VersionItemNMSPacketEntity(newEntityID(), newEntityID());
}
@Override
public ClickableNMSPacketEntity newClickablePacketEntity() {
return new VersionClickableNMSPacketEntity(newEntityID());
}
@Override
public void injectPacketListener(Player player, PacketListener packetListener) {
modifyPipeline(player, (ChannelPipeline pipeline) -> {
ChannelHandler currentListener = pipeline.get(InboundPacketHandler.HANDLER_NAME);
if (currentListener != null) {
pipeline.remove(InboundPacketHandler.HANDLER_NAME);
}
pipeline.addBefore("packet_handler", InboundPacketHandler.HANDLER_NAME, new InboundPacketHandler(player, packetListener));
});
}
@Override
public void uninjectPacketListener(Player player) {
modifyPipeline(player, (ChannelPipeline pipeline) -> {
ChannelHandler currentListener = pipeline.get(InboundPacketHandler.HANDLER_NAME);
if (currentListener != null) {
pipeline.remove(InboundPacketHandler.HANDLER_NAME);
}
});
}
/*
* Modifying the pipeline in the main thread can cause deadlocks, delays and other concurrency issues,
* which can be avoided by using the event loop. Thanks to ProtocolLib for this insight.
*/
private void modifyPipeline(Player player, Consumer<ChannelPipeline> pipelineModifierTask) {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
channel.eventLoop().execute(() -> {
if (!player.isOnline()) {
return;
}
try {
pipelineModifierTask.accept(channel.pipeline());
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import net.minecraft.server.v1_16_R1.Packet;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
abstract class VersionNMSPacket implements PacketGroup {
@Override
public void sendTo(Player player) {
((CraftPlayer) player).getHandle().playerConnection.sendPacket(getRawPacket());
}
abstract Packet<?> getRawPacket();
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R1;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
class VersionTextNMSPacketEntity implements TextNMSPacketEntity {
private final EntityID armorStandID;
VersionTextNMSPacketEntity(EntityID armorStandID) {
this.armorStandID = armorStandID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position, String text) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(armorStandID, EntityTypeID.ARMOR_STAND, position, ARMOR_STAND_Y_OFFSET),
EntityMetadataNMSPacket.builder(armorStandID)
.setArmorStandMarker()
.setCustomName(text)
.build()
);
}
@Override
public IndividualTextPacketGroup newSpawnPackets(PositionCoordinates position) {
return IndividualTextPacketGroup.of(
new EntityLivingSpawnNMSPacket(armorStandID, EntityTypeID.ARMOR_STAND, position, ARMOR_STAND_Y_OFFSET),
(String text) -> EntityMetadataNMSPacket.builder(armorStandID)
.setArmorStandMarker()
.setCustomName(text)
.build()
);
}
@Override
public PacketGroup newChangePackets(String text) {
return EntityMetadataNMSPacket.builder(armorStandID)
.setCustomName(text)
.build();
}
@Override
public IndividualTextPacketGroup newChangePackets() {
return IndividualTextPacketGroup.of(
(String text) -> EntityMetadataNMSPacket.builder(armorStandID)
.setCustomName(text)
.build()
);
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(armorStandID, position, ARMOR_STAND_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(armorStandID);
}
}

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.2-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_16_r2</artifactId>
<name>HolographicDisplays NMS v1_16_R2</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-common</artifactId>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.16.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import io.netty.handler.codec.EncoderException;
import net.minecraft.server.v1_16_R2.DataWatcherRegistry;
import net.minecraft.server.v1_16_R2.DataWatcherSerializer;
import net.minecraft.server.v1_16_R2.IChatBaseComponent;
import net.minecraft.server.v1_16_R2.ItemStack;
import java.util.Optional;
class DataWatcherKey<T> {
private static final DataWatcherSerializer<Byte> BYTE_SERIALIZER = DataWatcherRegistry.a;
private static final DataWatcherSerializer<Integer> INT_SERIALIZER = DataWatcherRegistry.b;
private static final DataWatcherSerializer<Boolean> BOOLEAN_SERIALIZER = DataWatcherRegistry.i;
private static final DataWatcherSerializer<ItemStack> ITEM_STACK_SERIALIZER = DataWatcherRegistry.g;
private static final DataWatcherSerializer<Optional<IChatBaseComponent>> OPTIONAL_CHAT_COMPONENT_SERIALIZER = DataWatcherRegistry.f;
static final DataWatcherKey<Byte> ENTITY_STATUS = new DataWatcherKey<>(0, BYTE_SERIALIZER);
static final DataWatcherKey<Optional<IChatBaseComponent>> CUSTOM_NAME = new DataWatcherKey<>(2, OPTIONAL_CHAT_COMPONENT_SERIALIZER);
static final DataWatcherKey<Boolean> CUSTOM_NAME_VISIBILITY = new DataWatcherKey<>(3, BOOLEAN_SERIALIZER);
static final DataWatcherKey<ItemStack> ITEM_STACK = new DataWatcherKey<>(7, ITEM_STACK_SERIALIZER);
static final DataWatcherKey<Byte> ARMOR_STAND_STATUS = new DataWatcherKey<>(14, BYTE_SERIALIZER);
static final DataWatcherKey<Integer> SLIME_SIZE = new DataWatcherKey<>(15, INT_SERIALIZER);
private final int index;
private final DataWatcherSerializer<T> serializer;
private final int serializerTypeID;
private DataWatcherKey(int index, DataWatcherSerializer<T> serializer) {
this.index = index;
this.serializer = serializer;
this.serializerTypeID = DataWatcherRegistry.b(serializer);
if (serializerTypeID < 0) {
throw new EncoderException("Could not find serializer ID of " + serializer);
}
}
int getIndex() {
return index;
}
DataWatcherSerializer<T> getSerializer() {
return serializer;
}
int getSerializerTypeID() {
return serializerTypeID;
}
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.fcommons.Strings;
import net.minecraft.server.v1_16_R2.IChatBaseComponent;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_16_R2.util.CraftChatMessage;
import org.bukkit.inventory.ItemStack;
import java.util.Optional;
abstract class DataWatcherPacketBuilder<T> {
private static final int MAX_CUSTOM_NAME_LENGTH = 5000;
private final PacketByteBuffer packetByteBuffer;
DataWatcherPacketBuilder(PacketByteBuffer packetByteBuffer) {
this.packetByteBuffer = packetByteBuffer;
}
DataWatcherPacketBuilder<T> setInvisible() {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ENTITY_STATUS, (byte) 0x20); // Invisible
return this;
}
DataWatcherPacketBuilder<T> setArmorStandMarker() {
setInvisible();
packetByteBuffer.writeDataWatcherEntry(
DataWatcherKey.ARMOR_STAND_STATUS, (byte) (0x01 | 0x02 | 0x08 | 0x10)); // Small, no gravity, no base plate, marker
return this;
}
DataWatcherPacketBuilder<T> setCustomName(String customName) {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.CUSTOM_NAME, getCustomNameDataWatcherValue(customName));
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.CUSTOM_NAME_VISIBILITY, !Strings.isEmpty(customName));
return this;
}
private Optional<IChatBaseComponent> getCustomNameDataWatcherValue(String customName) {
customName = Strings.truncate(customName, MAX_CUSTOM_NAME_LENGTH);
if (!Strings.isEmpty(customName)) {
return Optional.of(CraftChatMessage.fromString(customName, false)[0]);
} else {
return Optional.empty();
}
}
DataWatcherPacketBuilder<T> setItemStack(ItemStack itemStack) {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack));
return this;
}
DataWatcherPacketBuilder<T> setSlimeSmall() {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.SLIME_SIZE, 1);
return this;
}
T build() {
packetByteBuffer.writeDataWatcherEntriesEnd();
return createPacket(packetByteBuffer);
}
abstract T createPacket(PacketByteBuffer packetByteBuffer);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutEntityDestroy;
class EntityDestroyNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityDestroyNMSPacket(EntityID entityID) {
this.rawPacket = new PacketPlayOutEntityDestroy(entityID.getNumericID());
}
EntityDestroyNMSPacket(EntityID entityID1, EntityID entityID2) {
this.rawPacket = new PacketPlayOutEntityDestroy(entityID1.getNumericID(), entityID2.getNumericID());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutSpawnEntityLiving;
class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityLivingSpawnNMSPacket(EntityID entityID, int entityTypeID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
packetByteBuffer.writeUUID(entityID.getUUID());
packetByteBuffer.writeVarInt(entityTypeID);
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// Head rotation
packetByteBuffer.writeByte(0);
// Velocity
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutEntityMetadata;
class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
public static DataWatcherPacketBuilder<EntityMetadataNMSPacket> builder(EntityID entityID) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
return new Builder(packetByteBuffer);
}
private static class Builder extends DataWatcherPacketBuilder<EntityMetadataNMSPacket> {
private Builder(PacketByteBuffer packetByteBuffer) {
super(packetByteBuffer);
}
@Override
EntityMetadataNMSPacket createPacket(PacketByteBuffer packetByteBuffer) {
return new EntityMetadataNMSPacket(packetByteBuffer);
}
}
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutMount;
class EntityMountNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityMountNMSPacket(EntityID vehicleEntityID, EntityID passengerEntityID) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutSpawnEntity;
class EntitySpawnNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntitySpawnNMSPacket(EntityID entityID, int entityTypeID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
packetByteBuffer.writeUUID(entityID.getUUID());
packetByteBuffer.writeVarInt(entityTypeID);
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// Object data
if (entityTypeID == EntityTypeID.ITEM) {
packetByteBuffer.writeInt(1); // Velocity is present and zero (otherwise by default a random velocity is applied)
} else {
packetByteBuffer.writeInt(0);
}
// Velocity
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketPlayOutEntityTeleport;
class EntityTeleportNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityTeleportNMSPacket(EntityID entityID, PositionCoordinates position, double positionOffsetY) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
// Position
packetByteBuffer.writeDouble(position.getX());
packetByteBuffer.writeDouble(position.getY() + positionOffsetY);
packetByteBuffer.writeDouble(position.getZ());
// Rotation
packetByteBuffer.writeByte(0);
packetByteBuffer.writeByte(0);
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override
Packet<?> getRawPacket() {
return rawPacket;
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
class EntityTypeID {
static final int ARMOR_STAND = 1;
static final int ITEM = 37;
static final int SLIME = 75;
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
import me.filoghost.holographicdisplays.nms.common.NMSErrors;
import me.filoghost.holographicdisplays.nms.common.PacketListener;
import net.minecraft.server.v1_16_R2.PacketPlayInUseEntity;
import org.bukkit.entity.Player;
class InboundPacketHandler extends ChannelInboundHandlerAdapter {
public static final String HANDLER_NAME = "holographic_displays_listener";
private static final ReflectField<Integer> ENTITY_ID_FIELD = ReflectField.lookup(int.class, PacketPlayInUseEntity.class, "a");
private final Player player;
private final PacketListener packetListener;
InboundPacketHandler(Player player, PacketListener packetListener) {
this.player = player;
this.packetListener = packetListener;
}
@Override
public void channelRead(ChannelHandlerContext context, Object packet) throws Exception {
try {
if (packet instanceof PacketPlayInUseEntity) {
int entityID = ENTITY_ID_FIELD.get(packet);
boolean cancel = packetListener.onAsyncEntityInteract(player, entityID);
if (cancel) {
return;
}
}
} catch (Throwable t) {
Log.warning(NMSErrors.EXCEPTION_ON_PACKET_READ, t);
}
super.channelRead(context, packet);
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_16_R2.Packet;
import net.minecraft.server.v1_16_R2.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
}
private PacketByteBuffer() {
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
serializer.d(i);
}
void writeVarIntArray(int i1) {
writeVarInt(1);
writeVarInt(i1);
}
void writeUUID(UUID uuid) {
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.ClickableNMSPacketEntity;
class VersionClickableNMSPacketEntity implements ClickableNMSPacketEntity {
private final EntityID slimeID;
VersionClickableNMSPacketEntity(EntityID slimeID) {
this.slimeID = slimeID;
}
@Override
public EntityID getID() {
return slimeID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(slimeID, EntityTypeID.SLIME, position, SLIME_Y_OFFSET),
EntityMetadataNMSPacket.builder(slimeID)
.setInvisible()
.setSlimeSmall() // Required for a correct client-side collision box
.build()
);
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(slimeID, position, SLIME_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(slimeID);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import org.bukkit.inventory.ItemStack;
class VersionItemNMSPacketEntity implements ItemNMSPacketEntity {
private final EntityID itemID;
private final EntityID vehicleID;
VersionItemNMSPacketEntity(EntityID itemID, EntityID vehicleID) {
this.itemID = itemID;
this.vehicleID = vehicleID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position, ItemStack itemStack) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(vehicleID, EntityTypeID.ARMOR_STAND, position, ITEM_Y_OFFSET),
EntityMetadataNMSPacket.builder(vehicleID)
.setArmorStandMarker()
.build(),
new EntitySpawnNMSPacket(itemID, EntityTypeID.ITEM, position, ITEM_Y_OFFSET),
EntityMetadataNMSPacket.builder(itemID)
.setItemStack(itemStack)
.build(),
new EntityMountNMSPacket(vehicleID, itemID)
);
}
@Override
public PacketGroup newChangePackets(ItemStack itemStack) {
return EntityMetadataNMSPacket.builder(itemID)
.setItemStack(itemStack)
.build();
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(vehicleID, position, ITEM_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(itemID, vehicleID);
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.FallbackEntityIDGenerator;
import me.filoghost.holographicdisplays.nms.common.NMSErrors;
import me.filoghost.holographicdisplays.nms.common.NMSManager;
import me.filoghost.holographicdisplays.nms.common.PacketListener;
import me.filoghost.holographicdisplays.nms.common.entity.ClickableNMSPacketEntity;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
import net.minecraft.server.v1_16_R2.Entity;
import net.minecraft.server.v1_16_R2.NetworkManager;
import net.minecraft.server.v1_16_R2.PlayerConnection;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class VersionNMSManager implements NMSManager {
private static final ReflectField<AtomicInteger> ENTITY_ID_COUNTER_FIELD =
ReflectField.lookup(AtomicInteger.class, Entity.class, "entityCount");
private final Supplier<Integer> entityIDGenerator;
public VersionNMSManager(ErrorCollector errorCollector) {
this.entityIDGenerator = getEntityIDGenerator(errorCollector);
// Force initialization of class to eventually throw exceptions early
DataWatcherKey.ENTITY_STATUS.getIndex();
}
private Supplier<Integer> getEntityIDGenerator(ErrorCollector errorCollector) {
try {
AtomicInteger nmsEntityIDCounter = ENTITY_ID_COUNTER_FIELD.getStatic();
return nmsEntityIDCounter::incrementAndGet;
} catch (ReflectiveOperationException e) {
errorCollector.add(e, NMSErrors.EXCEPTION_GETTING_ENTITY_ID_GENERATOR);
return new FallbackEntityIDGenerator();
}
}
private EntityID newEntityID() {
return new EntityID(entityIDGenerator);
}
@Override
public TextNMSPacketEntity newTextPacketEntity() {
return new VersionTextNMSPacketEntity(newEntityID());
}
@Override
public ItemNMSPacketEntity newItemPacketEntity() {
return new VersionItemNMSPacketEntity(newEntityID(), newEntityID());
}
@Override
public ClickableNMSPacketEntity newClickablePacketEntity() {
return new VersionClickableNMSPacketEntity(newEntityID());
}
@Override
public void injectPacketListener(Player player, PacketListener packetListener) {
modifyPipeline(player, (ChannelPipeline pipeline) -> {
ChannelHandler currentListener = pipeline.get(InboundPacketHandler.HANDLER_NAME);
if (currentListener != null) {
pipeline.remove(InboundPacketHandler.HANDLER_NAME);
}
pipeline.addBefore("packet_handler", InboundPacketHandler.HANDLER_NAME, new InboundPacketHandler(player, packetListener));
});
}
@Override
public void uninjectPacketListener(Player player) {
modifyPipeline(player, (ChannelPipeline pipeline) -> {
ChannelHandler currentListener = pipeline.get(InboundPacketHandler.HANDLER_NAME);
if (currentListener != null) {
pipeline.remove(InboundPacketHandler.HANDLER_NAME);
}
});
}
/*
* Modifying the pipeline in the main thread can cause deadlocks, delays and other concurrency issues,
* which can be avoided by using the event loop. Thanks to ProtocolLib for this insight.
*/
private void modifyPipeline(Player player, Consumer<ChannelPipeline> pipelineModifierTask) {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
channel.eventLoop().execute(() -> {
if (!player.isOnline()) {
return;
}
try {
pipelineModifierTask.accept(channel.pipeline());
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import net.minecraft.server.v1_16_R2.Packet;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
abstract class VersionNMSPacket implements PacketGroup {
@Override
public void sendTo(Player player) {
((CraftPlayer) player).getHandle().playerConnection.sendPacket(getRawPacket());
}
abstract Packet<?> getRawPacket();
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_16_R2;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
class VersionTextNMSPacketEntity implements TextNMSPacketEntity {
private final EntityID armorStandID;
VersionTextNMSPacketEntity(EntityID armorStandID) {
this.armorStandID = armorStandID;
}
@Override
public PacketGroup newSpawnPackets(PositionCoordinates position, String text) {
return PacketGroup.of(
new EntityLivingSpawnNMSPacket(armorStandID, EntityTypeID.ARMOR_STAND, position, ARMOR_STAND_Y_OFFSET),
EntityMetadataNMSPacket.builder(armorStandID)
.setArmorStandMarker()
.setCustomName(text)
.build()
);
}
@Override
public IndividualTextPacketGroup newSpawnPackets(PositionCoordinates position) {
return IndividualTextPacketGroup.of(
new EntityLivingSpawnNMSPacket(armorStandID, EntityTypeID.ARMOR_STAND, position, ARMOR_STAND_Y_OFFSET),
(String text) -> EntityMetadataNMSPacket.builder(armorStandID)
.setArmorStandMarker()
.setCustomName(text)
.build()
);
}
@Override
public PacketGroup newChangePackets(String text) {
return EntityMetadataNMSPacket.builder(armorStandID)
.setCustomName(text)
.build();
}
@Override
public IndividualTextPacketGroup newChangePackets() {
return IndividualTextPacketGroup.of(
(String text) -> EntityMetadataNMSPacket.builder(armorStandID)
.setCustomName(text)
.build()
);
}
@Override
public PacketGroup newTeleportPackets(PositionCoordinates position) {
return new EntityTeleportNMSPacket(armorStandID, position, ARMOR_STAND_Y_OFFSET);
}
@Override
public PacketGroup newDestroyPackets() {
return new EntityDestroyNMSPacket(armorStandID);
}
}