3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-26 16:12:46 +01:00

Better handling of fake cooldown

Because of Bedrock limitations, if a player has text background opacity enabled, they'll see an empty section where the title is usually displayed as the fake cooldown is shown. This commit minimizes the time that is shown by clearing the text as soon as possible. Reference issue: https://github.com/GeyserMC/Geyser/issues/1710

This commit also removes starting the fake cooldown process if the client switches to an inventory slot with the same Java ID.
Dieser Commit ist enthalten in:
Camotoy 2022-03-25 20:22:39 -04:00
Ursprung c610e98f4c
Commit f639be6362
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
6 geänderte Dateien mit 105 neuen und 23 gelöschten Zeilen

Datei anzeigen

@ -26,24 +26,36 @@
package org.geysermc.geyser.session.cache; package org.geysermc.geyser.session.cache;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.scoreboard.Scoreboard; import org.geysermc.geyser.scoreboard.Scoreboard;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession; import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
import org.geysermc.geyser.session.GeyserSession;
@Getter public final class WorldCache {
public class WorldCache {
private final GeyserSession session; private final GeyserSession session;
@Getter
private final ScoreboardSession scoreboardSession; private final ScoreboardSession scoreboardSession;
@Getter
private Scoreboard scoreboard; private Scoreboard scoreboard;
@Getter
@Setter @Setter
private Difficulty difficulty = Difficulty.EASY; private Difficulty difficulty = Difficulty.EASY;
/**
* Whether our cooldown changed the title time, and the true title times need to be re-sent.
*/
private boolean titleTimesNeedReset = false;
private int trueTitleFadeInTime;
private int trueTitleStayTime;
private int trueTitleFadeOutTime;
public WorldCache(GeyserSession session) { public WorldCache(GeyserSession session) {
this.session = session; this.session = session;
this.scoreboard = new Scoreboard(session); this.scoreboard = new Scoreboard(session);
scoreboardSession = new ScoreboardSession(session); scoreboardSession = new ScoreboardSession(session);
resetTitleTimes(false);
} }
public void removeScoreboard() { public void removeScoreboard() {
@ -58,4 +70,53 @@ public class WorldCache {
int pps = scoreboardSession.getPacketsPerSecond(); int pps = scoreboardSession.getPacketsPerSecond();
return Math.max(pps, pendingPps); return Math.max(pps, pendingPps);
} }
public void markTitleTimesAsIncorrect() {
titleTimesNeedReset = true;
}
/**
* Store the true active title times.
*/
public void setTitleTimes(int fadeInTime, int stayTime, int fadeOutTime) {
trueTitleFadeInTime = fadeInTime;
trueTitleStayTime = stayTime;
trueTitleFadeOutTime = fadeOutTime;
}
/**
* If needed, ensure that the Bedrock client will use the correct timings for titles.
*/
public void synchronizeCorrectTitleTimes() {
if (titleTimesNeedReset) {
forceSyncCorrectTitleTimes();
titleTimesNeedReset = false;
}
}
private void forceSyncCorrectTitleTimes() {
SetTitlePacket titlePacket = new SetTitlePacket();
titlePacket.setType(SetTitlePacket.Type.TIMES);
titlePacket.setText("");
titlePacket.setFadeInTime(trueTitleFadeInTime);
titlePacket.setStayTime(trueTitleStayTime);
titlePacket.setFadeOutTime(trueTitleFadeOutTime);
titlePacket.setPlatformOnlineId("");
titlePacket.setXuid("");
session.sendUpstreamPacket(titlePacket);
}
/**
* Reset the true active title times to the (Java Edition 1.18.2) defaults.
*/
public void resetTitleTimes(boolean clientSync) {
trueTitleFadeInTime = 10;
trueTitleStayTime = 70;
trueTitleFadeOutTime = 20;
if (clientSync) {
forceSyncCorrectTitleTimes();
}
}
} }

Datei anzeigen

@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
import com.nukkitx.protocol.bedrock.packet.MobEquipmentPacket; import com.nukkitx.protocol.bedrock.packet.MobEquipmentPacket;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
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;
@ -42,8 +43,9 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
@Override @Override
public void translate(GeyserSession session, MobEquipmentPacket packet) { public void translate(GeyserSession session, MobEquipmentPacket packet) {
if (!session.isSpawned() || packet.getHotbarSlot() > 8 || int newSlot = packet.getHotbarSlot();
packet.getContainerId() != ContainerId.INVENTORY || session.getPlayerInventory().getHeldItemSlot() == packet.getHotbarSlot()) { if (!session.isSpawned() || newSlot > 8 || packet.getContainerId() != ContainerId.INVENTORY
|| session.getPlayerInventory().getHeldItemSlot() == newSlot) {
// For the last condition - Don't update the slot if the slot is the same - not Java Edition behavior and messes with plugins such as Grief Prevention // For the last condition - Don't update the slot if the slot is the same - not Java Edition behavior and messes with plugins such as Grief Prevention
return; return;
} }
@ -51,12 +53,15 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
// Send book update before switching hotbar slot // Send book update before switching hotbar slot
session.getBookEditCache().checkForSend(); session.getBookEditCache().checkForSend();
session.getPlayerInventory().setHeldItemSlot(packet.getHotbarSlot()); GeyserItemStack oldItem = session.getPlayerInventory().getItemInHand();
session.getPlayerInventory().setHeldItemSlot(newSlot);
ServerboundSetCarriedItemPacket setCarriedItemPacket = new ServerboundSetCarriedItemPacket(packet.getHotbarSlot()); ServerboundSetCarriedItemPacket setCarriedItemPacket = new ServerboundSetCarriedItemPacket(newSlot);
session.sendDownstreamPacket(setCarriedItemPacket); session.sendDownstreamPacket(setCarriedItemPacket);
if (session.isSneaking() && session.getPlayerInventory().getItemInHand().getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) { GeyserItemStack newItem = session.getPlayerInventory().getItemInHand();
if (session.isSneaking() && newItem.getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
// Activate shield since we are already sneaking // Activate shield since we are already sneaking
// (No need to send a release item packet - Java doesn't do this when swapping items) // (No need to send a release item packet - Java doesn't do this when swapping items)
// Required to do it a tick later or else it doesn't register // Required to do it a tick later or else it doesn't register
@ -64,8 +69,10 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
50, TimeUnit.MILLISECONDS); 50, TimeUnit.MILLISECONDS);
} }
// Java sends a cooldown indicator whenever you switch an item if (oldItem.getJavaId() != newItem.getJavaId()) {
CooldownUtils.sendCooldown(session); // Java sends a cooldown indicator whenever you switch to a new item type
CooldownUtils.sendCooldown(session);
}
// Update the interactive tag, if an entity is present // Update the interactive tag, if an entity is present
if (session.getMouseoverEntity() != null) { if (session.getMouseoverEntity() != null) {

Datei anzeigen

@ -37,11 +37,14 @@ public class JavaClearTitlesTranslator extends PacketTranslator<ClientboundClear
@Override @Override
public void translate(GeyserSession session, ClientboundClearTitlesPacket packet) { public void translate(GeyserSession session, ClientboundClearTitlesPacket packet) {
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
// TODO handle packet.isResetTimes()
titlePacket.setType(SetTitlePacket.Type.CLEAR); titlePacket.setType(SetTitlePacket.Type.CLEAR);
titlePacket.setText(""); titlePacket.setText("");
titlePacket.setXuid(""); titlePacket.setXuid("");
titlePacket.setPlatformOnlineId(""); titlePacket.setPlatformOnlineId("");
session.sendUpstreamPacket(titlePacket); session.sendUpstreamPacket(titlePacket);
if (packet.isResetTimes()) {
session.getWorldCache().resetTitleTimes(true);
}
} }
} }

Datei anzeigen

@ -38,6 +38,8 @@ public class JavaSetTitleTextTranslator extends PacketTranslator<ClientboundSetT
@Override @Override
public void translate(GeyserSession session, ClientboundSetTitleTextPacket packet) { public void translate(GeyserSession session, ClientboundSetTitleTextPacket packet) {
session.getWorldCache().synchronizeCorrectTitleTimes();
String text; String text;
if (packet.getText() == null || Component.empty().equals(packet.getText())) { // This can happen, see https://github.com/KyoriPowered/adventure/issues/447 if (packet.getText() == null || Component.empty().equals(packet.getText())) { // This can happen, see https://github.com/KyoriPowered/adventure/issues/447
text = " "; text = " ";

Datei anzeigen

@ -36,12 +36,17 @@ public class JavaSetTitlesAnimationTranslator extends PacketTranslator<Clientbou
@Override @Override
public void translate(GeyserSession session, ClientboundSetTitlesAnimationPacket packet) { public void translate(GeyserSession session, ClientboundSetTitlesAnimationPacket packet) {
int fadeInTime = packet.getFadeIn();
int stayTime = packet.getStay();
int fadeOutTime = packet.getFadeOut();
session.getWorldCache().setTitleTimes(fadeInTime, stayTime, fadeOutTime);
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
titlePacket.setType(SetTitlePacket.Type.TIMES); titlePacket.setType(SetTitlePacket.Type.TIMES);
titlePacket.setText(""); titlePacket.setText("");
titlePacket.setFadeInTime(packet.getFadeIn()); titlePacket.setFadeInTime(fadeInTime);
titlePacket.setFadeOutTime(packet.getFadeOut()); titlePacket.setFadeOutTime(fadeOutTime);
titlePacket.setStayTime(packet.getStay()); titlePacket.setStayTime(stayTime);
titlePacket.setXuid(""); titlePacket.setXuid("");
titlePacket.setPlatformOnlineId(""); titlePacket.setPlatformOnlineId("");
session.sendUpstreamPacket(titlePacket); session.sendUpstreamPacket(titlePacket);

Datei anzeigen

@ -57,8 +57,19 @@ public class CooldownUtils {
if (sessionPreference == CooldownType.DISABLED) return; 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 // Set the times to stay a bit with no fade in nor out
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
titlePacket.setType(SetTitlePacket.Type.TIMES);
titlePacket.setStayTime(1000);
titlePacket.setText("");
titlePacket.setXuid("");
titlePacket.setPlatformOnlineId("");
session.sendUpstreamPacket(titlePacket);
session.getWorldCache().markTitleTimesAsIncorrect();
// Needs to be sent or no subtitle packet is recognized by the client
titlePacket = new SetTitlePacket();
titlePacket.setType(SetTitlePacket.Type.TITLE); titlePacket.setType(SetTitlePacket.Type.TITLE);
titlePacket.setText(" "); titlePacket.setText(" ");
titlePacket.setXuid(""); titlePacket.setXuid("");
@ -85,9 +96,6 @@ public class CooldownUtils {
titlePacket.setType(SetTitlePacket.Type.SUBTITLE); titlePacket.setType(SetTitlePacket.Type.SUBTITLE);
} }
titlePacket.setText(getTitle(session)); titlePacket.setText(getTitle(session));
titlePacket.setFadeInTime(0);
titlePacket.setFadeOutTime(5);
titlePacket.setStayTime(2);
titlePacket.setXuid(""); titlePacket.setXuid("");
titlePacket.setPlatformOnlineId(""); titlePacket.setPlatformOnlineId("");
session.sendUpstreamPacket(titlePacket); session.sendUpstreamPacket(titlePacket);
@ -96,11 +104,7 @@ public class CooldownUtils {
computeCooldown(session, sessionPreference, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 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 (sessionPreference == CooldownType.ACTIONBAR) { removeTitlePacket.setType(SetTitlePacket.Type.CLEAR);
removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
} else {
removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE);
}
removeTitlePacket.setText(" "); removeTitlePacket.setText(" ");
removeTitlePacket.setXuid(""); removeTitlePacket.setXuid("");
removeTitlePacket.setPlatformOnlineId(""); removeTitlePacket.setPlatformOnlineId("");