Skip to content

Commit

Permalink
Fix forced zoom issue when switching into spectator mode (#4093)
Browse files Browse the repository at this point in the history
* init: spectator mode support

* properly set second abilitylayer for spectator mode

* Fixes #3318 by not sending changed flags in spectator mode
  • Loading branch information
onebeastchris authored Sep 6, 2023
1 parent 54bb1f3 commit 3ec5915
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ protected void setInvisible(boolean value) {
@Override
public InteractionResult interactAt(Hand hand) {
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;
} else {
return InteractionResult.PASS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import org.cloudburstmc.math.vector.Vector3f;
Expand Down Expand Up @@ -109,10 +110,17 @@ public void setPositionManual(Vector3f 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
public void setFlags(ByteEntityMetadata entityMetadata) {
super.setFlags(entityMetadata);
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
// 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);
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
}
refreshSpeed = true;
}

Expand Down
44 changes: 28 additions & 16 deletions core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,20 @@
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode;
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.util.FormBuilder;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.util.BedrockData;
import org.geysermc.geyser.Constants;
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.entity.type.GeyserEntity;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
import org.geysermc.geyser.configuration.GeyserConfiguration;
Expand All @@ -131,7 +131,6 @@
import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings;
Expand All @@ -147,6 +146,7 @@
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -1516,11 +1516,7 @@ private void startGame() {
StartGamePacket startGamePacket = new StartGamePacket();
startGamePacket.setUniqueEntityId(playerEntity.getGeyserId());
startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId());
startGamePacket.setPlayerGameType(switch (gameMode) {
case CREATIVE -> GameType.CREATIVE;
case ADVENTURE -> GameType.ADVENTURE;
default -> GameType.SURVIVAL;
});
startGamePacket.setPlayerGameType(EntityUtils.toBedrockGamemode(gameMode));
startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0));
startGamePacket.setRotation(Vector2f.from(1, 1));

Expand Down Expand Up @@ -1756,7 +1752,7 @@ public void sendAdventureSettings() {

AbilityLayer abilityLayer = new AbilityLayer();
Set<Ability> abilities = abilityLayer.getAbilityValues();
if (canFly || spectator) {
if (canFly) {
abilities.add(Ability.MAY_FLY);
}

Expand Down Expand Up @@ -1790,15 +1786,31 @@ public void sendAdventureSettings() {
}

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);
// https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10
abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.JavaCodecUtil;
import org.geysermc.geyser.util.PluginMessageUtils;

Expand Down Expand Up @@ -113,7 +114,7 @@ public void translate(GeyserSession session, ClientboundLoginPacket packet) {

if (!needsSpawnPacket) {
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(packet.getGameMode().ordinal());
playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(packet.getGameMode()).ordinal());
session.sendUpstreamPacket(playerGameTypePacket);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;

@Translator(packet = ClientboundRespawnPacket.class)
public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPacket> {
Expand All @@ -59,7 +60,7 @@ public void translate(GeyserSession session, ClientboundRespawnPacket packet) {
entity.updateBedrockMetadata();

SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(packet.getGamemode().ordinal());
playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(packet.getGamemode()).ordinal());
session.sendUpstreamPacket(playerGameTypePacket);
session.setGameMode(packet.getGamemode());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.EntityUtils;

@Translator(packet = ClientboundGameEventPacket.class)
public class JavaGameEventTranslator extends PacketTranslator<ClientboundGameEventPacket> {
Expand Down Expand Up @@ -105,7 +106,7 @@ public void translate(GeyserSession session, ClientboundGameEventPacket packet)
GameMode gameMode = (GameMode) packet.getValue();

SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
playerGameTypePacket.setGamemode(gameMode.ordinal());
playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(gameMode).ordinal());
session.sendUpstreamPacket(playerGameTypePacket);
session.setGameMode(gameMode);

Expand Down
15 changes: 15 additions & 0 deletions core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
package org.geysermc.geyser.util;

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.type.EntityType;
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.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinitions;
Expand Down Expand Up @@ -260,6 +262,19 @@ public static InteractionResult attemptToSaddle(Entity entityToSaddle, GeyserIte
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() {
}
}

0 comments on commit 3ec5915

Please sign in to comment.