Metadata#setNotifyAboutChanges

This commit is contained in:
Konstantin Shandurenko 2021-02-24 13:28:23 +03:00
parent 3f941d51bb
commit f8634171f7
3 changed files with 62 additions and 8 deletions

View File

@ -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);
}
}

View File

@ -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<Byte, Entry<?>> metadataMap = new ConcurrentHashMap<>();
private final Map<Byte, Entry<?>> metadataMap = new ConcurrentHashMap<>();
private volatile boolean notifyAboutChanges = true;
private final Map<Byte, Entry<?>> notNotifiedChanges = new HashMap<>();
public Metadata(@Nullable Entity entity) {
this.entity = entity;
}
@SuppressWarnings("unchecked")
public <T> 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<Entry<?>> 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<Entry<?>> getEntries() {
return metadataMap.values();

View File

@ -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.
* <p>
* 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);
}