1.17.x NMS SetDirection for EntityItemFrame broken

Discussion in 'Spigot Plugin Development' started by SnowGears, Jun 25, 2021.

  1. I am using NMS to send fake entity packets to players but for whatever reason the setdirection just will not work. I built this same thing in 1.16.5 and it all work perfectly so I'm wondering if I'm doing something wrong with the new 1.17 obfuscation. Any help would be greatly appreciated.

    Code (Java):

    protected void spawnItemFramePacket(Player player, ItemStack is, Location location, BlockFace facing, boolean isGlowing){

        WorldServer worldServer = ((CraftWorld) location.getWorld()).getHandle();
        BlockPosition blockPosition = new BlockPosition(location.getX(), location.getY(), location.getZ());

        EntityItemFrame itemFrame = new EntityItemFrame(worldServer, blockPosition, getEnumDirection(facing));

        int entityID = itemFrame.getId();
        this.entityIDs.add(entityID);
        itemFrame.setLocation(location.getX(), location.getY(), location.getZ(),0f,0f);
        itemFrame.setItem(CraftItemStack.asNMSCopy(is));
        itemFrame.setDirection(getEnumDirection(facing));

        PacketPlayOutSpawnEntity entitySpawnPacket = new PacketPlayOutSpawnEntity(itemFrame);
        PacketPlayOutEntityMetadata entityMetadataPacket = new PacketPlayOutEntityMetadata(entityID, itemFrame.getDataWatcher(), true);

        sendPacket(player, entitySpawnPacket);
        sendPacket(player, entityMetadataPacket);
    }

    private EnumDirection getEnumDirection(BlockFace facing){
        switch (facing){
            case NORTH:
                return EnumDirection.c;
            case SOUTH:
                return EnumDirection.d;
            case WEST:
                return EnumDirection.e;
            case EAST:
                return EnumDirection.f;
            case DOWN:
                return EnumDirection.a;
            default:
                return EnumDirection.b;
        }
    }
     
    This spawns the EntityItemFrame for the player with the correct item in it but it is always facing down. No matter what I set the enum to in itemFrame.setDirection() it is always facing down. I have even tried putting the different enum constants in directly and nothing. Still facing down.

    Code (Java):

    itemFrame.setDirection(EnumDirection.c);
    itemFrame.setDirection(EnumDirection.d);
    itemFrame.setDirection(EnumDirection.e);
    itemFrame.setDirection(EnumDirection.f);
     
    All still end up with the frame facing down. Any help would be greatly appreciated!
     
  2. Acording to the ItemFrameEntity.setDirection(EnumDirection)
    The pitch and yaw are set corresponding to the EnumDirection.
    So that doens't look that is the case here

    Code (Java):
    public void setDirection(EnumDirection enumdirection) {
            Validate.notNull(enumdirection);
            this.d = enumdirection;
            if (enumdirection.n().d()) {
                this.setXRot(0.0F);
                this.setYRot((float)(this.d.get2DRotationValue() * 90));
            } else {
                this.setXRot((float)(-90 * enumdirection.e().a()));
                this.setYRot(0.0F);
            }

            this.y = this.getXRot();
            this.x = this.getYRot();
            this.updateBoundingBox();
        }
     
  3. Use itemFrame.getPacket() instead of creating the PacketPlayOutSpawnEntity your self.
     
  4. In PacketPlayOutSpawnEntity there is a data field called 'PacketPlayOutSpawnEntity.n' which represents the data of the object (Facing) in this case. Because you used the default constructor
    Code (Java):
    public PacketPlayOutSpawnEntity(Entity var0) {
        this(var0, 0);
    }
    The facing field is always set to zero. So the default facing was down.

    Value Orientation
    0 Down <---- default
    1 Up
    2 North
    3 South
    4 West
    5 East

    You can fix this by either using the propper constructor PacketPlayOutSpawnEntity(Entity var0, int var1) or call PacketPlayOutSpawnEntity.getPacket()
    But make sure, if you use the other constructor, to set the pitch/yaw accordingly to the itemframe facing.

    Code (Java):
    EnumDirection direction = getEnumDirection(facing);
    frame.setDirection(direction);
    PacketPlayOutSpawnEntity entitySpawnPacket = new PacketPlayOutSpawnEntity(frame, direction.b());
     
    #6 DanielTheDev, Jun 28, 2021
    Last edited: Jun 28, 2021
    • Winner Winner x 1
  5. You're the best! Fixed it by using the other constructor just as you suggested! (after already setting the direction)
    Code (Java):

    PacketPlayOutSpawnEntity entitySpawnPacket = new PacketPlayOutSpawnEntity(itemFrame, itemFrame.getDirection().b());
     
     
    • Like Like x 1