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
|
||||
*/
|
||||
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.protocol.bedrock.data.CameraShakeAction;
|
||||
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.CameraFadeInstruction;
|
||||
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
|
||||
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 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 {
|
||||
|
||||
|
|
@ -57,6 +70,11 @@ public class GeyserCameraData implements CameraData {
|
|||
|
||||
private final Set<UUID> cameraLockOwners = new HashSet<>();
|
||||
|
||||
/**
|
||||
* All currently hidden HUD elements
|
||||
*/
|
||||
private final Set<GuiElement> hiddenHudElements = new HashSet<>();
|
||||
|
||||
public GeyserCameraData(GeyserSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
|
@ -223,4 +241,66 @@ public class GeyserCameraData implements CameraData {
|
|||
public boolean isCameraLocked() {
|
||||
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.exception.request.RequestException;
|
||||
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.MinecraftProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
|
|
@ -288,7 +289,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
*/
|
||||
private volatile boolean closed;
|
||||
|
||||
@Setter
|
||||
private GameMode gameMode = GameMode.SURVIVAL;
|
||||
|
||||
/**
|
||||
|
|
@ -581,6 +581,19 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
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) {
|
||||
this.geyser = geyser;
|
||||
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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue