Improve NMS implementation

This commit is contained in:
filoghost 2021-07-25 19:02:48 +02:00
parent 98f27b73b4
commit 6be5f00f53
6 changed files with 107 additions and 97 deletions

View File

@ -1,26 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.nms.v1_17_R1;
class DataWatcherEntry<T> {
private final DataWatcherKey<T> key;
private final T value;
DataWatcherEntry(DataWatcherKey<T> key, T value) {
this.key = key;
this.value = value;
}
DataWatcherKey<T> getKey() {
return key;
}
T getValue() {
return value;
}
}

View File

@ -26,12 +26,12 @@ class DataWatcherKey<T> {
static DataWatcherKey<ItemStack> ITEM_STACK = new DataWatcherKey<>(8, ITEM_STACK_SERIALIZER);
static DataWatcherKey<Byte> ARMOR_STAND_STATUS = new DataWatcherKey<>(15, BYTE_SERIALIZER);
private final int keyIndex;
private final int index;
private final DataWatcherSerializer<T> serializer;
private final int serializerTypeID;
private DataWatcherKey(int keyIndex, DataWatcherSerializer<T> serializer) {
this.keyIndex = keyIndex;
private DataWatcherKey(int index, DataWatcherSerializer<T> serializer) {
this.index = index;
this.serializer = serializer;
this.serializerTypeID = DataWatcherRegistry.b(serializer);
if (serializerTypeID < 0) {
@ -39,8 +39,8 @@ class DataWatcherKey<T> {
}
}
int getKeyIndex() {
return keyIndex;
int getIndex() {
return index;
}
DataWatcherSerializer<T> getSerializer() {

View File

@ -5,20 +5,22 @@
*/
package me.filoghost.holographicdisplays.nms.v1_17_R1;
import me.filoghost.fcommons.Strings;
import me.filoghost.holographicdisplays.common.nms.EntityID;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.util.CraftChatMessage;
import org.bukkit.inventory.ItemStack;
import java.util.Optional;
class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
EntityMetadataNMSPacket(EntityID entityID, DataWatcherEntry<?>... dataWatcherEntries) {
PacketByteBuffer packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
packetByteBuffer.writeDataWatcherEntries(dataWatcherEntries);
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = new PacketPlayOutEntityMetadata(packetByteBuffer);
}
@ -27,4 +29,57 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
return rawPacket;
}
public static Builder builder(EntityID entityID) {
return new Builder(entityID);
}
static class Builder {
private final PacketByteBuffer packetByteBuffer;
private Builder(EntityID entityID) {
this.packetByteBuffer = PacketByteBuffer.get();
packetByteBuffer.writeVarInt(entityID.getNumericID());
}
Builder setInvisible() {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ENTITY_STATUS, (byte) 0x20); // Invisible
return this;
}
Builder setMarkerArmorStand() {
setInvisible();
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ARMOR_STAND_STATUS, (byte) (0x01 | 0x08 | 0x10)); // Small, no base plate, marker
return this;
}
Builder 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, 300);
if (!Strings.isEmpty(customName)) {
return Optional.of(CraftChatMessage.fromString(customName, false, true)[0]);
} else {
return Optional.empty();
}
}
Builder setItemStack(ItemStack itemStack) {
packetByteBuffer.writeDataWatcherEntry(DataWatcherKey.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack));
return this;
}
EntityMetadataNMSPacket build() {
packetByteBuffer.writeDataWatcherEntriesEnd();
return new EntityMetadataNMSPacket(packetByteBuffer);
}
}
}

View File

@ -37,17 +37,14 @@ class PacketByteBuffer extends PacketDataSerializer {
super.a(array);
}
void writeDataWatcherEntries(DataWatcherEntry<?>... dataWatcherEntries) {
for (DataWatcherEntry<?> dataWatcherItem : dataWatcherEntries) {
writeDataWatcherEntry(dataWatcherItem);
}
writeByte(255); // End of data watcher entries
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
}
private <T> void writeDataWatcherEntry(DataWatcherEntry<T> dataWatcherItem) {
writeByte(dataWatcherItem.getKey().getKeyIndex());
writeVarInt(dataWatcherItem.getKey().getSerializerTypeID());
dataWatcherItem.getKey().getSerializer().a(this, dataWatcherItem.getValue());
void writeDataWatcherEntriesEnd() {
writeByte(255);
}
}

View File

@ -26,7 +26,7 @@ public class VersionNMSManager implements NMSManager {
this.entityIDGenerator = getEntityIDGenerator(errorCollector);
// Force initialization of class to eventually throw exceptions early
DataWatcherKey.ENTITY_STATUS.getKeyIndex();
DataWatcherKey.ENTITY_STATUS.getIndex();
}
private Supplier<Integer> getEntityIDGenerator(ErrorCollector errorCollector) {

View File

@ -5,106 +5,90 @@
*/
package me.filoghost.holographicdisplays.nms.v1_17_R1;
import me.filoghost.fcommons.Strings;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.common.nms.AbstractNMSPacketList;
import me.filoghost.holographicdisplays.common.nms.EntityID;
import me.filoghost.holographicdisplays.common.nms.IndividualCustomName;
import me.filoghost.holographicdisplays.common.nms.IndividualNMSPacket;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntList;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.util.CraftChatMessage;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Field;
import java.util.Optional;
class VersionNMSPacketList extends AbstractNMSPacketList {
private static final DataWatcherEntry<Byte> ENTITY_STATUS_INVISIBLE = new DataWatcherEntry<>(DataWatcherKey.ENTITY_STATUS, (byte) 0x20);
private static final DataWatcherEntry<Boolean> CUSTOM_NAME_VISIBLE = new DataWatcherEntry<>(DataWatcherKey.CUSTOM_NAME_VISIBILITY, true);
private static final DataWatcherEntry<Boolean> CUSTOM_NAME_INVISIBLE = new DataWatcherEntry<>(DataWatcherKey.CUSTOM_NAME_VISIBILITY, false);
private static final DataWatcherEntry<Byte> ARMOR_STAND_STATUS_MARKER = new DataWatcherEntry<>(DataWatcherKey.ARMOR_STAND_STATUS, (byte) (0x01 | 0x08 | 0x10)); // Small, no base plate, marker
private static final boolean USE_ENTITY_LIST_DESTROY_PACKET = useEntityListDestroyPacket();
@Override
public void addArmorStandSpawnPackets(EntityID entityID, double locationX, double locationY, double locationZ) {
add(new EntityLivingSpawnNMSPacket(entityID, EntityTypeID.ARMOR_STAND, locationX, locationY, locationZ));
add(new EntityMetadataNMSPacket(entityID,
ENTITY_STATUS_INVISIBLE,
ARMOR_STAND_STATUS_MARKER
));
add(EntityMetadataNMSPacket.builder(entityID)
.setMarkerArmorStand()
.build()
);
}
@Override
public void addArmorStandSpawnPackets(EntityID entityID, double locationX, double locationY, double locationZ, String customName) {
add(new EntityLivingSpawnNMSPacket(entityID, EntityTypeID.ARMOR_STAND, locationX, locationY, locationZ));
add(createFullArmorStandMetadataPacket(entityID, customName));
add(EntityMetadataNMSPacket.builder(entityID)
.setMarkerArmorStand()
.setCustomName(customName)
.build()
);
}
@Override
public void addArmorStandSpawnPackets(EntityID entityID, double locationX, double locationY, double locationZ, IndividualCustomName individualCustomName) {
add(new EntityLivingSpawnNMSPacket(entityID, EntityTypeID.ARMOR_STAND, locationX, locationY, locationZ));
add(new IndividualNMSPacket(player -> createFullArmorStandMetadataPacket(entityID, individualCustomName.get(player))));
}
private EntityMetadataNMSPacket createFullArmorStandMetadataPacket(EntityID entityID, String customName) {
return new EntityMetadataNMSPacket(entityID,
ENTITY_STATUS_INVISIBLE,
new DataWatcherEntry<>(DataWatcherKey.CUSTOM_NAME, getCustomNameDataWatcherValue(customName)),
Strings.isEmpty(customName) ? CUSTOM_NAME_INVISIBLE : CUSTOM_NAME_VISIBLE,
ARMOR_STAND_STATUS_MARKER
);
add(new IndividualNMSPacket(player -> EntityMetadataNMSPacket.builder(entityID)
.setMarkerArmorStand()
.setCustomName(individualCustomName.get(player))
.build()
));
}
@Override
public void addArmorStandNameChangePackets(EntityID entityID, String customName) {
add(createPartialArmorStandMetadataPacket(entityID, customName));
add(EntityMetadataNMSPacket.builder(entityID)
.setCustomName(customName)
.build()
);
}
@Override
public void addArmorStandNameChangePackets(EntityID entityID, IndividualCustomName individualCustomName) {
add(new IndividualNMSPacket(player -> createPartialArmorStandMetadataPacket(entityID, individualCustomName.get(player))));
}
private EntityMetadataNMSPacket createPartialArmorStandMetadataPacket(EntityID entityID, String customName) {
return new EntityMetadataNMSPacket(entityID,
new DataWatcherEntry<>(DataWatcherKey.CUSTOM_NAME, getCustomNameDataWatcherValue(customName)),
Strings.isEmpty(customName) ? CUSTOM_NAME_INVISIBLE : CUSTOM_NAME_VISIBLE
);
}
private Optional<IChatBaseComponent> getCustomNameDataWatcherValue(String customName) {
customName = Strings.truncate(customName, 300);
if (!Strings.isEmpty(customName)) {
return Optional.of(CraftChatMessage.fromString(customName, false, true)[0]);
} else {
return Optional.empty();
}
add(new IndividualNMSPacket(player -> EntityMetadataNMSPacket.builder(entityID)
.setCustomName(individualCustomName.get(player))
.build()
));
}
@Override
public void addItemSpawnPackets(EntityID entityID, double locationX, double locationY, double locationZ, ItemStack itemStack) {
add(new EntitySpawnNMSPacket(entityID, EntityTypeID.ITEM, locationX, locationY, locationZ));
add(new EntityMetadataNMSPacket(entityID,
new DataWatcherEntry<>(DataWatcherKey.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack))
));
add(EntityMetadataNMSPacket.builder(entityID)
.setItemStack(itemStack)
.build()
);
}
@Override
public void addItemStackChangePackets(EntityID entityID, ItemStack itemStack) {
add(new EntityMetadataNMSPacket(entityID,
new DataWatcherEntry<>(DataWatcherKey.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack))
));
add(EntityMetadataNMSPacket.builder(entityID)
.setItemStack(itemStack)
.build()
);
}
@Override
public void addSlimeSpawnPackets(EntityID entityID, double locationX, double locationY, double locationZ) {
add(new EntityLivingSpawnNMSPacket(entityID, EntityTypeID.SLIME, locationX, locationY, locationZ));
add(new EntityMetadataNMSPacket(entityID, ENTITY_STATUS_INVISIBLE));
add(EntityMetadataNMSPacket.builder(entityID)
.setInvisible()
.build()
);
}
@Override