From a4f5d3286d8688e26854ab14a0e343ec9643ae92 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Mon, 8 May 2023 00:11:29 -0400 Subject: [PATCH] Implement game time locking implement for quests --- .../quest/exec/ExecSetGameTimeLocked.java | 20 ++++++++++++ .../emu/grasscutter/game/world/Scene.java | 3 +- .../emu/grasscutter/game/world/World.java | 31 +++++++++++++------ .../send/PacketClientLockGameTimeNotify.java | 18 +++++++++++ 4 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 src/main/java/emu/grasscutter/game/quest/exec/ExecSetGameTimeLocked.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketClientLockGameTimeNotify.java diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecSetGameTimeLocked.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecSetGameTimeLocked.java new file mode 100644 index 000000000..b3ae165cf --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecSetGameTimeLocked.java @@ -0,0 +1,20 @@ +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.quest.QuestData.QuestExecParam; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValueExec; +import emu.grasscutter.game.quest.enums.QuestExec; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +import java.util.Objects; + +@QuestValueExec(QuestExec.QUEST_EXEC_SET_IS_GAME_TIME_LOCKED) +public final class ExecSetGameTimeLocked extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestExecParam condition, String... paramStr) { + var isLocked = Objects.equals(condition.getParam()[0], "1"); + quest.getOwner().getWorld().lockTime(isLocked); + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index 05965048a..c05a423bc 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -510,7 +510,8 @@ public final class Scene { this.finishLoading(); this.checkPlayerRespawn(); - if (this.tickCount++ % 10 == 0) broadcastPacket(new PacketSceneTimeNotify(this)); + if (this.tickCount++ % 10 == 0) + this.broadcastPacket(new PacketSceneTimeNotify(this)); } /** Validates a player's current position. Teleports the player if the player is out of bounds. */ diff --git a/src/main/java/emu/grasscutter/game/world/World.java b/src/main/java/emu/grasscutter/game/world/World.java index 7616bcfc6..7f83e7d0e 100644 --- a/src/main/java/emu/grasscutter/game/world/World.java +++ b/src/main/java/emu/grasscutter/game/world/World.java @@ -31,7 +31,7 @@ import java.util.stream.Collectors; import lombok.Getter; import lombok.val; -public class World implements Iterable { +public final class World implements Iterable { @Getter private final GameServer server; @Getter private final Player host; @Getter private final List players; @@ -42,12 +42,12 @@ public class World implements Iterable { private int nextPeerId = 0; private int worldLevel; - private boolean isMultiplayer; + @Getter private boolean isMultiplayer, timeLocked = false; private long lastUpdateTime; @Getter private int tickCount = 0; @Getter private boolean isPaused = false; - @Getter private long currentWorldTime = 0; + @Getter private long currentWorldTime; public World(Player player) { this(player, false); @@ -118,10 +118,6 @@ public class World implements Iterable { return this.getPlayers().size(); } - public boolean isMultiplayer() { - return isMultiplayer; - } - /** * Gets the next entity ID for the specified entity type. * @@ -427,7 +423,7 @@ public class World implements Iterable { // store updated world time every 60 seconds. (in-game hour) if (this.tickCount % 60 == 0) { - this.getHost().updatePlayerGameTime(currentWorldTime); + this.getHost().updatePlayerGameTime(this.currentWorldTime); } this.tickCount++; @@ -438,13 +434,13 @@ public class World implements Iterable { /** Returns the in-game world time in real milliseconds. */ public long getWorldTime() { - if (!this.isPaused) { + if (!this.isPaused && !this.timeLocked) { var newUpdateTime = System.currentTimeMillis(); this.currentWorldTime += (newUpdateTime - lastUpdateTime); this.lastUpdateTime = newUpdateTime; } - return currentWorldTime; + return this.currentWorldTime; } /** Returns the current in game days world time in in-game minutes (0-1439) */ @@ -512,6 +508,9 @@ public class World implements Iterable { * @param days The number of days to add. */ public void changeTime(int time, int days) { + // Check if the time is locked. + if (this.timeLocked) return; + // Calculate time differences. var currentTime = this.getGameTime(); var diff = time - currentTime; @@ -526,6 +525,18 @@ public class World implements Iterable { player -> player.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_GAME_TIME_TICK)); } + /** + * Locks the world time. + * + * @param locked True if the world time should be locked. + */ + public void lockTime(boolean locked) { + this.timeLocked = locked; + + // Broadcast the state change. + this.broadcastPacket(new PacketClientLockGameTimeNotify(this)); + } + @Override public Iterator iterator() { return this.getPlayers().iterator(); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketClientLockGameTimeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketClientLockGameTimeNotify.java new file mode 100644 index 000000000..bad6e84bd --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketClientLockGameTimeNotify.java @@ -0,0 +1,18 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ClientLockGameTimeNotifyOuterClass.ClientLockGameTimeNotify; + +public final class PacketClientLockGameTimeNotify extends BasePacket { + public PacketClientLockGameTimeNotify(World world) { + super(PacketOpcodes.ClientLockGameTimeNotify); + + var packet = ClientLockGameTimeNotify.newBuilder() + .setIsLock(world.isTimeLocked()) + .build(); + + this.setData(packet); + } +}