3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-27 08:30:12 +01:00

Fix forced zoom issue when switching into spectator mode (#4093)

* init: spectator mode support

* properly set second abilitylayer for spectator mode

* Fixes https://github.com/GeyserMC/Geyser/issues/3318 by not sending changed flags in spectator mode
Dieser Commit ist enthalten in:
chris 2023-09-07 00:13:19 +02:00 committet von GitHub
Ursprung 54bb1f3d13
Commit 3ec591509c
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
7 geänderte Dateien mit 60 neuen und 22 gelöschten Zeilen

Datei anzeigen

@ -249,7 +249,7 @@ public class ArmorStandEntity extends LivingEntity {
@Override @Override
public InteractionResult interactAt(Hand hand) { public InteractionResult interactAt(Hand hand) {
if (!isMarker && session.getPlayerInventory().getItemInHand(hand).asItem() != Items.NAME_TAG) { if (!isMarker && session.getPlayerInventory().getItemInHand(hand).asItem() != Items.NAME_TAG) {
// Java Edition returns SUCCESS if in spectator mode, but this is overrided with an earlier check on the client // Java Edition returns SUCCESS if in spectator mode, but this is overridden with an earlier check on the client
return InteractionResult.CONSUME; return InteractionResult.CONSUME;
} else { } else {
return InteractionResult.PASS; return InteractionResult.PASS;

Datei anzeigen

@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeTyp
import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter; import lombok.Getter;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
@ -109,10 +110,17 @@ public class SessionPlayerEntity extends PlayerEntity {
this.position = position; this.position = position;
} }
/**
* Sending any updated flags (sprinting, onFire, etc.) to the client while in spectator is not needed
* Also "fixes" https://github.com/GeyserMC/Geyser/issues/3318
*/
@Override @Override
public void setFlags(ByteEntityMetadata entityMetadata) { public void setFlags(ByteEntityMetadata entityMetadata) {
// TODO: proper fix, BDS somehow does it? https://paste.gg/p/anonymous/3adfb7612f1540be80fa03a2281f93dc (BDS 1.20.13)
if (!this.session.getGameMode().equals(GameMode.SPECTATOR)) {
super.setFlags(entityMetadata); super.setFlags(entityMetadata);
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING)); session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
}
refreshSpeed = true; refreshSpeed = true;
} }

Datei anzeigen

@ -98,20 +98,20 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean;
import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode; import org.geysermc.api.util.InputMode;
import org.geysermc.api.util.UiProfile; import org.geysermc.api.util.UiProfile;
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.cumulus.form.util.FormBuilder;
import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.util.BedrockData; import org.geysermc.floodgate.util.BedrockData;
import org.geysermc.geyser.Constants; import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent;
import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.configuration.GeyserConfiguration;
@ -131,7 +131,6 @@ import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.BlockMappings;
@ -147,6 +146,7 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils; import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -1516,11 +1516,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
StartGamePacket startGamePacket = new StartGamePacket(); StartGamePacket startGamePacket = new StartGamePacket();
startGamePacket.setUniqueEntityId(playerEntity.getGeyserId()); startGamePacket.setUniqueEntityId(playerEntity.getGeyserId());
startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId()); startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId());
startGamePacket.setPlayerGameType(switch (gameMode) { startGamePacket.setPlayerGameType(EntityUtils.toBedrockGamemode(gameMode));
case CREATIVE -> GameType.CREATIVE;
case ADVENTURE -> GameType.ADVENTURE;
default -> GameType.SURVIVAL;
});
startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0)); startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0));
startGamePacket.setRotation(Vector2f.from(1, 1)); startGamePacket.setRotation(Vector2f.from(1, 1));
@ -1756,7 +1752,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
AbilityLayer abilityLayer = new AbilityLayer(); AbilityLayer abilityLayer = new AbilityLayer();
Set<Ability> abilities = abilityLayer.getAbilityValues(); Set<Ability> abilities = abilityLayer.getAbilityValues();
if (canFly || spectator) { if (canFly) {
abilities.add(Ability.MAY_FLY); abilities.add(Ability.MAY_FLY);
} }
@ -1790,15 +1786,31 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
} }
if (spectator) { if (spectator) {
abilities.add(Ability.NO_CLIP); AbilityLayer spectatorLayer = new AbilityLayer();
spectatorLayer.setLayerType(AbilityLayer.Type.SPECTATOR);
// Setting all abilitySet causes the zoom issue... BDS only sends these, so ig we will too
Set<Ability> abilitySet = spectatorLayer.getAbilitiesSet();
abilitySet.add(Ability.BUILD);
abilitySet.add(Ability.MINE);
abilitySet.add(Ability.DOORS_AND_SWITCHES);
abilitySet.add(Ability.OPEN_CONTAINERS);
abilitySet.add(Ability.ATTACK_PLAYERS);
abilitySet.add(Ability.ATTACK_MOBS);
abilitySet.add(Ability.INVULNERABLE);
abilitySet.add(Ability.FLYING);
abilitySet.add(Ability.MAY_FLY);
abilitySet.add(Ability.INSTABUILD);
abilitySet.add(Ability.NO_CLIP);
Set<Ability> abilityValues = spectatorLayer.getAbilityValues();
abilityValues.add(Ability.INVULNERABLE);
abilityValues.add(Ability.FLYING);
abilityValues.add(Ability.NO_CLIP);
updateAbilitiesPacket.getAbilityLayers().add(spectatorLayer);
} }
// https://github.com/GeyserMC/Geyser/issues/3769 Setting Spectator mode ability layer
if (spectator) {
abilityLayer.setLayerType(AbilityLayer.Type.SPECTATOR);
} else {
abilityLayer.setLayerType(AbilityLayer.Type.BASE); abilityLayer.setLayerType(AbilityLayer.Type.BASE);
}
abilityLayer.setFlySpeed(flySpeed); abilityLayer.setFlySpeed(flySpeed);
// https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10 // https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10
abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed); abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed);

Datei anzeigen

@ -45,6 +45,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.JavaCodecUtil; import org.geysermc.geyser.util.JavaCodecUtil;
import org.geysermc.geyser.util.PluginMessageUtils; import org.geysermc.geyser.util.PluginMessageUtils;
@ -113,7 +114,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
if (!needsSpawnPacket) { if (!needsSpawnPacket) {
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(packet.getGameMode().ordinal()); playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(packet.getGameMode()).ordinal());
session.sendUpstreamPacket(playerGameTypePacket); session.sendUpstreamPacket(playerGameTypePacket);
} }

Datei anzeigen

@ -38,6 +38,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
@Translator(packet = ClientboundRespawnPacket.class) @Translator(packet = ClientboundRespawnPacket.class)
public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPacket> { public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPacket> {
@ -59,7 +60,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
entity.updateBedrockMetadata(); entity.updateBedrockMetadata();
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(packet.getGamemode()).ordinal());
session.sendUpstreamPacket(playerGameTypePacket); session.sendUpstreamPacket(playerGameTypePacket);
session.setGameMode(packet.getGamemode()); session.setGameMode(packet.getGamemode());

Datei anzeigen

@ -44,6 +44,7 @@ import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator; import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
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.geyser.util.EntityUtils;
@Translator(packet = ClientboundGameEventPacket.class) @Translator(packet = ClientboundGameEventPacket.class)
public class JavaGameEventTranslator extends PacketTranslator<ClientboundGameEventPacket> { public class JavaGameEventTranslator extends PacketTranslator<ClientboundGameEventPacket> {
@ -105,7 +106,7 @@ public class JavaGameEventTranslator extends PacketTranslator<ClientboundGameEve
GameMode gameMode = (GameMode) packet.getValue(); GameMode gameMode = (GameMode) packet.getValue();
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(gameMode.ordinal()); playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(gameMode).ordinal());
session.sendUpstreamPacket(playerGameTypePacket); session.sendUpstreamPacket(playerGameTypePacket);
session.setGameMode(gameMode); session.setGameMode(gameMode);

Datei anzeigen

@ -26,9 +26,11 @@
package org.geysermc.geyser.util; package org.geysermc.geyser.util;
import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.GameType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
@ -260,6 +262,19 @@ public final class EntityUtils {
return InteractionResult.PASS; return InteractionResult.PASS;
} }
/**
* Convert Java GameMode to Bedrock GameType
* Needed to account for ordinal differences (spectator is 3 in Java, 6 in Bedrock)
*/
public static GameType toBedrockGamemode(GameMode gamemode) {
return switch (gamemode) {
case CREATIVE -> GameType.CREATIVE;
case ADVENTURE -> GameType.ADVENTURE;
case SPECTATOR -> GameType.SPECTATOR;
default -> GameType.SURVIVAL;
};
}
private EntityUtils() { private EntityUtils() {
} }
} }