diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java index 317c240b3..13b37096d 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java @@ -129,6 +129,13 @@ public interface NonVanillaCustomItemData extends CustomItemData { */ boolean isHat(); + /** + * Gets if the item is a foil. This is used to determine if the item should be rendered with an enchantment glint effect. + * + * @return if the item is a foil + */ + boolean isFoil(); + /** * @deprecated Use {@link #displayHandheld()} instead. * Gets if the item is a tool. This is used to set the render type of the item, if the item is handheld. @@ -174,6 +181,8 @@ public interface NonVanillaCustomItemData extends CustomItemData { Builder hat(boolean isHat); + Builder foil(boolean isFoil); + /** * @deprecated Use {@link #displayHandheld(boolean)} instead. */ diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index e0f8c5a49..6ada880ce 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -36,6 +36,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; +import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -171,7 +172,9 @@ public class Entity implements GeyserEntity { addEntityPacket.setUniqueEntityId(geyserId); addEntityPacket.setPosition(position); addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation().toVector2(false)); // TODO: Check this + addEntityPacket.setRotation(Vector2f.from(pitch, yaw)); + addEntityPacket.setHeadRotation(headYaw); + addEntityPacket.setBodyRotation(yaw); // TODO: This should be bodyYaw addEntityPacket.getMetadata().putFlags(flags); dirtyMetadata.apply(addEntityPacket.getMetadata()); addAdditionalSpawnData(addEntityPacket); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index 892e22693..569ab2300 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -53,6 +53,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private final OptionalInt creativeCategory; private final String creativeGroup; private final boolean isHat; + private final boolean isFoil; private final boolean isTool; public GeyserNonVanillaCustomItemData(NonVanillaCustomItemDataBuilder builder) { @@ -72,6 +73,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i this.creativeCategory = builder.creativeCategory; this.creativeGroup = builder.creativeGroup; this.isHat = builder.hat; + this.isFoil = builder.foil; this.isTool = builder.tool; } @@ -140,6 +142,11 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return isHat; } + @Override + public boolean isFoil() { + return isFoil; + } + public static class NonVanillaCustomItemDataBuilder extends GeyserCustomItemData.CustomItemDataBuilder implements NonVanillaCustomItemData.Builder { private String identifier = null; private int javaId = -1; @@ -162,6 +169,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private String creativeGroup = null; private boolean hat = false; + private boolean foil = false; private boolean tool = false; @Override @@ -283,6 +291,12 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return this; } + @Override + public NonVanillaCustomItemData.Builder foil(boolean isFoil) { + this.foil = isFoil; + return this; + } + @Override public NonVanillaCustomItemData build() { if (identifier == null || javaId == -1) { diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index b2d49678e..7f1ea51bf 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -29,6 +29,8 @@ import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.item.type.*; import org.geysermc.geyser.registry.Registries; +import java.util.Collections; + import static org.geysermc.geyser.item.type.Item.builder; /** @@ -1298,7 +1300,11 @@ public final class Items { public static T register(T item, int id) { item.setJavaId(id); - Registries.JAVA_ITEMS.get().add(item); + // This makes sure that the array is large enough to put the java item at the correct location + if (Registries.JAVA_ITEMS.get().size() <= id) { + Registries.JAVA_ITEMS.get().addAll(Collections.nCopies(id - Registries.JAVA_ITEMS.get().size() + 1, AIR)); + } + Registries.JAVA_ITEMS.get().set(id, item); Registries.JAVA_ITEM_IDENTIFIERS.register(item.javaIdentifier(), item); return item; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java index 3c037988f..ca0d7aad1 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java @@ -247,6 +247,10 @@ public class CustomItemRegistryPopulator { itemProperties.putInt("creative_category", creativeCategory.getAsInt()); } + if (customItemData.isFoil()) { + itemProperties.putBoolean("foil", true); + } + componentBuilder.putCompound("item_properties", itemProperties.build()); builder.putCompound("components", componentBuilder.build()); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 696b6a4f6..a2b16ff3c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1745,7 +1745,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { abilities.add(Ability.NO_CLIP); } - abilityLayer.setLayerType(AbilityLayer.Type.BASE); + // https://github.com/GeyserMC/Geyser/issues/3769 Setting Spectator mode ability layer + if (spectator) { + abilityLayer.setLayerType(AbilityLayer.Type.SPECTATOR); + } else { + abilityLayer.setLayerType(AbilityLayer.Type.BASE); + } abilityLayer.setFlySpeed(flySpeed); // https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10 abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed);