mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
parent
d1afb81a3b
commit
b5e1ddc3c8
3 changed files with 56 additions and 24 deletions
|
@ -455,7 +455,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts how many ticks have occurred since an arm animation started.
|
* Counts how many ticks have occurred since an arm animation started.
|
||||||
* -1 means there is no active arm swing.
|
* -1 means there is no active arm swing; -2 means an arm swing will start in a tick.
|
||||||
*/
|
*/
|
||||||
private int armAnimationTicks = -1;
|
private int armAnimationTicks = -1;
|
||||||
|
|
||||||
|
@ -1157,7 +1157,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
entity.tick();
|
entity.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (armAnimationTicks != -1) {
|
if (armAnimationTicks >= 0) {
|
||||||
// As of 1.18.2 Java Edition, it appears that the swing time is dynamically updated depending on the
|
// As of 1.18.2 Java Edition, it appears that the swing time is dynamically updated depending on the
|
||||||
// player's effect status, but the animation can cut short if the duration suddenly decreases
|
// player's effect status, but the animation can cut short if the duration suddenly decreases
|
||||||
// (from suddenly no longer having mining fatigue, for example)
|
// (from suddenly no longer having mining fatigue, for example)
|
||||||
|
@ -1196,7 +1196,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
public void startSneaking() {
|
public void startSneaking() {
|
||||||
// Toggle the shield, if there is no ongoing arm animation
|
// Toggle the shield, if there is no ongoing arm animation
|
||||||
// This matches Bedrock Edition behavior as of 1.18.12
|
// This matches Bedrock Edition behavior as of 1.18.12
|
||||||
if (armAnimationTicks == -1) {
|
if (armAnimationTicks < 0) {
|
||||||
attemptToBlock();
|
attemptToBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,6 +1328,16 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For https://github.com/GeyserMC/Geyser/issues/2113 and combating arm ticking activating being delayed in
|
||||||
|
* BedrockAnimateTranslator.
|
||||||
|
*/
|
||||||
|
public void armSwingPending() {
|
||||||
|
if (armAnimationTicks == -1) {
|
||||||
|
armAnimationTicks = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates to the client to stop blocking and tells the Java server the same.
|
* Indicates to the client to stop blocking and tells the Java server the same.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -46,30 +46,32 @@ public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (packet.getAction()) {
|
switch (packet.getAction()) {
|
||||||
case SWING_ARM ->
|
case SWING_ARM -> {
|
||||||
|
session.armSwingPending();
|
||||||
// Delay so entity damage can be processed first
|
// Delay so entity damage can be processed first
|
||||||
session.scheduleInEventLoop(() -> {
|
session.scheduleInEventLoop(() -> {
|
||||||
if (session.getArmAnimationTicks() != 0) {
|
if (session.getArmAnimationTicks() != 0) {
|
||||||
// So, generally, a Java player can only do one *thing* at a time.
|
// So, generally, a Java player can only do one *thing* at a time.
|
||||||
// If a player right-clicks, for example, then there's probably only one action associated with
|
// If a player right-clicks, for example, then there's probably only one action associated with
|
||||||
// that right-click that will send a swing.
|
// that right-click that will send a swing.
|
||||||
// The only exception I can think of to this, *maybe*, is a player dropping items
|
// The only exception I can think of to this, *maybe*, is a player dropping items
|
||||||
// Bedrock is a little funkier than this - it can send several arm animation packets in the
|
// Bedrock is a little funkier than this - it can send several arm animation packets in the
|
||||||
// same tick, notably with high levels of haste applied.
|
// same tick, notably with high levels of haste applied.
|
||||||
// Packet limiters do not like this and can crash the player.
|
// Packet limiters do not like this and can crash the player.
|
||||||
// If arm animation ticks is 0, then we just sent an arm swing packet this tick.
|
// If arm animation ticks is 0, then we just sent an arm swing packet this tick.
|
||||||
// See https://github.com/GeyserMC/Geyser/issues/2875
|
// See https://github.com/GeyserMC/Geyser/issues/2875
|
||||||
// This behavior was last touched on with ViaVersion 4.5.1 (with its packet limiter), Java 1.16.5,
|
// This behavior was last touched on with ViaVersion 4.5.1 (with its packet limiter), Java 1.16.5,
|
||||||
// and Bedrock 1.19.51.
|
// and Bedrock 1.19.51.
|
||||||
// Note for the future: we should probably largely ignore this packet and instead replicate
|
// Note for the future: we should probably largely ignore this packet and instead replicate
|
||||||
// all actions on our end, and send swings where needed.
|
// all actions on our end, and send swings where needed.
|
||||||
session.sendDownstreamPacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
session.sendDownstreamPacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
||||||
session.activateArmAnimationTicking();
|
session.activateArmAnimationTicking();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
25,
|
25,
|
||||||
TimeUnit.MILLISECONDS
|
TimeUnit.MILLISECONDS
|
||||||
);
|
);
|
||||||
|
}
|
||||||
// These two might need to be flipped, but my recommendation is getting moving working first
|
// These two might need to be flipped, but my recommendation is getting moving working first
|
||||||
case ROW_LEFT -> {
|
case ROW_LEFT -> {
|
||||||
// Packet value is a float of how long one has been rowing, so we convert that into a boolean
|
// Packet value is a float of how long one has been rowing, so we convert that into a boolean
|
||||||
|
|
|
@ -25,7 +25,10 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.translator.protocol.bedrock.world;
|
package org.geysermc.geyser.translator.protocol.bedrock.world;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket;
|
||||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.AnimatePacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
|
@ -46,5 +49,22 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator<LevelSoun
|
||||||
// Sent here because Java still sends a cooldown if the player doesn't hit anything but Bedrock always sends a sound
|
// Sent here because Java still sends a cooldown if the player doesn't hit anything but Bedrock always sends a sound
|
||||||
CooldownUtils.sendCooldown(session);
|
CooldownUtils.sendCooldown(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet.getSound() == SoundEvent.ATTACK_NODAMAGE && session.getArmAnimationTicks() == -1) {
|
||||||
|
// https://github.com/GeyserMC/Geyser/issues/2113
|
||||||
|
// Seems like consoles and Android with keyboard send the animation packet on 1.19.51, hence the animation
|
||||||
|
// tick check - the animate packet is sent first.
|
||||||
|
// ATTACK_NODAMAGE = player clicked air
|
||||||
|
// This should only be revisited if Bedrock packets get full Java parity, or Bedrock starts sending arm
|
||||||
|
// animation packets after ATTACK_NODAMAGE, OR ATTACK_NODAMAGE gets removed/isn't sent in the same spot
|
||||||
|
session.sendDownstreamPacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
||||||
|
session.activateArmAnimationTicking();
|
||||||
|
|
||||||
|
// Send packet to Bedrock so it knows
|
||||||
|
AnimatePacket animatePacket = new AnimatePacket();
|
||||||
|
animatePacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId());
|
||||||
|
animatePacket.setAction(AnimatePacket.Action.SWING_ARM);
|
||||||
|
session.sendUpstreamPacket(animatePacket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue