From f8634171f74e9cd735ad9e577b0f8b900e4d3d68 Mon Sep 17 00:00:00 2001 From: Konstantin Shandurenko Date: Wed, 24 Feb 2021 13:28:23 +0300 Subject: [PATCH] Metadata#setNotifyAboutChanges --- .../minestom/server/entity/LivingEntity.java | 2 + .../net/minestom/server/entity/Metadata.java | 51 ++++++++++++++++--- .../server/entity/metadata/EntityMeta.java | 17 +++++++ 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/minestom/server/entity/LivingEntity.java b/src/main/java/net/minestom/server/entity/LivingEntity.java index ba345ce3f..f69a2995b 100644 --- a/src/main/java/net/minestom/server/entity/LivingEntity.java +++ b/src/main/java/net/minestom/server/entity/LivingEntity.java @@ -460,9 +460,11 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler { public void refreshActiveHand(boolean isHandActive, boolean offHand, boolean riptideSpinAttack) { LivingEntityMeta meta = getLivingEntityMeta(); if (meta != null) { + meta.setNotifyAboutChanges(false); meta.setHandActive(isHandActive); meta.setActiveHand(offHand ? Player.Hand.OFF : Player.Hand.MAIN); meta.setInRiptideSpinAttack(riptideSpinAttack); + meta.setNotifyAboutChanges(true); } } diff --git a/src/main/java/net/minestom/server/entity/Metadata.java b/src/main/java/net/minestom/server/entity/Metadata.java index e6f97cec9..8d90adc3e 100644 --- a/src/main/java/net/minestom/server/entity/Metadata.java +++ b/src/main/java/net/minestom/server/entity/Metadata.java @@ -12,10 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jglrxavpok.hephaistos.nbt.NBT; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; @@ -153,14 +150,18 @@ public class Metadata { private final Entity entity; - private Map> metadataMap = new ConcurrentHashMap<>(); + private final Map> metadataMap = new ConcurrentHashMap<>(); + + private volatile boolean notifyAboutChanges = true; + private final Map> notNotifiedChanges = new HashMap<>(); public Metadata(@Nullable Entity entity) { this.entity = entity; } + @SuppressWarnings("unchecked") public T getIndex(byte index, @Nullable T defaultValue) { - Entry value = metadataMap.get(index); + Entry value = this.metadataMap.get(index); return value != null ? (T) value.getMetaValue().value : defaultValue; } @@ -169,15 +170,49 @@ public class Metadata { this.metadataMap.put(index, entry); // Send metadata packet to update viewers and self - if (entity != null && entity.isActive()) { + if (this.entity != null && this.entity.isActive()) { + if (!this.notifyAboutChanges) { + synchronized (this.notNotifiedChanges) { + this.notNotifiedChanges.put(index, entry); + } + return; + } EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket(); - metaDataPacket.entityId = entity.getEntityId(); + metaDataPacket.entityId = this.entity.getEntityId(); metaDataPacket.entries = Collections.singleton(entry); this.entity.sendPacketToViewersAndSelf(metaDataPacket); } } + public void setNotifyAboutChanges(boolean notifyAboutChanges) { + if (this.notifyAboutChanges == notifyAboutChanges) { + return; + } + + Collection> entries = null; + synchronized (this.notNotifiedChanges) { + this.notifyAboutChanges = notifyAboutChanges; + if (notifyAboutChanges) { + entries = this.notNotifiedChanges.values(); + if (entries.isEmpty()) { + return; + } + this.notNotifiedChanges.clear(); + } + } + + if (entries == null || this.entity == null || !this.entity.isActive()) { + return; + } + + EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket(); + metaDataPacket.entityId = this.entity.getEntityId(); + metaDataPacket.entries = entries; + + this.entity.sendPacketToViewersAndSelf(metaDataPacket); + } + @NotNull public Collection> getEntries() { return metadataMap.values(); diff --git a/src/main/java/net/minestom/server/entity/metadata/EntityMeta.java b/src/main/java/net/minestom/server/entity/metadata/EntityMeta.java index 5d29beb9e..9d535e594 100644 --- a/src/main/java/net/minestom/server/entity/metadata/EntityMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/EntityMeta.java @@ -25,6 +25,23 @@ public class EntityMeta { this.metadata = metadata; } + /** + * Sets whether any changes to this meta must result in a metadata packet being sent to entity viewers. + * By default it's set to true. + *

+ * It's usable if you want to change multiple values of this meta at the same time and want just a + * single packet being sent: if so, disable notification before your first change and enable it + * right after the last one: once notification is set to false, we collect all the updates + * that are being performed, and when it's returned to true we send them all together. + * An example usage could be found at + * {@link net.minestom.server.entity.LivingEntity#refreshActiveHand(boolean, boolean, boolean)}. + * + * @param notifyAboutChanges if to notify entity viewers about this meta changes. + */ + public void setNotifyAboutChanges(boolean notifyAboutChanges) { + this.metadata.setNotifyAboutChanges(notifyAboutChanges); + } + public boolean isOnFire() { return getMaskBit(MASK_INDEX, ON_FIRE_BIT); }