forked from Shardstone/trail-into-darkness
217 lines
7.9 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|