Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 00:00:41 +01:00
Re-implement steering indicators
Dieser Commit ist enthalten in:
Ursprung
774d3670c5
Commit
9d2d12b87b
@ -39,6 +39,7 @@ import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -182,6 +183,12 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
|
||||
@Override
|
||||
public void tick() {
|
||||
// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
|
||||
if (session.getPlayerEntity().getVehicle() == this) {
|
||||
// For packet timing accuracy, we'll send the packets here, as that's what Java Edition 1.21.3 does.
|
||||
ServerboundPaddleBoatPacket steerPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
|
||||
session.sendDownstreamGamePacket(steerPacket);
|
||||
return;
|
||||
}
|
||||
doTick = !doTick; // Run every 100 ms
|
||||
if (!doTick || passengers.isEmpty()) {
|
||||
return;
|
||||
|
@ -25,13 +25,12 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket;
|
||||
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.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -45,45 +44,32 @@ public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (packet.getAction()) {
|
||||
case SWING_ARM -> {
|
||||
session.armSwingPending();
|
||||
// Delay so entity damage can be processed first
|
||||
session.scheduleInEventLoop(() -> {
|
||||
if (session.getArmAnimationTicks() != 0) {
|
||||
// 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
|
||||
// that right-click that will send a swing.
|
||||
// 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
|
||||
// same tick, notably with high levels of haste applied.
|
||||
// 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.
|
||||
// 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,
|
||||
// and Bedrock 1.19.51.
|
||||
// Note for the future: we should probably largely ignore this packet and instead replicate
|
||||
// all actions on our end, and send swings where needed.
|
||||
session.sendDownstreamGamePacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
||||
session.activateArmAnimationTicking();
|
||||
}
|
||||
},
|
||||
25,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
// These two might need to be flipped, but my recommendation is getting moving working first
|
||||
case ROW_LEFT -> {
|
||||
// Packet value is a float of how long one has been rowing, so we convert that into a boolean
|
||||
session.setSteeringLeft(packet.getRowingTime() > 0.0);
|
||||
ServerboundPaddleBoatPacket steerLeftPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
|
||||
session.sendDownstreamGamePacket(steerLeftPacket);
|
||||
}
|
||||
case ROW_RIGHT -> {
|
||||
session.setSteeringRight(packet.getRowingTime() > 0.0);
|
||||
ServerboundPaddleBoatPacket steerRightPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
|
||||
session.sendDownstreamGamePacket(steerRightPacket);
|
||||
}
|
||||
System.out.println("wewewewewewewewewewewe");
|
||||
if (packet.getAction() == AnimatePacket.Action.SWING_ARM) {
|
||||
session.armSwingPending();
|
||||
// Delay so entity damage can be processed first
|
||||
session.scheduleInEventLoop(() -> {
|
||||
if (session.getArmAnimationTicks() != 0) {
|
||||
// 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
|
||||
// that right-click that will send a swing.
|
||||
// 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
|
||||
// same tick, notably with high levels of haste applied.
|
||||
// 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.
|
||||
// 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,
|
||||
// and Bedrock 1.19.51.
|
||||
// Note for the future: we should probably largely ignore this packet and instead replicate
|
||||
// all actions on our end, and send swings where needed.
|
||||
session.sendDownstreamGamePacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
||||
session.activateArmAnimationTicking();
|
||||
}
|
||||
},
|
||||
25,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,83 +78,86 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
BedrockMovePlayerTranslator.translate(session, packet);
|
||||
|
||||
Set<PlayerAuthInputData> inputData = packet.getInputData();
|
||||
if (!inputData.isEmpty()) {
|
||||
for (PlayerAuthInputData input : inputData) {
|
||||
switch (input) {
|
||||
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
|
||||
case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions());
|
||||
case START_SNEAKING -> {
|
||||
ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
|
||||
session.sendDownstreamGamePacket(startSneakPacket);
|
||||
for (PlayerAuthInputData input : inputData) {
|
||||
switch (input) {
|
||||
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
|
||||
case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions());
|
||||
case START_SNEAKING -> {
|
||||
ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
|
||||
session.sendDownstreamGamePacket(startSneakPacket);
|
||||
|
||||
session.startSneaking();
|
||||
}
|
||||
case STOP_SNEAKING -> {
|
||||
ServerboundPlayerCommandPacket stopSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SNEAKING);
|
||||
session.sendDownstreamGamePacket(stopSneakPacket);
|
||||
|
||||
session.stopSneaking();
|
||||
}
|
||||
case START_SPRINTING -> {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
|
||||
session.sendDownstreamGamePacket(startSprintPacket);
|
||||
session.setSprinting(true);
|
||||
}
|
||||
}
|
||||
case STOP_SPRINTING -> {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
|
||||
session.sendDownstreamGamePacket(stopSprintPacket);
|
||||
}
|
||||
session.setSprinting(false);
|
||||
}
|
||||
case START_SWIMMING -> session.setSwimming(true);
|
||||
case STOP_SWIMMING -> session.setSwimming(false);
|
||||
case START_FLYING -> { // Since 1.20.30
|
||||
if (session.isCanFly()) {
|
||||
if (session.getGameMode() == GameMode.SPECTATOR) {
|
||||
// should already be flying
|
||||
session.sendAdventureSettings();
|
||||
break;
|
||||
}
|
||||
|
||||
if (session.getPlayerEntity().getFlag(EntityFlag.SWIMMING) && session.getCollisionManager().isPlayerInWater()) {
|
||||
// As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling
|
||||
// If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE
|
||||
session.sendAdventureSettings();
|
||||
break;
|
||||
}
|
||||
|
||||
session.setFlying(true);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(true));
|
||||
} else {
|
||||
// update whether we can fly
|
||||
session.sendAdventureSettings();
|
||||
// stop flying
|
||||
PlayerActionPacket stopFlyingPacket = new PlayerActionPacket();
|
||||
stopFlyingPacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId());
|
||||
stopFlyingPacket.setAction(PlayerActionType.STOP_FLYING);
|
||||
stopFlyingPacket.setBlockPosition(Vector3i.ZERO);
|
||||
stopFlyingPacket.setResultPosition(Vector3i.ZERO);
|
||||
stopFlyingPacket.setFace(0);
|
||||
session.sendUpstreamPacket(stopFlyingPacket);
|
||||
}
|
||||
}
|
||||
case STOP_FLYING -> {
|
||||
session.setFlying(false);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(false));
|
||||
}
|
||||
case START_GLIDING -> {
|
||||
// Otherwise gliding will not work in creative
|
||||
ServerboundPlayerAbilitiesPacket playerAbilitiesPacket = new ServerboundPlayerAbilitiesPacket(false);
|
||||
session.sendDownstreamGamePacket(playerAbilitiesPacket);
|
||||
sendPlayerGlideToggle(session, entity);
|
||||
}
|
||||
case STOP_GLIDING -> sendPlayerGlideToggle(session, entity);
|
||||
session.startSneaking();
|
||||
}
|
||||
case STOP_SNEAKING -> {
|
||||
ServerboundPlayerCommandPacket stopSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SNEAKING);
|
||||
session.sendDownstreamGamePacket(stopSneakPacket);
|
||||
|
||||
session.stopSneaking();
|
||||
}
|
||||
case START_SPRINTING -> {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
|
||||
session.sendDownstreamGamePacket(startSprintPacket);
|
||||
session.setSprinting(true);
|
||||
}
|
||||
}
|
||||
case STOP_SPRINTING -> {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
|
||||
session.sendDownstreamGamePacket(stopSprintPacket);
|
||||
}
|
||||
session.setSprinting(false);
|
||||
}
|
||||
case START_SWIMMING -> session.setSwimming(true);
|
||||
case STOP_SWIMMING -> session.setSwimming(false);
|
||||
case START_FLYING -> { // Since 1.20.30
|
||||
if (session.isCanFly()) {
|
||||
if (session.getGameMode() == GameMode.SPECTATOR) {
|
||||
// should already be flying
|
||||
session.sendAdventureSettings();
|
||||
break;
|
||||
}
|
||||
|
||||
if (session.getPlayerEntity().getFlag(EntityFlag.SWIMMING) && session.getCollisionManager().isPlayerInWater()) {
|
||||
// As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling
|
||||
// If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE
|
||||
session.sendAdventureSettings();
|
||||
break;
|
||||
}
|
||||
|
||||
session.setFlying(true);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(true));
|
||||
} else {
|
||||
// update whether we can fly
|
||||
session.sendAdventureSettings();
|
||||
// stop flying
|
||||
PlayerActionPacket stopFlyingPacket = new PlayerActionPacket();
|
||||
stopFlyingPacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId());
|
||||
stopFlyingPacket.setAction(PlayerActionType.STOP_FLYING);
|
||||
stopFlyingPacket.setBlockPosition(Vector3i.ZERO);
|
||||
stopFlyingPacket.setResultPosition(Vector3i.ZERO);
|
||||
stopFlyingPacket.setFace(0);
|
||||
session.sendUpstreamPacket(stopFlyingPacket);
|
||||
}
|
||||
}
|
||||
case STOP_FLYING -> {
|
||||
session.setFlying(false);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(false));
|
||||
}
|
||||
case START_GLIDING -> {
|
||||
// Otherwise gliding will not work in creative
|
||||
ServerboundPlayerAbilitiesPacket playerAbilitiesPacket = new ServerboundPlayerAbilitiesPacket(false);
|
||||
session.sendDownstreamGamePacket(playerAbilitiesPacket);
|
||||
sendPlayerGlideToggle(session, entity);
|
||||
}
|
||||
case STOP_GLIDING -> sendPlayerGlideToggle(session, entity);
|
||||
}
|
||||
}
|
||||
boolean up = inputData.contains(PlayerAuthInputData.UP);
|
||||
// Yes. These are flipped. It's always been an issue with Geyser. That's what it's like working with this codebase.
|
||||
// Hi random stranger. I am six days into updating for 1.21.3. How's it going?
|
||||
session.setSteeringLeft(up || inputData.contains(PlayerAuthInputData.PADDLE_RIGHT));
|
||||
session.setSteeringRight(up || inputData.contains(PlayerAuthInputData.PADDLE_LEFT));
|
||||
}
|
||||
|
||||
private static void sendPlayerGlideToggle(GeyserSession session, Entity entity) {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren