Fix: Bedrock players being able to always eat food while in peaceful difficulty (#4904)

This commit is contained in:
chris 2024-07-27 00:39:45 +02:00 committed by GitHub
parent 663e3af7c8
commit 258d6aadb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 3 deletions

View file

@ -27,12 +27,14 @@ package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsResponsePacket; import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsResponsePacket;
import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket;
import org.geysermc.cumulus.form.CustomForm; import org.geysermc.cumulus.form.CustomForm;
import org.geysermc.cumulus.form.impl.FormDefinitions; import org.geysermc.cumulus.form.impl.FormDefinitions;
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;
import org.geysermc.geyser.util.SettingsUtils; import org.geysermc.geyser.util.SettingsUtils;
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -47,6 +49,14 @@ public class BedrockServerSettingsRequestTranslator extends PacketTranslator<Ser
return; return;
} }
// Peaceful difficulty allows always eating food - hence, we just do not send it to Bedrock.
// However, in order for server settings to show it properly, let's revert while we are in the menu!
if (session.getWorldCache().getDifficulty() == Difficulty.PEACEFUL) {
SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket();
setDifficultyPacket.setDifficulty(Difficulty.PEACEFUL.ordinal());
session.sendUpstreamPacket(setDifficultyPacket);
}
CustomForm form = SettingsUtils.buildForm(session); CustomForm form = SettingsUtils.buildForm(session);
int formId = session.getFormCache().addForm(form); int formId = session.getFormCache().addForm(form);

View file

@ -25,21 +25,29 @@
package org.geysermc.geyser.translator.protocol.java; package org.geysermc.geyser.translator.protocol.java;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket;
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;
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket;
@Translator(packet = ClientboundChangeDifficultyPacket.class) @Translator(packet = ClientboundChangeDifficultyPacket.class)
public class JavaChangeDifficultyTranslator extends PacketTranslator<ClientboundChangeDifficultyPacket> { public class JavaChangeDifficultyTranslator extends PacketTranslator<ClientboundChangeDifficultyPacket> {
@Override @Override
public void translate(GeyserSession session, ClientboundChangeDifficultyPacket packet) { public void translate(GeyserSession session, ClientboundChangeDifficultyPacket packet) {
Difficulty difficulty = packet.getDifficulty();
session.getWorldCache().setDifficulty(difficulty);
// Peaceful difficulty allows always eating food - hence, we just do not send it to Bedrock.
if (difficulty == Difficulty.PEACEFUL) {
difficulty = Difficulty.EASY;
}
SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket(); SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket();
setDifficultyPacket.setDifficulty(packet.getDifficulty().ordinal()); setDifficultyPacket.setDifficulty(difficulty.ordinal());
session.sendUpstreamPacket(setDifficultyPacket); session.sendUpstreamPacket(setDifficultyPacket);
session.getWorldCache().setDifficulty(packet.getDifficulty());
} }
} }

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.util; package org.geysermc.geyser.util;
import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket;
import org.geysermc.cumulus.component.DropdownComponent; import org.geysermc.cumulus.component.DropdownComponent;
import org.geysermc.cumulus.form.CustomForm; import org.geysermc.cumulus.form.CustomForm;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -33,6 +34,7 @@ import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
public class SettingsUtils { public class SettingsUtils {
/** /**
@ -96,6 +98,7 @@ public class SettingsUtils {
} }
builder.validResultHandler((response) -> { builder.validResultHandler((response) -> {
applyDifficultyFix(session);
if (showClientSettings) { if (showClientSettings) {
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
if (showCoordinates) { if (showCoordinates) {
@ -134,9 +137,21 @@ public class SettingsUtils {
} }
}); });
builder.closedOrInvalidResultHandler($ -> applyDifficultyFix(session));
return builder.build(); return builder.build();
} }
private static void applyDifficultyFix(GeyserSession session) {
// Peaceful difficulty allows always eating food - hence, we just do not send it to Bedrock.
// Since we sent the real difficulty before opening the server settings form, let's restore it to our workaround here
if (session.getWorldCache().getDifficulty() == Difficulty.PEACEFUL) {
SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket();
setDifficultyPacket.setDifficulty(Difficulty.EASY.ordinal());
session.sendUpstreamPacket(setDifficultyPacket);
}
}
private static String translateEntry(String key, String locale) { private static String translateEntry(String key, String locale) {
if (key.startsWith("%")) { if (key.startsWith("%")) {
// Bedrock will translate // Bedrock will translate