mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Add API to show/hide GUI elements
We can also use this for a nicer looking spectator mode GUI :)
This commit is contained in:
parent
0fcf0f9b4f
commit
a910733c91
4 changed files with 200 additions and 3 deletions
|
|
@ -145,4 +145,50 @@ public interface CameraData {
|
||||||
* @return whether the camera is currently locked
|
* @return whether the camera is currently locked
|
||||||
*/
|
*/
|
||||||
boolean isCameraLocked();
|
boolean isCameraLocked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides a {@link GuiElement} on the client's side.
|
||||||
|
*
|
||||||
|
* @param element the {@link GuiElement} to hide
|
||||||
|
*/
|
||||||
|
void hideElement(@NonNull GuiElement element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides a set of {@link GuiElement}'s on the client's side.
|
||||||
|
*
|
||||||
|
* @param elements the {@link Set<GuiElement>} to hide
|
||||||
|
*/
|
||||||
|
void hideElements(@NonNull Set<GuiElement> elements);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets a {@link GuiElement} on the client's side.
|
||||||
|
* This makes the client decide on its own - e.g. based on client settings -
|
||||||
|
* whether to show or hide the gui element.
|
||||||
|
*
|
||||||
|
* @param element the {@link GuiElement} to reset
|
||||||
|
*/
|
||||||
|
void resetElement(@NonNull GuiElement element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets a set of {@link GuiElement} on the client's side.
|
||||||
|
* This makes the client decide on its own - e.g. based on client settings -
|
||||||
|
* whether to show or hide the gui elements.
|
||||||
|
*
|
||||||
|
* @param elements the {@link Set<GuiElement>} to reset
|
||||||
|
*/
|
||||||
|
void resetElements(@NonNull Set<GuiElement> elements);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether a {@link GuiElement} is currently hidden.
|
||||||
|
*
|
||||||
|
* @param element the {@link GuiElement} to check
|
||||||
|
*/
|
||||||
|
boolean isHudElementHidden(@NonNull GuiElement element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently hidden {@link GuiElement}.
|
||||||
|
*
|
||||||
|
* @return an immutable set of all currently hidden {@link GuiElement}s
|
||||||
|
*/
|
||||||
|
@NonNull Set<GuiElement> hiddenElements();
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.api.bedrock.camera;
|
||||||
|
|
||||||
|
public enum GuiElement {
|
||||||
|
PAPER_DOLL,
|
||||||
|
ARMOR,
|
||||||
|
TOOL_TIPS,
|
||||||
|
TOUCH_CONTROLS,
|
||||||
|
CROSSHAIR,
|
||||||
|
HOTBAR,
|
||||||
|
HEALTH,
|
||||||
|
PROGRESS_BAR,
|
||||||
|
FOOD_BAR,
|
||||||
|
AIR_BUBBLES_BAR,
|
||||||
|
VEHICLE_HEALTH,
|
||||||
|
EFFECTS_BAR,
|
||||||
|
ITEM_TEXT_POPUP
|
||||||
|
}
|
||||||
|
|
@ -32,16 +32,29 @@ import org.cloudburstmc.math.vector.Vector2f;
|
||||||
import org.cloudburstmc.math.vector.Vector3f;
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
|
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
|
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.HudElement;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.HudVisibility;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase;
|
import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction;
|
import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
|
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
|
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
|
||||||
import org.geysermc.geyser.api.bedrock.camera.*;
|
import org.cloudburstmc.protocol.bedrock.packet.SetHudPacket;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraData;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraEaseType;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraFade;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraPosition;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.GuiElement;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class GeyserCameraData implements CameraData {
|
public class GeyserCameraData implements CameraData {
|
||||||
|
|
||||||
|
|
@ -57,6 +70,11 @@ public class GeyserCameraData implements CameraData {
|
||||||
|
|
||||||
private final Set<UUID> cameraLockOwners = new HashSet<>();
|
private final Set<UUID> cameraLockOwners = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All currently hidden HUD elements
|
||||||
|
*/
|
||||||
|
private final Set<GuiElement> hiddenHudElements = new HashSet<>();
|
||||||
|
|
||||||
public GeyserCameraData(GeyserSession session) {
|
public GeyserCameraData(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
@ -223,4 +241,66 @@ public class GeyserCameraData implements CameraData {
|
||||||
public boolean isCameraLocked() {
|
public boolean isCameraLocked() {
|
||||||
return !this.cameraLockOwners.isEmpty();
|
return !this.cameraLockOwners.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideElement(@NonNull GuiElement element) {
|
||||||
|
Objects.requireNonNull(element);
|
||||||
|
this.hiddenHudElements.add(element);
|
||||||
|
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.HIDE);
|
||||||
|
packet.getElements().add(HudElement.values()[element.ordinal()]);
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideElements(@NonNull Set<GuiElement> elements) {
|
||||||
|
Objects.requireNonNull(elements);
|
||||||
|
this.hiddenHudElements.removeAll(elements);
|
||||||
|
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.HIDE);
|
||||||
|
Set<HudElement> elementSet = packet.getElements();
|
||||||
|
elements.forEach((element) -> elementSet.add(HudElement.values()[element.ordinal()]));
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetElement(@NonNull GuiElement element) {
|
||||||
|
Objects.requireNonNull(element);
|
||||||
|
this.hiddenHudElements.remove(element);
|
||||||
|
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.RESET);
|
||||||
|
packet.getElements().add(HudElement.values()[element.ordinal()]);
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetElements(@NonNull Set<GuiElement> elements) {
|
||||||
|
Objects.requireNonNull(elements);
|
||||||
|
this.hiddenHudElements.removeAll(elements);
|
||||||
|
|
||||||
|
// This is unfortunate, but resetting multiple elements doesn't work otherwise
|
||||||
|
if (!hiddenHudElements.isEmpty()) {
|
||||||
|
elements.forEach(this::resetElement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.RESET);
|
||||||
|
packet.getElements().addAll(Set.of(HudElement.values()));
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHudElementHidden(@NonNull GuiElement element) {
|
||||||
|
Objects.requireNonNull(element);
|
||||||
|
return this.hiddenHudElements.contains(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Set<GuiElement> hiddenElements() {
|
||||||
|
return Set.copyOf(hiddenHudElements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.session;
|
||||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||||
import com.github.steveice10.mc.auth.exception.request.RequestException;
|
import com.github.steveice10.mc.auth.exception.request.RequestException;
|
||||||
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
||||||
|
import org.geysermc.geyser.api.bedrock.camera.GuiElement;
|
||||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||||
|
|
@ -288,7 +289,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
*/
|
*/
|
||||||
private volatile boolean closed;
|
private volatile boolean closed;
|
||||||
|
|
||||||
@Setter
|
|
||||||
private GameMode gameMode = GameMode.SURVIVAL;
|
private GameMode gameMode = GameMode.SURVIVAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -581,6 +581,19 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
|
|
||||||
private MinecraftProtocol protocol;
|
private MinecraftProtocol protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of elements to hide when the player is in spectator mode.
|
||||||
|
* Helps with tidying up the GUI; Java-style.
|
||||||
|
*/
|
||||||
|
private static final Set<GuiElement> SPECTATOR_HUD = Set.of(
|
||||||
|
GuiElement.AIR_BUBBLES_BAR,
|
||||||
|
GuiElement.ARMOR,
|
||||||
|
GuiElement.HEALTH,
|
||||||
|
GuiElement.FOOD_BAR,
|
||||||
|
GuiElement.PROGRESS_BAR,
|
||||||
|
GuiElement.TOOL_TIPS
|
||||||
|
);
|
||||||
|
|
||||||
public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) {
|
public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) {
|
||||||
this.geyser = geyser;
|
this.geyser = geyser;
|
||||||
this.upstream = new UpstreamSession(bedrockServerSession);
|
this.upstream = new UpstreamSession(bedrockServerSession);
|
||||||
|
|
@ -1321,6 +1334,22 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGameMode(GameMode newGamemode) {
|
||||||
|
boolean currentlySpectator = gameMode == GameMode.SPECTATOR;
|
||||||
|
this.gameMode = newGamemode;
|
||||||
|
|
||||||
|
// Hide/Unhide GUI elements as needed
|
||||||
|
if (newGamemode == GameMode.SPECTATOR) {
|
||||||
|
if (!currentlySpectator) {
|
||||||
|
this.cameraData.hideElements(SPECTATOR_HUD);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentlySpectator) {
|
||||||
|
this.cameraData.resetElements(SPECTATOR_HUD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjusts speed if the player is crawling.
|
* Adjusts speed if the player is crawling.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue