diff --git a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java index 80db3354e3c..abb5ebc7fad 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java +++ b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java @@ -54,6 +54,7 @@ public enum GeyserAttributeType { MINING_EFFICIENCY("minecraft:mining_efficiency", null, 0f, 1024f, 0f), BLOCK_BREAK_SPEED("minecraft:block_break_speed", null, 0f, 1024f, 1f), SUBMERGED_MINING_SPEED("minecraft:submerged_mining_speed", null, 0f, 20f, 0.2f), + WATER_MOVEMENT_EFFICIENCY("minecraft:water_movement_efficiency", null, 0f, 1f, 0f), // Bedrock Attributes ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), @@ -62,7 +63,9 @@ public enum GeyserAttributeType { EXPERIENCE_LEVEL(null, "minecraft:player.level", 0f, 24791.00f, 0f), HEALTH(null, "minecraft:health", 0f, 1024f, 20f), HUNGER(null, "minecraft:player.hunger", 0f, 20f, 20f), - SATURATION(null, "minecraft:player.saturation", 0f, 20f, 20f); + SATURATION(null, "minecraft:player.saturation", 0f, 20f, 20f), + LAVA_MOVEMENT(null, "minecraft:lava_movement", 0f, 3.4028235E38f, 0.02f), + UNDERWATER_MOVEMENT(null, "minecraft:underwater_movement", 0f, 3.4028235E38f, 0.02f); private final String javaIdentifier; private final String bedrockIdentifier; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index b98b4162bee..317259a0ce1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -572,4 +572,10 @@ public void forceFlagUpdate() { public boolean isGliding() { return getFlag(EntityFlag.GLIDING); } + + public AttributeData updateDolphinsGrace(boolean value) { + AttributeData data = GeyserAttributeType.UNDERWATER_MOVEMENT.getAttribute(value ? 0.024f : 0.02f); + attributes.put(GeyserAttributeType.UNDERWATER_MOVEMENT, data); + return data; + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java index e5fd76cd4a9..c6fe3f480ad 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java @@ -25,27 +25,39 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import org.geysermc.geyser.level.EffectType; -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveMobEffectPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.vehicle.ClientVehicle; +import org.geysermc.geyser.level.EffectType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveMobEffectPacket; + +import java.util.Collections; @Translator(packet = ClientboundRemoveMobEffectPacket.class) public class JavaRemoveMobEffectTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundRemoveMobEffectPacket packet) { - Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); + Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); if (entity == null) { return; } if (entity == session.getPlayerEntity()) { session.getEffectCache().removeEffect(packet.getEffect()); + + if (packet.getEffect() == Effect.DOLPHINS_GRACE) { + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(entity.geyserId()); + attributesPacket.setAttributes(Collections.singletonList( + session.getPlayerEntity().updateDolphinsGrace(false))); + session.sendUpstreamPacket(attributesPacket); + } } else if (entity instanceof ClientVehicle clientVehicle) { clientVehicle.getVehicleComponent().removeEffect(packet.getEffect()); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java index a64ebc7ffb8..1bf220baf40 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java @@ -30,8 +30,8 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; -import org.geysermc.geyser.level.EffectType; import org.geysermc.geyser.entity.vehicle.ClientVehicle; +import org.geysermc.geyser.level.EffectType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.EntityEffectCache; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -81,6 +81,7 @@ public void translate(GeyserSession session, ClientboundUpdateMobEffectPacket pa case ABSORPTION -> session.getPlayerEntity().getAttributes().get(GeyserAttributeType.ABSORPTION); // Fixes https://github.com/GeyserMC/Geyser/issues/5388 case SPEED -> session.getPlayerEntity().getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED); + case DOLPHINS_GRACE -> session.getPlayerEntity().updateDolphinsGrace(true); default -> null; }; diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java index 6b282d21d14..e0facc6c103 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -34,13 +34,15 @@ import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket; import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.type.Entity; -import org.geysermc.geyser.level.EffectType; import org.geysermc.geyser.level.BedrockDimension; +import org.geysermc.geyser.level.EffectType; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; +import java.util.Collections; import java.util.Set; public class DimensionUtils { @@ -75,6 +77,14 @@ public static void switchDimension(GeyserSession session, JavaDimension javaDime mobEffectPacket.setRuntimeEntityId(player.geyserId()); mobEffectPacket.setEffectId(EffectType.fromJavaEffect(effect).getBedrockId()); session.sendUpstreamPacket(mobEffectPacket); + + if (effect == Effect.DOLPHINS_GRACE) { + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(player.geyserId()); + attributesPacket.setAttributes(Collections.singletonList( + session.getPlayerEntity().updateDolphinsGrace(false))); + session.sendUpstreamPacket(attributesPacket); + } } // Effects are re-sent from server entityEffects.clear();