Properly handle item display rotation change

Fixes #3354
This commit is contained in:
Nassim Jahnke 2023-07-02 11:01:12 +02:00
parent f28aac5eb3
commit 7edb43844c
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
5 changed files with 69 additions and 106 deletions

View File

@ -50,4 +50,14 @@ public final class Quaternion {
public float w() {
return w;
}
@Override
public String toString() {
return "Quaternion{" +
"x=" + x +
", y=" + y +
", z=" + z +
", w=" + w +
'}';
}
}

View File

@ -23,10 +23,10 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_19_4;
@ -37,105 +37,18 @@ import com.viaversion.viaversion.rewriter.EntityRewriter;
public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20To1_19_4> {
private static final Quaternion Y_FLIPPED_ROTATION = new Quaternion(0, 1, 0, 0);
public EntityPackets(final Protocol1_20To1_19_4 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_19_4.SPAWN_ENTITY, Entity1_19_4Types.FALLING_BLOCK);
registerMetadataRewriter(ClientboundPackets1_19_4.ENTITY_METADATA, Types1_19_4.METADATA_LIST, Types1_20.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_19_4.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
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(trackerHandler());
handler(wrapper -> {
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityType entityType = tracker(wrapper.user()).entityType(entityId);
if (entityType == Entity1_19_4Types.FALLING_BLOCK) {
wrapper.set(Type.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(wrapper.get(Type.VAR_INT, 2)));
} else if (entityType == Entity1_19_4Types.ITEM_DISPLAY) {
// Turn it upside down
wrapper.set(Type.BYTE, 0, (byte) -wrapper.get(Type.BYTE, 0));
wrapper.set(Type.BYTE, 1, (byte) (wrapper.get(Type.BYTE, 1) - 128));
}
});
}
});
final PacketHandler displayYawPitchHandler = wrapper -> {
final TrackedEntity trackedEntity = tracker(wrapper.user()).entity(wrapper.get(Type.VAR_INT, 0));
if (trackedEntity == null || trackedEntity.entityType() != Entity1_19_4Types.ITEM_DISPLAY) {
return;
}
// Turn it upside down
wrapper.set(Type.BYTE, 0, (byte) (wrapper.get(Type.BYTE, 0) - 128));
wrapper.set(Type.BYTE, 1, (byte) -wrapper.get(Type.BYTE, 1));
};
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
protected void register() {
map(Type.VAR_INT); // Entity id
map(Type.SHORT); // Delta X
map(Type.SHORT); // Delta Y
map(Type.SHORT); // Delta Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
handler(displayYawPitchHandler);
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_ROTATION, new PacketHandlers() {
@Override
protected void register() {
map(Type.VAR_INT); // Entity id
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
handler(displayYawPitchHandler);
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_HEAD_LOOK, wrapper -> {
final TrackedEntity trackedEntity = tracker(wrapper.user()).entity(wrapper.passthrough(Type.VAR_INT));
if (trackedEntity == null || trackedEntity.entityType() != Entity1_19_4Types.ITEM_DISPLAY) {
return;
}
wrapper.write(Type.BYTE, (byte) (wrapper.read(Type.BYTE) - 128));
});
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_TELEPORT, new PacketHandlers() {
@Override
protected void register() {
map(Type.VAR_INT); // Entity id
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Y
map(Type.DOUBLE); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
handler(wrapper -> {
TrackedEntity trackedEntity = tracker(wrapper.user()).entity(wrapper.get(Type.VAR_INT, 0));
if (trackedEntity == null || trackedEntity.entityType() != Entity1_19_4Types.ITEM_DISPLAY) {
return;
}
wrapper.set(Type.BYTE, 0, (byte) (wrapper.get(Type.BYTE, 0) - 128));
wrapper.set(Type.BYTE, 1, (byte) -wrapper.get(Type.BYTE, 1));
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
@ -218,6 +131,21 @@ public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4
filter().handler((event, meta) -> meta.setMetaType(Types1_20.META_TYPES.byId(meta.metaType().typeId())));
registerMetaTypeHandler(Types1_20.META_TYPES.itemType, Types1_20.META_TYPES.blockStateType, Types1_20.META_TYPES.optionalBlockStateType, Types1_20.META_TYPES.particleType);
// Rotate item display by 180 degrees around the Y axis
filter().filterFamily(Entity1_19_4Types.DISPLAY).handler((event, meta) -> {
if (event.trackedEntity().hasSentMetadata() || event.hasExtraMeta()) {
return;
}
if (event.metaAtIndex(12) == null) {
event.createExtraMeta(new Metadata(12, Types1_20.META_TYPES.quaternionType, Y_FLIPPED_ROTATION));
}
});
filter().filterFamily(Entity1_19_4Types.DISPLAY).index(12).handler((event, meta) -> {
final Quaternion quaternion = meta.value();
meta.setValue(rotateY180(quaternion));
});
filter().filterFamily(Entity1_19_4Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
@ -228,4 +156,8 @@ public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4
public EntityType typeFromId(final int type) {
return Entity1_19_4Types.getTypeFromId(type);
}
private Quaternion rotateY180(final Quaternion quaternion) {
return new Quaternion(-quaternion.z(), quaternion.w(), quaternion.x(), -quaternion.y());
}
}

View File

@ -101,11 +101,11 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
@Override
public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) {
public void handleMetadata(final int entityId, final List<Metadata> metadataList, final UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final EntityType type = entity != null ? entity.entityType() : null;
int i = 0; // Count index for fast removal
for (Metadata metadata : metadataList.toArray(EMPTY_ARRAY)) { // Copy the list to allow mutation
for (final Metadata metadata : metadataList.toArray(EMPTY_ARRAY)) { // Copy the list to allow mutation
// Call handlers implementing the old handleMetadata
if (!callOldMetaHandler(entityId, type, metadata, metadataList, connection)) {
metadataList.remove(i--);
@ -113,18 +113,18 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
MetaHandlerEvent event = null;
for (MetaFilter filter : metadataFilters) {
for (final MetaFilter filter : metadataFilters) {
if (!filter.isFiltered(type, metadata)) {
continue;
}
if (event == null) {
// Only initialize when needed and share event instance
event = new MetaHandlerEventImpl(connection, type, entityId, metadata, metadataList);
event = new MetaHandlerEventImpl(connection, entity, entityId, metadata, metadataList);
}
try {
filter.handler().handle(event, metadata);
} catch (Exception e) {
} catch (final Exception e) {
logException(e, type, metadataList, metadata);
metadataList.remove(i--);
break;

View File

@ -18,11 +18,13 @@
package com.viaversion.viaversion.rewriter.meta;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
public interface MetaHandlerEvent {
/**
@ -39,12 +41,21 @@ public interface MetaHandlerEvent {
*/
int entityId();
/**
* Returns the tracked entity if present.
*
* @return tracked entity if present, else null
*/
@Nullable TrackedEntity trackedEntity();
/**
* Returns the entity type of the entity the metadata belongs to if tracked.
*
* @return entity type of the entity if tracked, else null
*/
@Nullable EntityType entityType();
default @Nullable EntityType entityType() {
return trackedEntity() != null ? trackedEntity().entityType() : null;
}
/**
* Returns the metadata index.
@ -110,6 +121,15 @@ public interface MetaHandlerEvent {
*/
@Nullable List<Metadata> extraMeta();
/**
* Returns whether additionally created metadata will be added.
*
* @return true if additionally created metadata is present
*/
default boolean hasExtraMeta() {
return extraMeta() != null;
}
/**
* Adds the given metadata to the metadata list.
* This metadata will not be passed through handlers of the current loop.

View File

@ -19,25 +19,26 @@
package com.viaversion.viaversion.rewriter.meta;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MetaHandlerEventImpl implements MetaHandlerEvent {
private final UserConnection connection;
private final EntityType entityType;
private final TrackedEntity trackedEntity;
private final int entityId;
private final List<Metadata> metadataList;
private final Metadata meta;
private List<Metadata> extraData;
private boolean cancel;
public MetaHandlerEventImpl(UserConnection connection, @Nullable EntityType entityType, int entityId, Metadata meta, List<Metadata> metadataList) {
public MetaHandlerEventImpl(UserConnection connection, @Nullable TrackedEntity trackedEntity, int entityId, Metadata meta, List<Metadata> metadataList) {
this.connection = connection;
this.entityType = entityType;
this.trackedEntity = trackedEntity;
this.entityId = entityId;
this.meta = meta;
this.metadataList = metadataList;
@ -54,8 +55,8 @@ public class MetaHandlerEventImpl implements MetaHandlerEvent {
}
@Override
public @Nullable EntityType entityType() {
return entityType;
public @Nullable TrackedEntity trackedEntity() {
return trackedEntity;
}
@Override