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) {
return wrapper -> {
// Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper);
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.INT, 0);
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) {
return wrapper -> {
// Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper);
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.VAR_INT, 2);
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.UUID); // 1 - Entity UUID
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
* @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);
EntityType entityType = typeFromId(typeId);
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.data.Int2IntMapMappings;
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.metadata.MetaType;
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.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Entity rewriter base class.
@ -65,34 +65,49 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
@Override
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);
EntityType type = tracker(connection).entityType(entityId);
if (type == null) {
if (entity == null) {
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
Metadata meta = getMeta(displayNameIndex, metadataList);
if (meta != null && entityData != null && entityData.mobName() != null
&& (meta.getValue() == null || meta.getValue().toString().isEmpty())
&& meta.metaType().typeId() == displayNameMetaType.typeId()) {
meta.setValue(entityData.mobName());
if (ViaBackwards.getConfig().alwaysShowOriginalMobName()) {
removeMeta(displayVisibilityIndex, metadataList);
metadataList.add(new Metadata(displayVisibilityIndex, displayVisibilityMetaType, true));
if (entityData != null && entityData.mobName() != null) {
final Metadata displayName = getMeta(displayNameIndex, metadataList);
if (initialMetadata) {
if (displayName == null) {
// Add it as new metadata
metadataList.add(new Metadata(displayNameIndex, displayNameMetaType, entityData.mobName()));
addDisplayVisibilityMeta(metadataList);
} 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
//TODO only do this once for a first meta packet?
if (entityData != null && entityData.hasBaseMeta()) {
if (entityData != null && entityData.hasBaseMeta() && initialMetadata) {
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) {
for (Metadata metadata : metadataList) {
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.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)) {
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.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));
}

View File

@ -190,7 +190,7 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol<ClientboundPackets1_
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)) {
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 WorldNameTracker());
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_16Types.PLAYER, true));
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_16Types.PLAYER));
}
@Override

View File

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

View File

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

View File

@ -54,7 +54,7 @@ public final class EntityPackets1_19_3 extends EntityRewriter<ClientboundPackets
private static final int UPDATE_DISPLAYNAME = 5;
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

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 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
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_19_4.SPAWN_ENTITY, null);
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() {
@Override
@ -102,7 +102,6 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
filter().handler((event, meta) -> {
int id = meta.metaType().typeId();
if (id >= 25) { // Vector3f/quaternion types
event.cancel();
return;
} else if (id >= 15) { // Optional block state - just map down to block state
id--;
@ -112,27 +111,35 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
});
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) -> {
// Remove a large heap of display metadata
if (event.index() > 7) {
event.cancel();
}
});
filter().filterFamily(Entity1_19_4Types.ABSTRACT_HORSE).addIndex(18); // Owner UUID
}
@Override
public void onMappingDataLoaded() {
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(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
};
mapEntityTypeWithData(Entity1_19_4Types.BLOCK_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(metaCreator);
mapEntityTypeWithData(Entity1_19_4Types.ITEM_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(metaCreator);
mapEntityTypeWithData(Entity1_19_4Types.TEXT_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(displayMetaCreator);
mapEntityTypeWithData(Entity1_19_4Types.BLOCK_DISPLAY, Entity1_19_4Types.ARMOR_STAND).spawnMetadata(displayMetaCreator);
}
@Override

View File

@ -349,7 +349,7 @@ public final class Protocol1_19To1_19_1 extends BackwardsProtocol<ClientboundPac
public void init(final UserConnection user) {
user.put(new ChatRegistryStorage1_19_1());
user.put(new ReceivedMessagesStorage());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER, true));
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER));
}
@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 EntityPackets1_19_1(final Protocol1_19To1_19_1 protocol) {
super(protocol);
super(protocol, Types1_19.META_TYPES.optionalComponentType, Types1_19.META_TYPES.booleanType);
}
@Override