diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java index 97ab18c6b..11702e78a 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java @@ -62,6 +62,7 @@ public final class BlockStateValues { private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet(); private static final IntSet MOVING_PISTONS = new IntOpenHashSet(); private static final Int2ByteMap SKULL_VARIANTS = new FixedInt2ByteMap(); + private static final IntSet SKULL_POWERED = new IntOpenHashSet(); private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap(); private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap(); private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap(); @@ -172,6 +173,13 @@ public final class BlockStateValues { SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } + if (javaId.startsWith("minecraft:dragon_head[") || javaId.startsWith("minecraft:piglin_head[") + || javaId.startsWith("minecraft:dragon_wall_head[") || javaId.startsWith("minecraft:piglin_wall_head[")) { + if (javaId.contains("powered=true")) { + SKULL_POWERED.add(javaBlockState); + } + } + if (javaId.contains("wall_skull") || javaId.contains("wall_head")) { String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7, javaId.lastIndexOf("powered=") - 1); int rotation = switch (direction) { @@ -448,6 +456,17 @@ public final class BlockStateValues { return SKULL_ROTATIONS.getOrDefault(state, (byte) -1); } + /** + * As of Java 1.20.2: + * Skull powered states are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * + * @param state BlockState of the block + * @return true if this skull is currently being powered. + */ + public static boolean isSkullPowered(int state) { + return SKULL_POWERED.contains(state); + } + /** * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a integer rotation that Bedrock can use. diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 76cdbb5a4..7f87f9465 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -60,6 +60,9 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } builder.put("Rotation", rotation); builder.put("SkullType", skullVariant); + if (BlockStateValues.isSkullPowered(blockState)) { + builder.putBoolean("MouthMoving", true); + } } private static UUID getUUID(CompoundTag owner) {