25
25
26
26
package org .geysermc .geyser .translator .protocol .java .entity ;
27
27
28
+ import org .cloudburstmc .protocol .bedrock .data .AttributeData ;
28
29
import org .cloudburstmc .protocol .bedrock .packet .MobEffectPacket ;
29
30
import org .cloudburstmc .protocol .bedrock .packet .UpdateAttributesPacket ;
30
31
import org .geysermc .geyser .entity .attribute .GeyserAttributeType ;
31
32
import org .geysermc .geyser .entity .type .Entity ;
32
33
import org .geysermc .geyser .entity .vehicle .ClientVehicle ;
33
34
import org .geysermc .geyser .session .GeyserSession ;
35
+ import org .geysermc .geyser .session .cache .EntityEffectCache ;
34
36
import org .geysermc .geyser .translator .protocol .PacketTranslator ;
35
37
import org .geysermc .geyser .translator .protocol .Translator ;
36
38
import org .geysermc .geyser .util .EntityUtils ;
37
- import org .geysermc .mcprotocollib .protocol .data .game .entity .Effect ;
38
39
import org .geysermc .mcprotocollib .protocol .packet .ingame .clientbound .entity .ClientboundUpdateMobEffectPacket ;
39
40
40
41
import java .util .Collections ;
@@ -49,33 +50,45 @@ public void translate(GeyserSession session, ClientboundUpdateMobEffectPacket pa
49
50
return ;
50
51
}
51
52
53
+ var event = MobEffectPacket .Event .ADD ;
54
+
52
55
if (entity == session .getPlayerEntity ()) {
53
- session .getEffectCache ().setEffect (packet .getEffect (), packet .getAmplifier ());
56
+ EntityEffectCache cache = session .getEffectCache ();
57
+ cache .setEffect (packet .getEffect (), packet .getAmplifier ());
58
+ // Matches BDS
59
+ if (cache .getEntityEffects ().contains (packet .getEffect ())) {
60
+ event = MobEffectPacket .Event .MODIFY ;
61
+ }
54
62
} else if (entity instanceof ClientVehicle clientVehicle ) {
55
63
clientVehicle .getVehicleComponent ().setEffect (packet .getEffect (), packet .getAmplifier ());
56
64
}
57
65
58
66
MobEffectPacket mobEffectPacket = new MobEffectPacket ();
59
67
mobEffectPacket .setAmplifier (packet .getAmplifier ());
60
68
mobEffectPacket .setDuration (packet .getDuration ());
61
- mobEffectPacket .setEvent (MobEffectPacket . Event . ADD );
69
+ mobEffectPacket .setEvent (event );
62
70
mobEffectPacket .setRuntimeEntityId (entity .getGeyserId ());
63
71
mobEffectPacket .setParticles (packet .isShowParticles ());
64
72
mobEffectPacket .setEffectId (EntityUtils .toBedrockEffectId (packet .getEffect ()));
65
73
session .sendUpstreamPacket (mobEffectPacket );
66
74
67
- // Fixes https://github.com/GeyserMC/Geyser/issues/5347 by re-sending the correct absorption hearts
68
- if (entity == session .getPlayerEntity () && packet .getEffect () == Effect .ABSORPTION ) {
69
- var absorptionAttribute = session .getPlayerEntity ().getAttributes ().get (GeyserAttributeType .ABSORPTION );
70
- if (absorptionAttribute == null ) {
75
+ // Bedrock expects some attributes to be updated in the same tick as the effect causing them
76
+ if (entity == session .getPlayerEntity ()) {
77
+ AttributeData attribute = switch (packet .getEffect ()) {
78
+ // Fixes https://github.com/GeyserMC/Geyser/issues/5347
79
+ case ABSORPTION -> session .getPlayerEntity ().getAttributes ().get (GeyserAttributeType .ABSORPTION );
80
+ // Fixes https://github.com/GeyserMC/Geyser/issues/5388
81
+ case SPEED -> session .getPlayerEntity ().getAttributes ().get (GeyserAttributeType .MOVEMENT_SPEED );
82
+ default -> null ;
83
+ };
84
+
85
+ if (attribute == null ) {
71
86
return ;
72
87
}
73
88
74
89
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket ();
75
90
attributesPacket .setRuntimeEntityId (entity .getGeyserId ());
76
- // Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit
77
- attributesPacket .setAttributes (Collections .singletonList (
78
- GeyserAttributeType .ABSORPTION .getAttribute (absorptionAttribute .getValue ())));
91
+ attributesPacket .setAttributes (Collections .singletonList (attribute ));
79
92
session .sendUpstreamPacket (attributesPacket );
80
93
}
81
94
}
0 commit comments