Improve additional metadata handling

Fixes #527
This commit is contained in:
Nassim Jahnke 2023-02-10 12:10:49 +01:00
parent 27dd148c69
commit 8715c243c9
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
13 changed files with 79 additions and 37 deletions

View File

@ -57,10 +57,30 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}); });
} }
@Override
public void registerTrackerWithData1_19(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Entity id
map(Type.UUID); // Entity UUID
map(Type.VAR_INT); // Entity type
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Y
map(Type.DOUBLE); // Z
map(Type.BYTE); // Pitch
map(Type.BYTE); // Yaw
map(Type.BYTE); // Head yaw
map(Type.VAR_INT); // Data
handler(getSpawnTrackerWithDataHandler1_19(fallingBlockType));
}
});
}
public PacketHandler getSpawnTrackerWithDataHandler(EntityType fallingBlockType) { public PacketHandler getSpawnTrackerWithDataHandler(EntityType fallingBlockType) {
return wrapper -> { return wrapper -> {
// Check against the UNMAPPED entity type // Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper); EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) { if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.INT, 0); int blockState = wrapper.get(Type.INT, 0);
wrapper.set(Type.INT, 0, protocol.getMappingData().getNewBlockStateId(blockState)); wrapper.set(Type.INT, 0, protocol.getMappingData().getNewBlockStateId(blockState));
@ -71,7 +91,7 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
public PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) { public PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) {
return wrapper -> { return wrapper -> {
// Check against the UNMAPPED entity type // Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper); EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) { if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.VAR_INT, 2); int blockState = wrapper.get(Type.VAR_INT, 2);
wrapper.set(Type.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(blockState)); wrapper.set(Type.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(blockState));
@ -86,7 +106,7 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
map(Type.VAR_INT); // 0 - Entity ID map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Entity UUID map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type map(Type.VAR_INT); // 2 - Entity Type
handler(wrapper -> setOldEntityId(wrapper)); handler(wrapper -> trackAndMapEntity(wrapper));
} }
}); });
} }
@ -114,7 +134,7 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
* @param wrapper packet wrapper * @param wrapper packet wrapper
* @return unmapped (!) entity type * @return unmapped (!) entity type
*/ */
protected EntityType setOldEntityId(PacketWrapper wrapper) throws Exception { protected EntityType trackAndMapEntity(PacketWrapper wrapper) throws Exception {
int typeId = wrapper.get(Type.VAR_INT, 1); int typeId = wrapper.get(Type.VAR_INT, 1);
EntityType entityType = typeFromId(typeId); EntityType entityType = typeFromId(typeId);
tracker(wrapper.user()).addEntity(wrapper.get(Type.VAR_INT, 0), entityType); tracker(wrapper.user()).addEntity(wrapper.get(Type.VAR_INT, 0), entityType);

View File

@ -25,6 +25,7 @@ import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.Int2IntMapMappings; import com.viaversion.viaversion.api.data.Int2IntMapMappings;
import com.viaversion.viaversion.api.data.entity.StoredEntityData; import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.entities.EntityType; import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType; import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata; import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
@ -37,9 +38,8 @@ import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.EntityRewriter; import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent; import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List; import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Entity rewriter base class. * Entity rewriter base class.
@ -65,34 +65,49 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
@Override @Override
public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) { public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final boolean initialMetadata = !(entity != null && entity.hasSentMetadata());
super.handleMetadata(entityId, metadataList, connection); super.handleMetadata(entityId, metadataList, connection);
EntityType type = tracker(connection).entityType(entityId); if (entity == null) {
if (type == null) {
return; // Don't handle untracked entities - basically always the fault of a plugin sending virtual entities through concurrency-unsafe handling return; // Don't handle untracked entities - basically always the fault of a plugin sending virtual entities through concurrency-unsafe handling
} }
EntityData entityData = entityDataForType(type); final EntityData entityData = entityDataForType(entity.entityType());
// Set the mapped entity name if there is no custom name set already // Set the mapped entity name if there is no custom name set already
Metadata meta = getMeta(displayNameIndex, metadataList); if (entityData != null && entityData.mobName() != null) {
if (meta != null && entityData != null && entityData.mobName() != null final Metadata displayName = getMeta(displayNameIndex, metadataList);
&& (meta.getValue() == null || meta.getValue().toString().isEmpty()) if (initialMetadata) {
&& meta.metaType().typeId() == displayNameMetaType.typeId()) { if (displayName == null) {
meta.setValue(entityData.mobName()); // Add it as new metadata
if (ViaBackwards.getConfig().alwaysShowOriginalMobName()) { metadataList.add(new Metadata(displayNameIndex, displayNameMetaType, entityData.mobName()));
removeMeta(displayVisibilityIndex, metadataList); addDisplayVisibilityMeta(metadataList);
metadataList.add(new Metadata(displayVisibilityIndex, displayVisibilityMetaType, true)); } else if (displayName.getValue() == null || displayName.getValue().toString().isEmpty()) {
// Overwrite the existing null/empty display name
displayName.setValue(entityData.mobName());
addDisplayVisibilityMeta(metadataList);
}
} else if (displayName != null && (displayName.getValue() == null || displayName.getValue().toString().isEmpty())) {
// Overwrite null/empty display name
displayName.setValue(entityData.mobName());
addDisplayVisibilityMeta(metadataList);
} }
} }
// Add any other extra meta for mapped entities // Add any other extra meta for mapped entities
//TODO only do this once for a first meta packet? if (entityData != null && entityData.hasBaseMeta() && initialMetadata) {
if (entityData != null && entityData.hasBaseMeta()) {
entityData.defaultMeta().createMeta(new WrappedMetadata(metadataList)); entityData.defaultMeta().createMeta(new WrappedMetadata(metadataList));
} }
} }
private void addDisplayVisibilityMeta(List<Metadata> metadataList) {
if (ViaBackwards.getConfig().alwaysShowOriginalMobName()) {
removeMeta(displayVisibilityIndex, metadataList);
metadataList.add(new Metadata(displayVisibilityIndex, displayVisibilityMetaType, true));
}
}
protected @Nullable Metadata getMeta(int metaIndex, List<Metadata> metadataList) { protected @Nullable Metadata getMeta(int metaIndex, List<Metadata> metadataList) {
for (Metadata metadata : metadataList) { for (Metadata metadata : metadataList) {
if (metadata.id() == metaIndex) { if (metadata.id() == metaIndex) {

View File

@ -60,7 +60,7 @@ public class Protocol1_10To1_11 extends BackwardsProtocol<ClientboundPackets1_9_
user.put(new ClientWorld(user)); user.put(new ClientWorld(user));
} }
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_11Types.EntityType.PLAYER, true)); user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_11Types.EntityType.PLAYER));
if (!user.has(WindowTracker.class)) { if (!user.has(WindowTracker.class)) {
user.put(new WindowTracker()); user.put(new WindowTracker());

View File

@ -85,7 +85,7 @@ public class Protocol1_11_1To1_12 extends BackwardsProtocol<ClientboundPackets1_
user.put(new ClientWorld(user)); user.put(new ClientWorld(user));
} }
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_12Types.EntityType.PLAYER, true)); user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_12Types.EntityType.PLAYER));
user.put(new ShoulderTracker(user)); user.put(new ShoulderTracker(user));
} }

View File

@ -190,7 +190,7 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol<ClientboundPackets1_
user.put(new ClientWorld(user)); user.put(new ClientWorld(user));
} }
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_14Types.PLAYER, true)); user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_14Types.PLAYER));
if (!user.has(ChunkLightStorage.class)) { if (!user.has(ChunkLightStorage.class)) {
user.put(new ChunkLightStorage(user)); user.put(new ChunkLightStorage(user));

View File

@ -200,7 +200,7 @@ public class Protocol1_15_2To1_16 extends BackwardsProtocol<ClientboundPackets1_
user.put(new PlayerSneakStorage()); user.put(new PlayerSneakStorage());
user.put(new WorldNameTracker()); user.put(new WorldNameTracker());
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_16Types.PLAYER, true)); user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_16Types.PLAYER));
} }
@Override @Override

View File

@ -287,7 +287,7 @@ public final class Protocol1_18_2To1_19 extends BackwardsProtocol<ClientboundPac
@Override @Override
public void init(final UserConnection user) { public void init(final UserConnection user) {
user.put(new DimensionRegistryStorage()); user.put(new DimensionRegistryStorage());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER, true)); addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER));
} }
@Override @Override

View File

@ -68,7 +68,7 @@ public final class EntityPackets1_19 extends EntityRewriter<ClientboundPackets1_
handler(wrapper -> { handler(wrapper -> {
final byte headYaw = wrapper.read(Type.BYTE); final byte headYaw = wrapper.read(Type.BYTE);
int data = wrapper.read(Type.VAR_INT); int data = wrapper.read(Type.VAR_INT);
final EntityType entityType = setOldEntityId(wrapper); final EntityType entityType = trackAndMapEntity(wrapper);
if (entityType.isOrHasParent(Entity1_19Types.LIVINGENTITY)) { if (entityType.isOrHasParent(Entity1_19Types.LIVINGENTITY)) {
wrapper.write(Type.BYTE, headYaw); wrapper.write(Type.BYTE, headYaw);

View File

@ -376,7 +376,7 @@ public final class Protocol1_19_1To1_19_3 extends BackwardsProtocol<ClientboundP
public void init(final UserConnection user) { public void init(final UserConnection user) {
user.put(new ChatSessionStorage()); user.put(new ChatSessionStorage());
user.put(new ChatTypeStorage1_19_3()); user.put(new ChatTypeStorage1_19_3());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19_3Types.PLAYER, true)); addEntityTracker(user, new EntityTrackerBase(user, Entity1_19_3Types.PLAYER));
} }
@Override @Override

View File

@ -54,7 +54,7 @@ public final class EntityPackets1_19_3 extends EntityRewriter<ClientboundPackets
private static final int UPDATE_DISPLAYNAME = 5; private static final int UPDATE_DISPLAYNAME = 5;
public EntityPackets1_19_3(final Protocol1_19_1To1_19_3 protocol) { public EntityPackets1_19_3(final Protocol1_19_1To1_19_3 protocol) {
super(protocol); super(protocol, Types1_19.META_TYPES.optionalComponentType, Types1_19.META_TYPES.booleanType);
} }
@Override @Override

View File

@ -38,14 +38,14 @@ import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPac
public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_19_3To1_19_4> { public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_19_3To1_19_4> {
public EntityPackets1_19_4(final Protocol1_19_3To1_19_4 protocol) { public EntityPackets1_19_4(final Protocol1_19_3To1_19_4 protocol) {
super(protocol); super(protocol, Types1_19_3.META_TYPES.optionalComponentType, Types1_19_3.META_TYPES.booleanType);
} }
@Override @Override
public void registerPackets() { public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_19_4.SPAWN_ENTITY, null); registerTrackerWithData1_19(ClientboundPackets1_19_4.SPAWN_ENTITY, null);
registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES); registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_19_4.ENTITY_METADATA, Types1_19_4.METADATA_LIST); registerMetadataRewriter(ClientboundPackets1_19_4.ENTITY_METADATA, Types1_19_4.METADATA_LIST, Types1_19_3.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_19_4.JOIN_GAME, new PacketRemapper() { protocol.registerClientbound(ClientboundPackets1_19_4.JOIN_GAME, new PacketRemapper() {
@Override @Override
@ -102,7 +102,6 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
filter().handler((event, meta) -> { filter().handler((event, meta) -> {
int id = meta.metaType().typeId(); int id = meta.metaType().typeId();
if (id >= 25) { // Vector3f/quaternion types if (id >= 25) { // Vector3f/quaternion types
event.cancel();
return; return;
} else if (id >= 15) { // Optional block state - just map down to block state } else if (id >= 15) { // Optional block state - just map down to block state
id--; id--;
@ -112,27 +111,35 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
}); });
registerMetaTypeHandler(Types1_19_3.META_TYPES.itemType, null, null); registerMetaTypeHandler(Types1_19_3.META_TYPES.itemType, null, null);
filter().type(Entity1_19_4Types.TEXT_DISPLAY).index(22).handler(((event, meta) -> {
// Send as custom display name
event.setIndex(2);
meta.setMetaType(Types1_19_3.META_TYPES.optionalComponentType);
event.createExtraMeta(new Metadata(3, Types1_19_4.META_TYPES.booleanType, true)); // Show custom name
}));
// TODO Maybe spawn an extra entity to ride the armor stand for blocks and items
filter().filterFamily(Entity1_19_4Types.DISPLAY).handler((event, meta) -> { filter().filterFamily(Entity1_19_4Types.DISPLAY).handler((event, meta) -> {
// Remove a large heap of display metadata // Remove a large heap of display metadata
if (event.index() > 7) { if (event.index() > 7) {
event.cancel(); event.cancel();
} }
}); });
filter().filterFamily(Entity1_19_4Types.ABSTRACT_HORSE).addIndex(18); // Owner UUID filter().filterFamily(Entity1_19_4Types.ABSTRACT_HORSE).addIndex(18); // Owner UUID
} }
@Override @Override
public void onMappingDataLoaded() { public void onMappingDataLoaded() {
mapTypes(); mapTypes();
// TODO Use text/item/block
final EntityData.MetaCreator metaCreator = storage -> { final EntityData.MetaCreator displayMetaCreator = storage -> {
storage.add(new Metadata(0, Types1_19_4.META_TYPES.byteType, (byte) 0x20)); // Invisible storage.add(new Metadata(0, Types1_19_4.META_TYPES.byteType, (byte) 0x20)); // Invisible
storage.add(new Metadata(5, Types1_19_4.META_TYPES.booleanType, true)); // No gravity storage.add(new Metadata(5, Types1_19_4.META_TYPES.booleanType, true)); // No gravity
storage.add(new Metadata(15, Types1_19_4.META_TYPES.byteType, (byte) (0x01 | 0x10))); // Small marker storage.add(new Metadata(15, Types1_19_4.META_TYPES.byteType, (byte) (0x01 | 0x10))); // Small marker
}; };
mapEntityTypeWithData(Entity1_19_4Types.BLOCK_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(metaCreator); mapEntityTypeWithData(Entity1_19_4Types.TEXT_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(displayMetaCreator);
mapEntityTypeWithData(Entity1_19_4Types.ITEM_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(metaCreator); mapEntityTypeWithData(Entity1_19_4Types.ITEM_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(displayMetaCreator);
mapEntityTypeWithData(Entity1_19_4Types.TEXT_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(metaCreator); mapEntityTypeWithData(Entity1_19_4Types.BLOCK_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(displayMetaCreator);
} }
@Override @Override

View File

@ -349,7 +349,7 @@ public final class Protocol1_19To1_19_1 extends BackwardsProtocol<ClientboundPac
public void init(final UserConnection user) { public void init(final UserConnection user) {
user.put(new ChatRegistryStorage1_19_1()); user.put(new ChatRegistryStorage1_19_1());
user.put(new ReceivedMessagesStorage()); user.put(new ReceivedMessagesStorage());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER, true)); addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER));
} }
@Override @Override

View File

@ -27,7 +27,7 @@ import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPacke
public final class EntityPackets1_19_1 extends EntityRewriter<ClientboundPackets1_19_1, Protocol1_19To1_19_1> { public final class EntityPackets1_19_1 extends EntityRewriter<ClientboundPackets1_19_1, Protocol1_19To1_19_1> {
public EntityPackets1_19_1(final Protocol1_19To1_19_1 protocol) { public EntityPackets1_19_1(final Protocol1_19To1_19_1 protocol) {
super(protocol); super(protocol, Types1_19.META_TYPES.optionalComponentType, Types1_19.META_TYPES.booleanType);
} }
@Override @Override