From a69b9e1e15f38600974d1906657088818d999e7a Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Fri, 6 Sep 2024 00:05:48 +0200 Subject: [PATCH] Track entity data --- .../api/model/entity/CustomEntity.java | 22 +++++----- .../viabedrock/api/model/entity/Entity.java | 40 ++++++++++++++++++- .../api/model/entity/LivingEntity.java | 8 +++- .../protocol/packet/EntityPackets.java | 27 ++++++++++++- .../protocol/packet/OtherPlayerPackets.java | 4 +- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/raphimc/viabedrock/api/model/entity/CustomEntity.java b/src/main/java/net/raphimc/viabedrock/api/model/entity/CustomEntity.java index 7a0d3d99..bad7a31b 100644 --- a/src/main/java/net/raphimc/viabedrock/api/model/entity/CustomEntity.java +++ b/src/main/java/net/raphimc/viabedrock/api/model/entity/CustomEntity.java @@ -58,7 +58,6 @@ public void setPosition(final Position3f position) { super.setPosition(position); if (!this.spawned) { - this.spawned = true; this.spawn(); } else { this.partEntities.forEach(ItemDisplayEntity::updatePositionAndRotation); @@ -77,17 +76,11 @@ public void setRotation(final Position3f rotation) { @Override public void remove() { super.remove(); - - final int[] entityIds = new int[partEntities.size()]; - for (int i = 0; i < partEntities.size(); i++) { - entityIds[i] = partEntities.get(i).javaId; - } - final PacketWrapper removeEntities = PacketWrapper.create(ClientboundPackets1_21.REMOVE_ENTITIES, this.user); - removeEntities.write(Types.VAR_INT_ARRAY_PRIMITIVE, entityIds); // entity ids - removeEntities.send(BedrockProtocol.class); + this.despawn(); } private void spawn() { + this.spawned = true; final EntityTracker entityTracker = user.get(EntityTracker.class); final ResourcePacksStorage resourcePacksStorage = user.get(ResourcePacksStorage.class); final int parts = (int) resourcePacksStorage.getConverterData().get("ce_" + this.entityDefinition.identifier() + "_default"); @@ -128,6 +121,17 @@ private void spawn() { } } + private void despawn() { + this.spawned = false; + final int[] entityIds = new int[partEntities.size()]; + for (int i = 0; i < partEntities.size(); i++) { + entityIds[i] = partEntities.get(i).javaId(); + } + final PacketWrapper removeEntities = PacketWrapper.create(ClientboundPackets1_21.REMOVE_ENTITIES, this.user); + removeEntities.write(Types.VAR_INT_ARRAY_PRIMITIVE, entityIds); // entity ids + removeEntities.send(BedrockProtocol.class); + } + private class ItemDisplayEntity extends Entity { public ItemDisplayEntity(final int javaId) { diff --git a/src/main/java/net/raphimc/viabedrock/api/model/entity/Entity.java b/src/main/java/net/raphimc/viabedrock/api/model/entity/Entity.java index 5d33b8a4..79b0ce97 100644 --- a/src/main/java/net/raphimc/viabedrock/api/model/entity/Entity.java +++ b/src/main/java/net/raphimc/viabedrock/api/model/entity/Entity.java @@ -19,14 +19,19 @@ import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5; +import com.viaversion.viaversion.api.minecraft.entitydata.EntityData; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.type.Types; +import com.viaversion.viaversion.api.type.types.version.Types1_21; import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21; +import net.raphimc.viabedrock.ViaBedrock; import net.raphimc.viabedrock.protocol.BedrockProtocol; +import net.raphimc.viabedrock.protocol.data.enums.bedrock.ActorDataIDs; import net.raphimc.viabedrock.protocol.data.enums.java.BossEventOperationType; import net.raphimc.viabedrock.protocol.model.Position3f; -import java.util.UUID; +import java.util.*; +import java.util.logging.Level; public class Entity { @@ -46,6 +51,7 @@ public class Entity { */ protected Position3f rotation = Position3f.ZERO; protected boolean onGround; + protected final Map entityData = new EnumMap<>(ActorDataIDs.class); protected String name; protected int age; protected boolean hasBossBar; @@ -73,6 +79,30 @@ public void remove() { } } + public final void updateEntityData(final EntityData[] entityData) { + final List javaEntityData = new ArrayList<>(); + this.updateEntityData(entityData, javaEntityData); + final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_21.SET_ENTITY_DATA, this.user); + setEntityData.write(Types.VAR_INT, this.javaId); // entity id + setEntityData.write(Types1_21.ENTITY_DATA_LIST, javaEntityData); // entity data + setEntityData.send(BedrockProtocol.class); + } + + public final void updateEntityData(final EntityData[] entityData, final List javaEntityData) { + for (EntityData data : entityData) { + final ActorDataIDs id = ActorDataIDs.getByValue(data.id()); + if (id == null) { + ViaBedrock.getPlatform().getLogger().log(Level.WARNING, "Unknown ActorDataIDs: " + data.id()); + continue; + } + this.entityData.put(id, data); + if (!this.translateEntityData(id, data, javaEntityData)) { + // TODO: Log warning when entity data translation is fully implemented + // ViaBedrock.getPlatform().getLogger().log(Level.WARNING, "Received unknown entity data: " + id + " for entity type: " + this.type); + } + } + } + public float eyeOffset() { return 0F; } @@ -121,6 +151,10 @@ public void setOnGround(final boolean onGround) { this.onGround = onGround; } + public Map entityData() { + return this.entityData; + } + public String name() { return this.name; } @@ -149,4 +183,8 @@ public final int getJavaEntityDataIndex(final String fieldName) { return index; } + protected boolean translateEntityData(final ActorDataIDs id, final EntityData entityData, final List javaEntityData) { + return false; + } + } diff --git a/src/main/java/net/raphimc/viabedrock/api/model/entity/LivingEntity.java b/src/main/java/net/raphimc/viabedrock/api/model/entity/LivingEntity.java index cbdd1d93..63a501ac 100644 --- a/src/main/java/net/raphimc/viabedrock/api/model/entity/LivingEntity.java +++ b/src/main/java/net/raphimc/viabedrock/api/model/entity/LivingEntity.java @@ -36,8 +36,8 @@ public class LivingEntity extends Entity { - protected Map attributes = new HashMap<>(); - protected Map effects = new HashMap<>(); + protected final Map attributes = new HashMap<>(); + protected final Map effects = new HashMap<>(); public LivingEntity(final UserConnection user, final long uniqueId, final long runtimeId, final int javaId, final UUID javaUuid, final EntityTypes1_20_5 type) { super(user, uniqueId, runtimeId, javaId, javaUuid, type); @@ -140,6 +140,10 @@ public Map attributes() { return this.attributes; } + public Map effects() { + return this.effects; + } + protected boolean translateAttribute(final EntityAttribute attribute, final PacketWrapper javaAttributes, final AtomicInteger attributeCount, final List javaEntityData) { return switch (attribute.name()) { case "minecraft:attack_damage", "minecraft:knockback_resistance", "minecraft:movement" -> { diff --git a/src/main/java/net/raphimc/viabedrock/protocol/packet/EntityPackets.java b/src/main/java/net/raphimc/viabedrock/protocol/packet/EntityPackets.java index 0488a6ca..10f22959 100644 --- a/src/main/java/net/raphimc/viabedrock/protocol/packet/EntityPackets.java +++ b/src/main/java/net/raphimc/viabedrock/protocol/packet/EntityPackets.java @@ -51,6 +51,8 @@ import net.raphimc.viabedrock.protocol.storage.ResourcePacksStorage; import net.raphimc.viabedrock.protocol.types.BedrockTypes; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; public class EntityPackets { @@ -122,6 +124,7 @@ public static void register(final BedrockProtocol protocol) { if (entity instanceof LivingEntity livingEntity) { livingEntity.updateAttributes(attributes); } + entity.updateEntityData(entityData); }); protocol.registerClientbound(ClientboundBedrockPackets.ADD_ITEM_ENTITY, ClientboundPackets1_21.ADD_ENTITY, wrapper -> { final EntityTracker entityTracker = wrapper.user().get(EntityTracker.class); @@ -154,9 +157,12 @@ public static void register(final BedrockProtocol protocol) { wrapper.send(BedrockProtocol.class); wrapper.cancel(); + final List javaEntityData = new ArrayList<>(); + entity.updateEntityData(entityData, javaEntityData); + javaEntityData.add(new EntityData(entity.getJavaEntityDataIndex("ITEM"), Types1_21.ENTITY_DATA_TYPES.itemType, itemRewriter.javaItem(item))); final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_21.SET_ENTITY_DATA, wrapper.user()); setEntityData.write(Types.VAR_INT, entity.javaId()); // entity id - setEntityData.write(Types1_21.ENTITY_DATA_LIST, Lists.newArrayList(new EntityData(entity.getJavaEntityDataIndex("ITEM"), Types1_21.ENTITY_DATA_TYPES.itemType, itemRewriter.javaItem(item)))); // entity data + setEntityData.write(Types1_21.ENTITY_DATA_LIST, javaEntityData); // entity data setEntityData.send(BedrockProtocol.class); }); protocol.registerClientbound(ClientboundBedrockPackets.MOVE_ENTITY_ABSOLUTE, ClientboundPackets1_21.TELEPORT_ENTITY, wrapper -> { @@ -454,6 +460,25 @@ public static void register(final BedrockProtocol protocol) { wrapper.cancel(); } }); + protocol.registerClientbound(ClientboundBedrockPackets.SET_ENTITY_DATA, ClientboundPackets1_21.SET_ENTITY_DATA, wrapper -> { + final EntityTracker entityTracker = wrapper.user().get(EntityTracker.class); + + final long runtimeEntityId = wrapper.read(BedrockTypes.UNSIGNED_VAR_LONG); // runtime entity id + final EntityData[] entityData = wrapper.read(BedrockTypes.ENTITY_DATA_ARRAY); // entity data + final EntityProperties entityProperties = wrapper.read(BedrockTypes.ENTITY_PROPERTIES); // entity properties + wrapper.read(BedrockTypes.UNSIGNED_VAR_LONG); // tick + + final Entity entity = entityTracker.getEntityByRid(runtimeEntityId); + if (entity == null) { + wrapper.cancel(); + return; + } + + final List javaEntityData = new ArrayList<>(); + entity.updateEntityData(entityData, javaEntityData); + wrapper.write(Types.VAR_INT, entity.javaId()); // entity id + wrapper.write(Types1_21.ENTITY_DATA_LIST, javaEntityData); // entity data + }); protocol.registerClientbound(ClientboundBedrockPackets.MOB_EFFECT, ClientboundPackets1_21.UPDATE_MOB_EFFECT, wrapper -> { final long runtimeEntityId = wrapper.read(BedrockTypes.UNSIGNED_VAR_LONG); // runtime entity id final MobEffectPacket_Event event = MobEffectPacket_Event.getByValue(wrapper.read(Types.BYTE), MobEffectPacket_Event.Invalid); // event id diff --git a/src/main/java/net/raphimc/viabedrock/protocol/packet/OtherPlayerPackets.java b/src/main/java/net/raphimc/viabedrock/protocol/packet/OtherPlayerPackets.java index 84834719..201d1047 100644 --- a/src/main/java/net/raphimc/viabedrock/protocol/packet/OtherPlayerPackets.java +++ b/src/main/java/net/raphimc/viabedrock/protocol/packet/OtherPlayerPackets.java @@ -71,8 +71,6 @@ public static void register(final BedrockProtocol protocol) { final PlayerAbilities abilities = wrapper.read(BedrockTypes.PLAYER_ABILITIES); // abilities final EntityLink[] entityLinks = wrapper.read(BedrockTypes.ENTITY_LINK_ARRAY); // entity links - // TODO: Handle remaining fields - final PlayerEntity entity = entityTracker.addEntity(new PlayerEntity(wrapper.user(), runtimeEntityId, entityTracker.getNextJavaEntityId(), uuid, abilities)); entity.setPosition(position); entity.setRotation(rotation); @@ -117,6 +115,8 @@ public static void register(final BedrockProtocol protocol) { setEquipment.write(Types.BYTE, (byte) EquipmentSlot.MAINHAND.ordinal()); // slot setEquipment.write(Types1_21.ITEM, itemRewriter.javaItem(item)); // item setEquipment.send(BedrockProtocol.class); + + entity.updateEntityData(entityData); }); protocol.registerClientbound(ClientboundBedrockPackets.MOVE_PLAYER, ClientboundPackets1_21.TELEPORT_ENTITY, wrapper -> { final EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);