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:
Ursprung
54bb1f3d13
Commit
3ec591509c
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren