mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2025-01-01 21:57:36 +01:00
Improve NMS implementation
This commit is contained in:
parent
98f27b73b4
commit
6be5f00f53
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user