Add client setting for cooldown type, refactor show-coordinates (#2193)

This commit is contained in:
Konicai 2021-05-14 22:48:34 -04:00 committed by GitHub
parent dbf366b138
commit 3e3b8faf16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 125 additions and 43 deletions

View file

@ -188,7 +188,7 @@ public class GeyserConnector {
defaultAuthType = AuthType.getByName(config.getRemote().getAuthType()); defaultAuthType = AuthType.getByName(config.getRemote().getAuthType());
CooldownUtils.setShowCooldown(config.getShowCooldown()); CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls(); SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls();

View file

@ -144,6 +144,7 @@ public class GeyserSession implements CommandSender {
private ChunkCache chunkCache; private ChunkCache chunkCache;
private EntityCache entityCache; private EntityCache entityCache;
private EntityEffectCache effectCache; private EntityEffectCache effectCache;
private final PreferencesCache preferencesCache;
private final TagCache tagCache; private final TagCache tagCache;
private WorldCache worldCache; private WorldCache worldCache;
private WindowCache windowCache; private WindowCache windowCache;
@ -451,6 +452,7 @@ public class GeyserSession implements CommandSender {
this.chunkCache = new ChunkCache(this); this.chunkCache = new ChunkCache(this);
this.entityCache = new EntityCache(this); this.entityCache = new EntityCache(this);
this.effectCache = new EntityEffectCache(); this.effectCache = new EntityEffectCache();
this.preferencesCache = new PreferencesCache(this);
this.tagCache = new TagCache(); this.tagCache = new TagCache();
this.worldCache = new WorldCache(this); this.worldCache = new WorldCache(this);
this.windowCache = new WindowCache(this); this.windowCache = new WindowCache(this);
@ -1224,7 +1226,7 @@ public class GeyserSession implements CommandSender {
public void setReducedDebugInfo(boolean value) { public void setReducedDebugInfo(boolean value) {
reducedDebugInfo = value; reducedDebugInfo = value;
// Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable. // Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable.
getWorldCache().updateShowCoordinates(); preferencesCache.updateShowCoordinates();
} }
/** /**

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2019-2021 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.connector.network.session.cache;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.CooldownUtils;
@Getter
public class PreferencesCache {
private final GeyserSession session;
/**
* True if the client prefers being shown their coordinates, regardless if they're being shown or not.
* This will be true everytime the client joins the server because neither the client nor server store the preference permanently.
*/
@Setter
private boolean prefersShowCoordinates = true;
/**
* If the client's preference will be ignored, this will return false.
*/
private boolean allowShowCoordinates;
/**
* Which CooldownType the client prefers. Initially set to {@link CooldownUtils#getDefaultShowCooldown()}.
*/
@Setter
private CooldownUtils.CooldownType cooldownPreference = CooldownUtils.getDefaultShowCooldown();
public PreferencesCache(GeyserSession session) {
this.session = session;
}
/**
* Tell the client to hide or show the coordinates.
*
* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply: <br>
* <br>
* {@link GeyserSession#reducedDebugInfo} is enabled
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
*/
public void updateShowCoordinates() {
allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates();
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
}
}

View file

@ -28,7 +28,6 @@ package org.geysermc.connector.network.session.cache;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.scoreboard.Objective; import org.geysermc.connector.scoreboard.Objective;
import org.geysermc.connector.scoreboard.Scoreboard; import org.geysermc.connector.scoreboard.Scoreboard;
@ -40,13 +39,6 @@ public class WorldCache {
@Setter @Setter
private Difficulty difficulty = Difficulty.EASY; private Difficulty difficulty = Difficulty.EASY;
/**
* True if the client prefers being shown their coordinates, regardless if they're being shown or not.
* This will be true everytime the client joins the server because neither the client nor server store the preference permanently.
*/
@Setter
private boolean prefersShowCoordinates = true;
private Scoreboard scoreboard; private Scoreboard scoreboard;
private final ScoreboardUpdater scoreboardUpdater; private final ScoreboardUpdater scoreboardUpdater;
@ -71,17 +63,4 @@ public class WorldCache {
int pps = scoreboardUpdater.getPacketsPerSecond(); int pps = scoreboardUpdater.getPacketsPerSecond();
return Math.max(pps, pendingPps); return Math.max(pps, pendingPps);
} }
/**
* Tell the client to hide or show the coordinates.
*
* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply: <br>
* <br>
* {@link GeyserSession#reducedDebugInfo} is enabled
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
*/
public void updateShowCoordinates() {
boolean allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates();
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
}
} }

View file

@ -28,6 +28,7 @@ package org.geysermc.connector.utils;
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket; import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
import lombok.Getter; import lombok.Getter;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.session.cache.PreferencesCache;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -36,18 +37,25 @@ import java.util.concurrent.TimeUnit;
* Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind * Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind
*/ */
public class CooldownUtils { public class CooldownUtils {
private static CooldownType SHOW_COOLDOWN; private static CooldownType DEFAULT_SHOW_COOLDOWN;
public static void setShowCooldown(String showCooldown) { public static void setDefaultShowCooldown(String showCooldown) {
SHOW_COOLDOWN = CooldownType.getByName(showCooldown); DEFAULT_SHOW_COOLDOWN = CooldownType.getByName(showCooldown);
}
public static CooldownType getDefaultShowCooldown() {
return DEFAULT_SHOW_COOLDOWN;
} }
/** /**
* Starts sending the fake cooldown to the Bedrock client. * Starts sending the fake cooldown to the Bedrock client. If the cooldown is not disabled, the sent type is {@link PreferencesCache#getCooldownPreference()}
* @param session GeyserSession * @param session GeyserSession
*/ */
public static void sendCooldown(GeyserSession session) { public static void sendCooldown(GeyserSession session) {
if (SHOW_COOLDOWN == CooldownType.DISABLED) return; if (DEFAULT_SHOW_COOLDOWN == CooldownType.DISABLED) return;
CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference();
if (sessionPreference == CooldownType.DISABLED) return;
if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used
// Needs to be sent or no subtitle packet is recognized by the client // Needs to be sent or no subtitle packet is recognized by the client
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
@ -56,19 +64,20 @@ public class CooldownUtils {
session.sendUpstreamPacket(titlePacket); session.sendUpstreamPacket(titlePacket);
session.setLastHitTime(System.currentTimeMillis()); session.setLastHitTime(System.currentTimeMillis());
long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads
computeCooldown(session, lastHitTime); computeCooldown(session, sessionPreference, lastHitTime);
} }
/** /**
* Keeps updating the cooldown until the bar is complete. * Keeps updating the cooldown until the bar is complete.
* @param session GeyserSession * @param session GeyserSession
* @param sessionPreference The type of cooldown the client prefers
* @param lastHitTime The time of the last hit. Used to gauge how long the cooldown is taking. * @param lastHitTime The time of the last hit. Used to gauge how long the cooldown is taking.
*/ */
private static void computeCooldown(GeyserSession session, long lastHitTime) { private static void computeCooldown(GeyserSession session, CooldownType sessionPreference, long lastHitTime) {
if (session.isClosed()) return; // Don't run scheduled tasks if the client left if (session.isClosed()) return; // Don't run scheduled tasks if the client left
if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { if (sessionPreference == CooldownType.ACTIONBAR) {
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
} else { } else {
titlePacket.setType(SetTitlePacket.Type.SUBTITLE); titlePacket.setType(SetTitlePacket.Type.SUBTITLE);
@ -79,10 +88,10 @@ public class CooldownUtils {
titlePacket.setStayTime(2); titlePacket.setStayTime(2);
session.sendUpstreamPacket(titlePacket); session.sendUpstreamPacket(titlePacket);
if (hasCooldown(session)) { if (hasCooldown(session)) {
session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, sessionPreference, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50
} else { } else {
SetTitlePacket removeTitlePacket = new SetTitlePacket(); SetTitlePacket removeTitlePacket = new SetTitlePacket();
if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { if (sessionPreference == CooldownType.ACTIONBAR) {
removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR); removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
} else { } else {
removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE); removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE);
@ -133,7 +142,7 @@ public class CooldownUtils {
public static final CooldownType[] VALUES = values(); public static final CooldownType[] VALUES = values();
/** /**
* Convert the CooldownType string (from config) to the enum, TITLE on fail * Convert the CooldownType string (from config) to the enum, DISABLED on fail
* *
* @param name CooldownType string * @param name CooldownType string
* *

View file

@ -57,11 +57,24 @@ public class SettingsUtils {
CustomFormBuilder builder = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.settings.title.main", language)); CustomFormBuilder builder = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.settings.title.main", language));
builder.setIcon(new FormImage(FormImage.FormImageType.PATH, "textures/ui/settings_glyph_color_2x.png")); builder.setIcon(new FormImage(FormImage.FormImageType.PATH, "textures/ui/settings_glyph_color_2x.png"));
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. // Only show the client title if any of the client settings are available
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) { if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.client", language))); builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.client", language)));
builder.addComponent(new ToggleComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.option.coordinates", language), session.getWorldCache().isPrefersShowCoordinates())); // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
if (session.getPreferencesCache().isAllowShowCoordinates()) {
builder.addComponent(new ToggleComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.option.coordinates", language), session.getPreferencesCache().isPrefersShowCoordinates()));
}
if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
DropdownComponent cooldownDropdown = new DropdownComponent();
cooldownDropdown.setText(LocaleUtils.getLocaleString("options.attackIndicator", language));
cooldownDropdown.setOptions(new ArrayList<>());
cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.attack.crosshair", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.TITLE);
cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.attack.hotbar", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.ACTIONBAR);
cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.off", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.DISABLED);
builder.addComponent(cooldownDropdown);
}
} }
@ -121,15 +134,23 @@ public class SettingsUtils {
} }
int offset = 0; int offset = 0;
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) {
offset++; // Client settings title offset++; // Client settings title
session.getWorldCache().setPrefersShowCoordinates(settingsResponse.getToggleResponses().get(offset)); // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
session.getWorldCache().updateShowCoordinates(); if (session.getPreferencesCache().isAllowShowCoordinates()) {
session.getPreferencesCache().setPrefersShowCoordinates(settingsResponse.getToggleResponses().get(offset));
session.getPreferencesCache().updateShowCoordinates();
offset++; offset++;
} }
if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
CooldownUtils.CooldownType cooldownType = CooldownUtils.CooldownType.VALUES[settingsResponse.getDropdownResponses().get(offset).getElementID()];
session.getPreferencesCache().setCooldownPreference(cooldownType);
offset++;
}
}
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) { if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
offset++; // Server settings title offset++; // Server settings title

@ -1 +1 @@
Subproject commit 96e7ed66ccdafea0cc991b8004566d448e8f6e6a Subproject commit 9b08df51898fd71ee24e7accdfbe56f164b5c539