Files
trail-into-darkness/Assets/Code/Core/GameModeGameState.cs
Sebastian Bularca fa15608f3a added in-game logger
2026-04-05 12:32:42 +02:00

217 lines
7.9 KiB
C#

#nullable enable
using Nox.Game;
using Nox.Platform;
using Nox.Game.UI;
using Jovian.SaveSystem;
using Jovian.InGameLogging;
using System.Collections.Generic;
using ZLinq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace Nox.Core {
/// <summary>
/// The Game Mode Game State which is the base state in which all GameModes need to run.
/// Game Modes are any modes that involve gameplay and gameplay related scenes. This state is where the game runs.
/// </summary>
public class GameModeGameState : IGameState {
private readonly GameDataState gameDataState;
private readonly PlatformSettings platformSettings;
private readonly PlayModeSettings bootstrapSettings;
private readonly ISaveSystem saveSystem;
private readonly ISceneTransition sceneTransition;
private readonly AdventureData adventuredata;
private readonly IGameLogStore gameLogStore;
private readonly Dictionary<PlayMode, IPlayMode?> playModeCache = new();
private IMenuView? pauseMenuView;
private IPlayMode? playMode;
private IPlayMode? suspendedPlayMode;
private bool isTransitioning;
private PlayMode currentPlaymode;
private bool stateEntered;
private AsyncOperationHandle<AdventureSettings> advSettingsHandler;
private AdventureSettings? adventureSettings;
public bool IsGameStateInitialized {
get => stateEntered && (playMode == null || playMode.IsGameModeInitialized);
}
public GameModeGameState(GameDataState gameDataState,
BootstrapReferences bootstrapReferences,
PlatformSettings platformSettings,
ISaveSystem saveSystem,
ISceneTransition sceneTransition,
AdventureData adventuredata,
IGameLogStore gameLogStore) {
this.gameDataState = gameDataState;
this.platformSettings = platformSettings;
this.saveSystem = saveSystem;
this.sceneTransition = sceneTransition;
this.adventuredata = adventuredata;
this.gameLogStore = gameLogStore;
bootstrapSettings = Addressables.LoadAssetAsync<PlayModeSettings>(bootstrapReferences.playModeSettings).WaitForCompletion();
}
public void EnterGameState() {
if(gameDataState.ActivePlayMode == PlayMode.None) {
var sceneReference = Object.FindFirstObjectByType<SceneReference>();
if(bootstrapSettings.gameModeData.AsValueEnumerable().Any(g => g.playMode == sceneReference.playMode)) {
gameDataState.ChangePlayMode(sceneReference.playMode);
}
}
advSettingsHandler = Addressables.LoadAssetAsync<AdventureSettings>("AdventureSettings");
adventureSettings = advSettingsHandler.WaitForCompletion();
InitializeGameViews();
currentPlaymode = gameDataState.ActivePlayMode;
playMode?.EnterPlayMode();
Debug.Log($"Initialized Game Mode: {gameDataState.ActivePlayMode}");
stateEntered = true;
}
private void InitializeGameViews() {
SwitchGameMode();
pauseMenuView ??= new PauseMenuView(gameDataState, saveSystem, CaptureNoxSaveData);
}
private NoxSavedDataSet? CaptureNoxSaveData() {
var adventure = FindAdventurePlayMode();
var saveData = adventure?.CaptureNoxSaveData();
if(saveData != null) {
saveData.gameLogData = gameLogStore.GetSaveData();
}
return saveData;
}
private AdventurePlayMode? FindAdventurePlayMode() {
if(playMode is AdventurePlayMode active) {
return active;
}
if(suspendedPlayMode is AdventurePlayMode suspended) {
return suspended;
}
if(playModeCache.TryGetValue(PlayMode.Adventure, out var cached) && cached is AdventurePlayMode fromCache) {
return fromCache;
}
return null;
}
private void SwitchGameMode() {
var activeParty = gameDataState.ActiveParty;
if(playModeCache.TryGetValue(gameDataState.ActivePlayMode, out var cached)) {
playMode = cached;
return;
}
playMode = gameDataState.ActivePlayMode switch {
PlayMode.Adventure => new AdventurePlayMode(platformSettings, activeParty, bootstrapSettings, gameDataState, saveSystem, adventureSettings, adventuredata),
PlayMode.PauseMenu => new PauseMenuPlayMode(platformSettings, gameDataState, pauseMenuView!),
PlayMode.Town => new TownPlayMode(platformSettings, activeParty),
PlayMode.Rest => new RestPlayMode(platformSettings, activeParty),
PlayMode.Combat => new CombatPlayMode(platformSettings, activeParty),
_ => playMode
};
playModeCache[gameDataState.ActivePlayMode] = playMode;
}
public GameState Tick() {
if(isTransitioning) {
return GameState.GameMode;
}
if(ShouldTransition()) {
HandlePlayModeTransition();
return GameState.GameMode;
}
if(playMode is { IsGameModeInitialized: true }) {
playMode.Tick();
}
return GameState.GameMode;
}
private bool ShouldTransition() {
return currentPlaymode != gameDataState.ActivePlayMode
&& gameDataState.ActivePlayMode != PlayMode.None;
}
private bool IsPauseTransition() {
return gameDataState.ActivePlayMode == PlayMode.PauseMenu
|| (currentPlaymode == PlayMode.PauseMenu && suspendedPlayMode != null);
}
private void HandlePlayModeTransition() {
if(IsPauseTransition()) {
ExecutePlayModeSwitch();
return;
}
isTransitioning = true;
sceneTransition.FadeOut(() => {
ExecutePlayModeSwitch();
sceneTransition.FadeIn(() => {
isTransitioning = false;
});
});
}
private void ExecutePlayModeSwitch() {
var enteringPause = gameDataState.ActivePlayMode == PlayMode.PauseMenu;
var resumingFromPause = currentPlaymode == PlayMode.PauseMenu
&& suspendedPlayMode != null;
if(enteringPause) {
suspendedPlayMode = playMode;
}
playMode?.ExitGameMode();
currentPlaymode = gameDataState.ActivePlayMode;
if(resumingFromPause) {
playMode = suspendedPlayMode;
suspendedPlayMode = null;
playMode?.EnterPlayMode();
return;
}
SwitchGameMode();
playMode?.EnterPlayMode();
}
public void LateTick() {
if(playMode is { IsGameModeInitialized: true }) {
playMode.LateTick();
}
}
public void Dispose() {
suspendedPlayMode?.Dispose();
playMode?.Dispose();
}
public void ExitGameState() {
suspendedPlayMode?.ExitGameMode();
suspendedPlayMode?.Dispose();
suspendedPlayMode = null;
playMode?.ExitGameMode();
playMode?.Dispose();
playMode = null;
foreach(var cached in playModeCache.Values) {
if(cached != null && cached != playMode && cached != suspendedPlayMode) {
cached.Dispose();
}
}
playModeCache.Clear();
stateEntered = false;
gameDataState.ChangePlayMode(PlayMode.None);
advSettingsHandler.Release();
}
}
}