mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-19 14:59:27 +00:00
Fix: Input processing on mobile devices with classic D-Pad control mode
This commit is contained in:
@@ -29,6 +29,7 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.cloudburstmc.math.vector.Vector2f;
|
import org.cloudburstmc.math.vector.Vector2f;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.InputInteractionModel;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.InputMode;
|
import org.cloudburstmc.protocol.bedrock.data.InputMode;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.PlayerAuthInputData;
|
import org.cloudburstmc.protocol.bedrock.data.PlayerAuthInputData;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
|
||||||
@@ -61,14 +62,54 @@ public final class InputCache {
|
|||||||
var oldInputPacket = this.inputPacket;
|
var oldInputPacket = this.inputPacket;
|
||||||
this.inputMode = packet.getInputMode();
|
this.inputMode = packet.getInputMode();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Brief introduction to how Bedrock sends movement inputs! It's mainly based on the following:
|
||||||
|
(as of 1.21.111)
|
||||||
|
1. inputmode:
|
||||||
|
- MOUSE: same as Java edition; will send up/down/left/right inputs via input flags
|
||||||
|
- GAMEPAD: indicates the use of a controller with joysticks, sends an "analogue movement vector" instead
|
||||||
|
- TOUCH: see interaction model!
|
||||||
|
- MOTION_CONTROLLER: what even is this
|
||||||
|
|
||||||
|
2. Interaction model (here, only really relevant for us when the inputmode is "touch"):
|
||||||
|
- CLASSIC: shows "wasd" keys on the client; like input-mode MOUSE would, additionally up_left / up_right / down_left / down_right
|
||||||
|
- CROSSHAIR / TOUCH: NO wasd, analogue movement vector instead
|
||||||
|
|
||||||
|
Hence, we'll also need to check for this fun edge-case!
|
||||||
|
*/
|
||||||
|
boolean isMobileAndClassicMovement = inputMode == InputMode.TOUCH && packet.getInputInteractionModel() == InputInteractionModel.CLASSIC;
|
||||||
|
|
||||||
boolean up, down, left, right;
|
boolean up, down, left, right;
|
||||||
if (this.inputMode == InputMode.MOUSE) {
|
if (this.inputMode == InputMode.MOUSE || isMobileAndClassicMovement) {
|
||||||
up = bedrockInput.contains(PlayerAuthInputData.UP);
|
up = bedrockInput.contains(PlayerAuthInputData.UP);
|
||||||
down = bedrockInput.contains(PlayerAuthInputData.DOWN);
|
down = bedrockInput.contains(PlayerAuthInputData.DOWN);
|
||||||
left = bedrockInput.contains(PlayerAuthInputData.LEFT);
|
left = bedrockInput.contains(PlayerAuthInputData.LEFT);
|
||||||
right = bedrockInput.contains(PlayerAuthInputData.RIGHT);
|
right = bedrockInput.contains(PlayerAuthInputData.RIGHT);
|
||||||
|
|
||||||
|
if (isMobileAndClassicMovement) {
|
||||||
|
// These are the buttons in the corners of the touch area
|
||||||
|
if (bedrockInput.contains(PlayerAuthInputData.UP_LEFT)) {
|
||||||
|
up = true;
|
||||||
|
left = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bedrockInput.contains(PlayerAuthInputData.UP_RIGHT)) {
|
||||||
|
up = true;
|
||||||
|
right = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bedrockInput.contains(PlayerAuthInputData.DOWN_LEFT)) {
|
||||||
|
down = true;
|
||||||
|
left = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bedrockInput.contains(PlayerAuthInputData.DOWN_RIGHT)) {
|
||||||
|
down = true;
|
||||||
|
right = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// The above flags don't fire TODO test console
|
// The above flags don't fire
|
||||||
Vector2f analogMovement = packet.getAnalogMoveVector();
|
Vector2f analogMovement = packet.getAnalogMoveVector();
|
||||||
up = analogMovement.getY() > 0;
|
up = analogMovement.getY() > 0;
|
||||||
down = analogMovement.getY() < 0;
|
down = analogMovement.getY() < 0;
|
||||||
@@ -78,7 +119,6 @@ public final class InputCache {
|
|||||||
|
|
||||||
boolean sneaking = isSneaking(bedrockInput);
|
boolean sneaking = isSneaking(bedrockInput);
|
||||||
|
|
||||||
// TODO when is UP_LEFT, etc. used?
|
|
||||||
this.inputPacket = this.inputPacket
|
this.inputPacket = this.inputPacket
|
||||||
.withForward(up)
|
.withForward(up)
|
||||||
.withBackward(down)
|
.withBackward(down)
|
||||||
@@ -133,7 +173,7 @@ public final class InputCache {
|
|||||||
public boolean isSneaking(Set<PlayerAuthInputData> authInputData) {
|
public boolean isSneaking(Set<PlayerAuthInputData> authInputData) {
|
||||||
// Flying doesn't send start / stop fly cases; might as well return early
|
// Flying doesn't send start / stop fly cases; might as well return early
|
||||||
if (session.isFlying()) {
|
if (session.isFlying()) {
|
||||||
// Of course e.g. mobile handles it differently with a descend case, while
|
// Of course e.g. mobile devices handle it differently with a descend case, while
|
||||||
// e.g. Win10 sends SNEAK_DOWN. Why? We'll never know.
|
// e.g. Win10 sends SNEAK_DOWN. Why? We'll never know.
|
||||||
return authInputData.contains(PlayerAuthInputData.DESCEND) || authInputData.contains(PlayerAuthInputData.SNEAK_DOWN);
|
return authInputData.contains(PlayerAuthInputData.DESCEND) || authInputData.contains(PlayerAuthInputData.SNEAK_DOWN);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user