diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java index ccb69856..36533844 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java @@ -25,6 +25,10 @@ package org.geysermc.connector.network.translators.java.world; +import com.nukkitx.protocol.bedrock.data.GameRuleData; +import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket; +import it.unimi.dsi.fastutil.longs.Long2LongMap; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -35,11 +39,37 @@ import com.nukkitx.protocol.bedrock.packet.SetTimePacket; @Translator(packet = ServerUpdateTimePacket.class) public class JavaUpdateTimeTranslator extends PacketTranslator { + // If negative, the last time is stored so we know it's not some plugin behavior doing weird things. + // Per-player for multi-world support + private static final Long2LongMap LAST_RECORDED_TIMES = new Long2LongOpenHashMap(); + @Override public void translate(ServerUpdateTimePacket packet, GeyserSession session) { - // https://minecraft.gamepedia.com/Day-night_cycle#24-hour_Minecraft_day - SetTimePacket setTimePacket = new SetTimePacket(); - setTimePacket.setTime((int) Math.abs(packet.getTime()) % 24000); - session.getUpstream().sendPacket(setTimePacket); + + // Bedrock sends a GameRulesChangedPacket if there is no daylight cycle + // Java just sends a negative long if there is no daylight cycle + long lastTime = LAST_RECORDED_TIMES.getOrDefault(session.getPlayerEntity().getEntityId(), 0); + long time = packet.getTime(); + + if (lastTime != time) { + // https://minecraft.gamepedia.com/Day-night_cycle#24-hour_Minecraft_day + SetTimePacket setTimePacket = new SetTimePacket(); + setTimePacket.setTime((int) Math.abs(time) % 24000); + session.getUpstream().sendPacket(setTimePacket); + // TODO: Performance efficient to always do this? + LAST_RECORDED_TIMES.put(session.getPlayerEntity().getEntityId(), time); + } + if (lastTime < 0 && time >= 0) { + setDoDaylightCycleGamerule(session, true); + } else if (lastTime != time && time < 0) { + setDoDaylightCycleGamerule(session, false); + } } + + private void setDoDaylightCycleGamerule(GeyserSession session, boolean doCycle) { + GameRulesChangedPacket gameRulesChangedPacket = new GameRulesChangedPacket(); + gameRulesChangedPacket.getGameRules().add(new GameRuleData<>("dodaylightcycle", doCycle)); + session.getUpstream().sendPacket(gameRulesChangedPacket); + } + }