1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-27 18:59:17 +00:00

Implement dirty entities to send updates once a tick

This commit is contained in:
onebeastchris
2025-11-30 02:25:43 +01:00
parent 460305a515
commit b26b9d17fb
4 changed files with 25 additions and 14 deletions

View File

@@ -26,24 +26,19 @@
package org.geysermc.geyser.entity;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import lombok.AllArgsConstructor;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataMap;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
import org.geysermc.geyser.entity.type.Entity;
import java.util.Map;
/**
* A wrapper for temporarily storing entity metadata that will be sent to Bedrock.
*/
@AllArgsConstructor
public final class GeyserDirtyMetadata {
private final Entity entity;
private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
public <T> void put(EntityDataType<T> entityData, T value) {
metadata.put(entityData, value);
entity.getMetadata().put(entityData, value);
}
/**

View File

@@ -145,7 +145,7 @@ public class Entity implements GeyserEntity {
/**
* A container to store temporary metadata before it's sent to Bedrock.
*/
protected final GeyserDirtyMetadata dirtyMetadata = new GeyserDirtyMetadata(this);
protected final GeyserDirtyMetadata dirtyMetadata = new GeyserDirtyMetadata();
/**
* A container storing all current metadata for an entity.
*/
@@ -413,7 +413,7 @@ public class Entity implements GeyserEntity {
return;
}
if (dirtyMetadata.hasEntries() || flagsDirty) {
if (dirtyMetadata.hasEntries() || flagsDirty || (propertyManager != null && propertyManager.hasProperties())) {
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(geyserId);
if (flagsDirty) {
@@ -837,20 +837,20 @@ public class Entity implements GeyserEntity {
});
if (propertyManager.hasProperties()) {
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId());
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
if (immediate) {
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId());
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
session.sendUpstreamPacketImmediately(packet);
} else {
session.sendUpstreamPacket(packet);
session.getEntityCache().markDirty(this);
}
}
}
public void offset(float offset) {
// TODO queue!!
// TODO queue?
if (isValid()) {
this.moveRelative(0, offset, 0, 0, 0, isOnGround());
}
@@ -875,6 +875,7 @@ public class Entity implements GeyserEntity {
public <T> void update(@NonNull GeyserEntityDataType<T> dataType, @Nullable T value) {
if (dataType instanceof GeyserEntityDataImpl<T> geyserEntityDataImpl) {
geyserEntityDataImpl.update(this, value);
session.getEntityCache().markDirty(this);
} else {
throw new IllegalArgumentException("Invalid data type: " + dataType.getClass().getSimpleName());
}

View File

@@ -125,8 +125,8 @@ import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.GeyserConfig;
import org.geysermc.geyser.entity.VanillaEntities;
import org.geysermc.geyser.entity.GeyserEntityData;
import org.geysermc.geyser.entity.VanillaEntities;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.Entity;
@@ -235,6 +235,7 @@ import java.util.BitSet;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -1262,6 +1263,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
clientVehicle.getVehicleComponent().tickVehicle();
}
for (Iterator<Entity> it = entityCache.getDirtyEntities().iterator(); it.hasNext(); ) {
it.next().updateBedrockMetadata();
it.remove();
}
for (Tickable entity : entityCache.getTickableEntities()) {
entity.drawTick();
if (gameShouldUpdate) {

View File

@@ -33,6 +33,7 @@ import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.Tickable;
@@ -42,6 +43,7 @@ import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@@ -63,6 +65,8 @@ public class EntityCache {
private final Object2LongMap<UUID> entityUuidTranslations = new Object2LongOpenHashMap<>();
private final Map<UUID, PlayerEntity> playerEntities = new Object2ObjectOpenHashMap<>();
private final Map<UUID, BossBar> bossBars = new Object2ObjectOpenHashMap<>();
@Getter
private final Set<Entity> dirtyEntities = new ObjectOpenHashSet<>();
@Getter
private final AtomicLong nextEntityId = new AtomicLong(2L);
@@ -123,6 +127,11 @@ public class EntityCache {
if (entity instanceof Tickable) {
tickableEntities.remove(entity);
}
dirtyEntities.remove(entity);
}
public void markDirty(Entity entity) {
dirtyEntities.add(entity);
}
public void removeAllEntities() {