diff --git a/api/src/main/java/org/geysermc/geyser/api/entity/type/GeyserEntity.java b/api/src/main/java/org/geysermc/geyser/api/entity/type/GeyserEntity.java index 1f8698518..6dd3c4fe2 100644 --- a/api/src/main/java/org/geysermc/geyser/api/entity/type/GeyserEntity.java +++ b/api/src/main/java/org/geysermc/geyser/api/entity/type/GeyserEntity.java @@ -62,7 +62,23 @@ public interface GeyserEntity { /** * Updates multiple properties with just one update packet. * @see BatchPropertyUpdater + * + * @param consumer a batch updater * @since 2.9.0 */ - void updatePropertiesBatched(Consumer consumer); + default void updatePropertiesBatched(Consumer consumer) { + this.updatePropertiesBatched(consumer, false); + } + + /** + * Updates multiple properties with just one update packet, which can be sent immediately to the client. + * Usually, sending updates immediately is not required except for specific situations where packet batching + * would result in update order issues. + * @see BatchPropertyUpdater + * + * @param consumer a batch updater + * @param immediate whether this update should be sent immediately + * @since 2.9.1 + */ + void updatePropertiesBatched(Consumer consumer, boolean immediate); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index 096bd8a70..f82b09fe2 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -778,40 +778,44 @@ public class Entity implements GeyserEntity { } @Override - public void updatePropertiesBatched(Consumer consumer) { - if (this.propertyManager != null) { - Objects.requireNonNull(consumer); - GeyserEntityProperties propertyDefinitions = definition.registeredProperties(); - consumer.accept(new BatchPropertyUpdater() { - @Override - public void update(@NonNull GeyserEntityProperty property, @Nullable T value) { - Objects.requireNonNull(property, "property must not be null!"); - if (!(property instanceof PropertyType propertyType)) { - throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName()); - } - int index = propertyDefinitions.getPropertyIndex(property.identifier().toString()); - if (index < 0) { - throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered."); - } + public void updatePropertiesBatched(Consumer consumer, boolean immediate) { + if (this.propertyManager == null) { + throw new IllegalArgumentException("Given entity has no registered properties!"); + } - var expectedProperty = propertyDefinitions.getProperties().get(index); - if (!expectedProperty.equals(propertyType)) { - throw new IllegalArgumentException("The supplied property was not registered with this entity type!"); - } - - propertyType.apply(propertyManager, value); + Objects.requireNonNull(consumer); + GeyserEntityProperties propertyDefinitions = definition.registeredProperties(); + consumer.accept(new BatchPropertyUpdater() { + @Override + public void update(@NonNull GeyserEntityProperty property, @Nullable T value) { + Objects.requireNonNull(property, "property must not be null!"); + if (!(property instanceof PropertyType propertyType)) { + throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName()); + } + int index = propertyDefinitions.getPropertyIndex(property.identifier().toString()); + if (index < 0) { + throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered."); } - }); - if (propertyManager.hasProperties()) { - SetEntityDataPacket packet = new SetEntityDataPacket(); - packet.setRuntimeEntityId(getGeyserId()); - propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties()); - propertyManager.applyIntProperties(packet.getProperties().getIntProperties()); + var expectedProperty = propertyDefinitions.getProperties().get(index); + if (!expectedProperty.equals(propertyType)) { + throw new IllegalArgumentException("The supplied property was not registered with this entity type!"); + } + + propertyType.apply(propertyManager, value); + } + }); + + if (propertyManager.hasProperties()) { + SetEntityDataPacket packet = new SetEntityDataPacket(); + packet.setRuntimeEntityId(getGeyserId()); + propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties()); + propertyManager.applyIntProperties(packet.getProperties().getIntProperties()); + if (immediate) { + session.sendUpstreamPacketImmediately(packet); + } else { session.sendUpstreamPacket(packet); } - } else { - throw new IllegalArgumentException("Given entity has no registered properties!"); } } }