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.geyser.util.InteractiveTag;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
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.data.game.entity.player.Hand;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -182,6 +183,12 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
|
|||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
|
// 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
|
doTick = !doTick; // Run every 100 ms
|
||||||
if (!doTick || passengers.isEmpty()) {
|
if (!doTick || passengers.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -25,13 +25,12 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
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.cloudburstmc.protocol.bedrock.packet.AnimatePacket;
|
||||||
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;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
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;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -45,45 +44,32 @@ public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (packet.getAction()) {
|
System.out.println("wewewewewewewewewewewe");
|
||||||
case SWING_ARM -> {
|
if (packet.getAction() == AnimatePacket.Action.SWING_ARM) {
|
||||||
session.armSwingPending();
|
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.sendDownstreamGamePacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
session.sendDownstreamGamePacket(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
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,83 +78,86 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
|||||||
BedrockMovePlayerTranslator.translate(session, packet);
|
BedrockMovePlayerTranslator.translate(session, packet);
|
||||||
|
|
||||||
Set<PlayerAuthInputData> inputData = packet.getInputData();
|
Set<PlayerAuthInputData> inputData = packet.getInputData();
|
||||||
if (!inputData.isEmpty()) {
|
for (PlayerAuthInputData input : inputData) {
|
||||||
for (PlayerAuthInputData input : inputData) {
|
switch (input) {
|
||||||
switch (input) {
|
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
|
||||||
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
|
case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions());
|
||||||
case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions());
|
case START_SNEAKING -> {
|
||||||
case START_SNEAKING -> {
|
ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
|
||||||
ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
|
session.sendDownstreamGamePacket(startSneakPacket);
|
||||||
session.sendDownstreamGamePacket(startSneakPacket);
|
|
||||||
|
|
||||||
session.startSneaking();
|
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);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
private static void sendPlayerGlideToggle(GeyserSession session, Entity entity) {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren