mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Feature: Add API to show/hide GUI elements (#4705)
* Add API to show/hide GUI elements * Bump version to 2.3.2 --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com>
This commit is contained in:
parent
aaad10b8c9
commit
0ca42308eb
5 changed files with 203 additions and 9 deletions
|
@ -145,4 +145,36 @@ 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* If no elements are specified, this will reset all currently hidden elements
|
||||||
|
*
|
||||||
|
* @param element the {@link GuiElement} to reset
|
||||||
|
*/
|
||||||
|
void resetElement(@NonNull GuiElement @Nullable... element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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}s.
|
||||||
|
*
|
||||||
|
* @return an unmodifiable view of all currently hidden {@link GuiElement}s
|
||||||
|
*/
|
||||||
|
@NonNull Set<GuiElement> hiddenElements();
|
||||||
}
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent GUI elements on the players HUD display.
|
||||||
|
* These can be hidden using {@link CameraData#hideElement(GuiElement...)},
|
||||||
|
* and one can reset their visibility using {@link CameraData#resetElement(GuiElement...)}.
|
||||||
|
*/
|
||||||
|
public class GuiElement {
|
||||||
|
public static final GuiElement PAPER_DOLL = new GuiElement(0);
|
||||||
|
public static final GuiElement ARMOR = new GuiElement(1);
|
||||||
|
public static final GuiElement TOOL_TIPS = new GuiElement(2);
|
||||||
|
public static final GuiElement TOUCH_CONTROLS = new GuiElement(3);
|
||||||
|
public static final GuiElement CROSSHAIR = new GuiElement(4);
|
||||||
|
public static final GuiElement HOTBAR = new GuiElement(5);
|
||||||
|
public static final GuiElement HEALTH = new GuiElement(6);
|
||||||
|
public static final GuiElement PROGRESS_BAR = new GuiElement(7);
|
||||||
|
public static final GuiElement FOOD_BAR = new GuiElement(8);
|
||||||
|
public static final GuiElement AIR_BUBBLES_BAR = new GuiElement(9);
|
||||||
|
public static final GuiElement VEHICLE_HEALTH = new GuiElement(10);
|
||||||
|
public static final GuiElement EFFECTS_BAR = new GuiElement(11);
|
||||||
|
public static final GuiElement ITEM_TEXT_POPUP = new GuiElement(12);
|
||||||
|
|
||||||
|
private GuiElement(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal use only; don't depend on these values being consistent.
|
||||||
|
*/
|
||||||
|
public int id() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,24 +32,50 @@ 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 org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||||
|
|
||||||
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 {
|
||||||
|
private static final HudElement[] HUD_ELEMENT_VALUES = HudElement.values();
|
||||||
|
private static final Set<HudElement> ALL_HUD_ELEMENTS = Set.of(HUD_ELEMENT_VALUES);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of elements to hide when the player is in spectator mode.
|
||||||
|
* Helps with tidying up the GUI; Java-style.
|
||||||
|
*/
|
||||||
|
private static final GuiElement[] SPECTATOR_HIDDEN_ELEMENTS = {
|
||||||
|
GuiElement.AIR_BUBBLES_BAR,
|
||||||
|
GuiElement.ARMOR,
|
||||||
|
GuiElement.HEALTH,
|
||||||
|
GuiElement.FOOD_BAR,
|
||||||
|
GuiElement.PROGRESS_BAR,
|
||||||
|
GuiElement.TOOL_TIPS
|
||||||
|
};
|
||||||
|
|
||||||
private final GeyserSession session;
|
private final GeyserSession session;
|
||||||
|
|
||||||
@Getter
|
|
||||||
private CameraPerspective cameraPerspective;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All fog effects that are currently applied to the client.
|
* All fog effects that are currently applied to the client.
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +83,14 @@ 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<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private CameraPerspective cameraPerspective;
|
||||||
|
|
||||||
public GeyserCameraData(GeyserSession session) {
|
public GeyserCameraData(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
@ -223,4 +257,67 @@ public class GeyserCameraData implements CameraData {
|
||||||
public boolean isCameraLocked() {
|
public boolean isCameraLocked() {
|
||||||
return !this.cameraLockOwners.isEmpty();
|
return !this.cameraLockOwners.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideElement(GuiElement... elements) {
|
||||||
|
Objects.requireNonNull(elements);
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.HIDE);
|
||||||
|
Set<HudElement> elementSet = packet.getElements();
|
||||||
|
|
||||||
|
for (GuiElement element : elements) {
|
||||||
|
this.hiddenHudElements.add(element);
|
||||||
|
elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetElement(GuiElement... elements) {
|
||||||
|
SetHudPacket packet = new SetHudPacket();
|
||||||
|
packet.setVisibility(HudVisibility.RESET);
|
||||||
|
Set<HudElement> elementSet = packet.getElements();
|
||||||
|
|
||||||
|
if (elements != null && elements.length != 0) {
|
||||||
|
for (GuiElement element : elements) {
|
||||||
|
this.hiddenHudElements.remove(element);
|
||||||
|
elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.hiddenHudElements.clear();
|
||||||
|
elementSet.addAll(ALL_HUD_ELEMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Collections.unmodifiableSet(hiddenHudElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals with hiding hud elements while in spectator.
|
||||||
|
*
|
||||||
|
* @param currentlySpectator whether the player is currently in spectator mode
|
||||||
|
* @param newGameMode the new GameMode to switch to
|
||||||
|
*/
|
||||||
|
public void handleGameModeChange(boolean currentlySpectator, GameMode newGameMode) {
|
||||||
|
if (newGameMode == GameMode.SPECTATOR) {
|
||||||
|
if (!currentlySpectator) {
|
||||||
|
hideElement(SPECTATOR_HIDDEN_ELEMENTS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentlySpectator) {
|
||||||
|
resetElement(SPECTATOR_HIDDEN_ELEMENTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -284,7 +284,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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1302,6 +1301,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGameMode(GameMode newGamemode) {
|
||||||
|
boolean currentlySpectator = this.gameMode == GameMode.SPECTATOR;
|
||||||
|
this.gameMode = newGamemode;
|
||||||
|
this.cameraData.handleGameModeChange(currentlySpectator, newGamemode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display
|
* Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display
|
||||||
* blocking and sends a packet to the Java server.
|
* blocking and sends a packet to the Java server.
|
||||||
|
|
|
@ -7,5 +7,5 @@ org.gradle.vfs.watch=false
|
||||||
|
|
||||||
group=org.geysermc
|
group=org.geysermc
|
||||||
id=geyser
|
id=geyser
|
||||||
version=2.3.1-SNAPSHOT
|
version=2.3.2-SNAPSHOT
|
||||||
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.
|
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.
|
||||||
|
|
Loading…
Reference in a new issue