Implement daily reset

This commit is contained in:
Melledy
2025-11-08 05:49:20 -08:00
parent 8cc08df65c
commit 2ecc0f28c5
4 changed files with 84 additions and 19 deletions

View File

@@ -98,6 +98,7 @@ public class Config {
public boolean autoCreateAccount = true; public boolean autoCreateAccount = true;
public boolean skipIntro = false; public boolean skipIntro = false;
public boolean unlockInstances = true; public boolean unlockInstances = true;
public int dailyResetHour = 0;
} }
@Getter @Getter

View File

@@ -1,9 +1,13 @@
package emu.nebula; package emu.nebula;
import java.time.ZoneId;
public class GameConstants { public class GameConstants {
public static final int DATA_VERSION = 31; public static final int DATA_VERSION = 31;
public static final String VERSION = "1.0.0." + DATA_VERSION; public static final String VERSION = "1.0.0." + DATA_VERSION;
public static final ZoneId UTC_ZONE = ZoneId.of("UTC");
public static final String PROTO_BASE_TYPE_URL = "type.googleapis.com/proto."; public static final String PROTO_BASE_TYPE_URL = "type.googleapis.com/proto.";
public static final int INTRO_GUIDE_ID = 1; public static final int INTRO_GUIDE_ID = 1;

View File

@@ -1,35 +1,46 @@
package emu.nebula.game; package emu.nebula.game;
import java.util.Timer; import java.time.Instant;
import java.util.TimerTask; import java.time.LocalDate;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import emu.nebula.GameConstants;
import emu.nebula.Nebula;
import emu.nebula.game.gacha.GachaModule; import emu.nebula.game.gacha.GachaModule;
import emu.nebula.game.player.PlayerModule; import emu.nebula.game.player.PlayerModule;
import emu.nebula.net.GameSession; import emu.nebula.net.GameSession;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
public class GameContext { public class GameContext implements Runnable {
private final Object2ObjectMap<String, GameSession> sessions; private final Object2ObjectMap<String, GameSession> sessions;
// Modules // Modules
private final PlayerModule playerModule; private final PlayerModule playerModule;
private final GachaModule gachaModule; private final GachaModule gachaModule;
// Cleanup thread // Game loop
private final Timer cleanupTimer; private final ScheduledExecutorService scheduler;
// Daily
private long epochDays;
public GameContext() { public GameContext() {
this.sessions = new Object2ObjectOpenHashMap<>(); this.sessions = new Object2ObjectOpenHashMap<>();
// Setup game modules
this.playerModule = new PlayerModule(this); this.playerModule = new PlayerModule(this);
this.gachaModule = new GachaModule(this); this.gachaModule = new GachaModule(this);
this.cleanupTimer = new Timer(); // Run game loop
this.cleanupTimer.scheduleAtFixedRate(new CleanupTask(this), 0, TimeUnit.SECONDS.toMillis(60)); this.scheduler = Executors.newScheduledThreadPool(1);
this.scheduler.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);
} }
public synchronized GameSession getSessionByToken(String token) { public synchronized GameSession getSessionByToken(String token) {
@@ -75,17 +86,40 @@ public class GameContext {
} }
} }
@Getter
public static class CleanupTask extends TimerTask {
private GameContext gameContext;
public CleanupTask(GameContext gameContext) {
this.gameContext = gameContext;
}
@Override @Override
public void run() { public void run() {
this.getGameContext().cleanupInactiveSessions(); // Check daily - Update epoch days
long offset = Nebula.getConfig().getServerOptions().getDailyResetHour() * -3600;
var instant = Instant.now().plusSeconds(offset);
var date = LocalDate.ofInstant(instant, GameConstants.UTC_ZONE);
long lastEpochDays = this.epochDays;
this.epochDays = date.toEpochDay();
// Check if the day was changed
if (this.epochDays > lastEpochDays) {
this.resetDailies();
}
// Clean up any inactive sessions
this.cleanupInactiveSessions();
}
/**
* Resets the daily missions/etc for all players on the server
*/
public synchronized void resetDailies() {
for (var session : this.getSessions().values()) {
// Cache
var player = session.getPlayer();
// Skip if session doesn't have a player
if (player == null) {
continue;
}
//
player.checkResetDailies();
} }
} }
} }

View File

@@ -64,6 +64,7 @@ public class Player implements GameDatabaseObject {
private int energy; private int energy;
private long energyLastUpdate; private long energyLastUpdate;
private long lastEpochDay;
private long createTime; private long createTime;
// Managers // Managers
@@ -430,6 +431,27 @@ public class Player implements GameDatabaseObject {
// Empty // Empty
} }
// Dailies
public void checkResetDailies() {
// Sanity check to make sure daily reset isnt being triggered wrong
if (Nebula.getGameContext().getEpochDays() <= this.getLastEpochDay()) {
return;
}
// Reset dailies
this.resetDailies();
// Update last epoch day
this.lastEpochDay = Nebula.getGameContext().getEpochDays();
Nebula.getGameDatabase().update(this, this.getUid(), "lastEpochDay", this.lastEpochDay);
}
public void resetDailies() {
// Reset daily quests
this.getQuestManager().resetDailyQuests();
}
// Login // Login
private <T extends PlayerManager> T loadManagerFromDatabase(Class<T> cls) { private <T extends PlayerManager> T loadManagerFromDatabase(Class<T> cls) {
@@ -471,6 +493,10 @@ public class Player implements GameDatabaseObject {
} }
public void onLogin() { public void onLogin() {
// See if we need to reset dailies
this.checkResetDailies();
// Trigger quest login
this.getQuestManager().triggerQuest(QuestCondType.LoginTotal, 1); this.getQuestManager().triggerQuest(QuestCondType.LoginTotal, 1);
} }