29
29
import lombok .Setter ;
30
30
import org .checkerframework .checker .nullness .qual .MonotonicNonNull ;
31
31
import org .cloudburstmc .math .vector .Vector2f ;
32
+ import org .cloudburstmc .protocol .bedrock .data .InputInteractionModel ;
32
33
import org .cloudburstmc .protocol .bedrock .data .InputMode ;
33
34
import org .cloudburstmc .protocol .bedrock .data .PlayerAuthInputData ;
34
35
import org .cloudburstmc .protocol .bedrock .packet .PlayerAuthInputPacket ;
@@ -61,14 +62,54 @@ public void processInputs(SessionPlayerEntity entity, PlayerAuthInputPacket pack
61
62
var oldInputPacket = this .inputPacket ;
62
63
this .inputMode = packet .getInputMode ();
63
64
65
+ /*
66
+ Brief introduction to how Bedrock sends movement inputs! It's mainly based on the following:
67
+ (as of 1.21.111)
68
+ 1. inputmode:
69
+ - MOUSE: same as Java edition; will send up/down/left/right inputs via input flags
70
+ - GAMEPAD: indicates the use of a controller with joysticks, sends an "analogue movement vector" instead
71
+ - TOUCH: see interaction model!
72
+ - MOTION_CONTROLLER: what even is this
73
+
74
+ 2. Interaction model (here, only really relevant for us when the inputmode is "touch"):
75
+ - CLASSIC: shows "wasd" keys on the client; like input-mode MOUSE would, additionally up_left / up_right / down_left / down_right
76
+ - CROSSHAIR / TOUCH: NO wasd, analogue movement vector instead
77
+
78
+ Hence, we'll also need to check for this fun edge-case!
79
+ */
80
+ boolean isMobileAndClassicMovement = inputMode == InputMode .TOUCH && packet .getInputInteractionModel () == InputInteractionModel .CLASSIC ;
81
+
64
82
boolean up , down , left , right ;
65
- if (this .inputMode == InputMode .MOUSE ) {
83
+ if (this .inputMode == InputMode .MOUSE || isMobileAndClassicMovement ) {
66
84
up = bedrockInput .contains (PlayerAuthInputData .UP );
67
85
down = bedrockInput .contains (PlayerAuthInputData .DOWN );
68
86
left = bedrockInput .contains (PlayerAuthInputData .LEFT );
69
87
right = bedrockInput .contains (PlayerAuthInputData .RIGHT );
88
+
89
+ if (isMobileAndClassicMovement ) {
90
+ // These are the buttons in the corners of the touch area
91
+ if (bedrockInput .contains (PlayerAuthInputData .UP_LEFT )) {
92
+ up = true ;
93
+ left = true ;
94
+ }
95
+
96
+ if (bedrockInput .contains (PlayerAuthInputData .UP_RIGHT )) {
97
+ up = true ;
98
+ right = true ;
99
+ }
100
+
101
+ if (bedrockInput .contains (PlayerAuthInputData .DOWN_LEFT )) {
102
+ down = true ;
103
+ left = true ;
104
+ }
105
+
106
+ if (bedrockInput .contains (PlayerAuthInputData .DOWN_RIGHT )) {
107
+ down = true ;
108
+ right = true ;
109
+ }
110
+ }
70
111
} else {
71
- // The above flags don't fire TODO test console
112
+ // The above flags don't fire
72
113
Vector2f analogMovement = packet .getAnalogMoveVector ();
73
114
up = analogMovement .getY () > 0 ;
74
115
down = analogMovement .getY () < 0 ;
@@ -78,7 +119,6 @@ public void processInputs(SessionPlayerEntity entity, PlayerAuthInputPacket pack
78
119
79
120
boolean sneaking = isSneaking (bedrockInput );
80
121
81
- // TODO when is UP_LEFT, etc. used?
82
122
this .inputPacket = this .inputPacket
83
123
.withForward (up )
84
124
.withBackward (down )
@@ -133,7 +173,7 @@ public boolean lastHorizontalCollision() {
133
173
public boolean isSneaking (Set <PlayerAuthInputData > authInputData ) {
134
174
// Flying doesn't send start / stop fly cases; might as well return early
135
175
if (session .isFlying ()) {
136
- // Of course e.g. mobile handles it differently with a descend case, while
176
+ // Of course e.g. mobile devices handle it differently with a descend case, while
137
177
// e.g. Win10 sends SNEAK_DOWN. Why? We'll never know.
138
178
return authInputData .contains (PlayerAuthInputData .DESCEND ) || authInputData .contains (PlayerAuthInputData .SNEAK_DOWN );
139
179
}
0 commit comments