forked from Shardstone/trail-into-darkness
First commit on my server, yey!
This commit is contained in:
42
Assets/Code/Core/Boot.cs
Normal file
42
Assets/Code/Core/Boot.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Nox.EditorCode;
|
||||
using System;
|
||||
using Unity.VectorGraphics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Nox.Core {
|
||||
public class Boot {
|
||||
/// <summary>
|
||||
/// The is the first method called when the game starts. It will load the Initializer prefab which will initialize the project
|
||||
/// </summary>
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void Initialize() {
|
||||
#if UNITY_EDITOR
|
||||
switch(BootMode.BootType) {
|
||||
case BootType.UnityDefault:
|
||||
return;
|
||||
case BootType.SceneBoot:
|
||||
Addressables.InstantiateAsync("Initializer").WaitForCompletion();
|
||||
break;
|
||||
case BootType.FullBoot:
|
||||
var loadOperation = SceneManager.LoadSceneAsync("Startup", LoadSceneMode.Single);
|
||||
if(loadOperation != null) {
|
||||
loadOperation.completed += OnCompleted;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
#else
|
||||
Addressables.InstantiateAsync("Initializer").WaitForCompletion();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void OnCompleted(AsyncOperation obj) {
|
||||
obj.allowSceneActivation = true;
|
||||
Addressables.InstantiateAsync("Initializer").WaitForCompletion();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/Boot.cs.meta
Normal file
2
Assets/Code/Core/Boot.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7904792340a14b458474cbdea3bbb2e
|
||||
13
Assets/Code/Core/BootstrapReferences.cs
Normal file
13
Assets/Code/Core/BootstrapReferences.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Nox.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Nox.Core {
|
||||
[CreateAssetMenu(menuName = "Nox/Database/General/BoostrapReferences", fileName = "BoostrapReferences")]
|
||||
public class BootstrapReferences : ScriptableObject {
|
||||
public AssetReference startMenuScene;
|
||||
public AssetReference splashUIReference;
|
||||
public AssetReference playModeSettings;
|
||||
public AssetReference menuPrefabsContainer;
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/BootstrapReferences.cs.meta
Normal file
2
Assets/Code/Core/BootstrapReferences.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55a600591b835403c8053e4ed4b581fa
|
||||
113
Assets/Code/Core/EntryPoint.cs
Normal file
113
Assets/Code/Core/EntryPoint.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Nox.Game;
|
||||
using Nox.Game.UI;
|
||||
using Nox.Input;
|
||||
using Nox.Platform;
|
||||
using Jovian.SaveSystem;
|
||||
using Nox.EditorCode;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// The main boot class which is initializing the project, loads the platforms settings, initializes the platforms and creates the game states
|
||||
/// </summary>
|
||||
public class EntryPoint : MonoBehaviour {
|
||||
public AssetReferenceT<InitializerSettingsFile> initializerSettingsFile;
|
||||
|
||||
private IPlatform platform;
|
||||
private GameDataState gameDataState;
|
||||
private Dictionary<GameState, IGameState> applicationStates;
|
||||
private ProfilerMarker createApplicationStateMarker = new ProfilerMarker("createApplicationState");
|
||||
private ISceneTransition sceneTransition;
|
||||
private ISaveSystem saveSystem;
|
||||
|
||||
private InitializerSettingsFile initializerSettings;
|
||||
private BootstrapReferences bootstrapReferences;
|
||||
private MenuGameStateData menuGameStateData;
|
||||
|
||||
public IEnumerator Start() {
|
||||
DontDestroyOnLoad(this);
|
||||
|
||||
// scene authoring is helping with making each scene stand-alone playable
|
||||
var activeSceneReference = FindFirstObjectByType<SceneReference>();
|
||||
if(activeSceneReference == null) {
|
||||
Debug.LogWarning("The scene has no SceneReference script. Will start by default in Splash Application State");
|
||||
var sceneRef = new GameObject {
|
||||
name = "Scene Reference"
|
||||
};
|
||||
activeSceneReference = sceneRef.AddComponent<SceneReference>();
|
||||
activeSceneReference.gameState = GameState.BootState;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Initialize platform
|
||||
gameDataState = new GameDataState {
|
||||
platformSelector = new PlatformSelector(PlatformSelector.GetDevicePlatform(), PlatformSelector.GetPlatformDefaultInputMode()),
|
||||
};
|
||||
gameDataState.ChangeGameState(activeSceneReference.gameState);
|
||||
|
||||
// Load Initialization Settings
|
||||
var initSettingsHandle = Addressables.LoadAssetAsync<InitializerSettingsFile>(initializerSettingsFile);
|
||||
yield return new WaitUntil(() => initSettingsHandle.IsDone);
|
||||
initializerSettings = initSettingsHandle.Result;
|
||||
yield return CreatePlatformFactory();
|
||||
|
||||
var bootStrapsSettingsHandle = Addressables.LoadAssetAsync<BootstrapReferences>(initializerSettings.bootstrapSettings);
|
||||
yield return new WaitUntil(() => bootStrapsSettingsHandle.IsDone);
|
||||
bootstrapReferences = bootStrapsSettingsHandle.Result;
|
||||
menuGameStateData = new MenuGameStateData();
|
||||
|
||||
var fadeObject = new GameObject("ScreenFadeTransition");
|
||||
sceneTransition = fadeObject.AddComponent<ScreenFadeTransition>();
|
||||
|
||||
CreateApplicationStates();
|
||||
|
||||
var gameStateRunner = gameObject.AddComponent<GameStateRunner>();
|
||||
gameStateRunner.Initialize(applicationStates, gameDataState, platform, sceneTransition);
|
||||
}
|
||||
|
||||
private IEnumerator CreatePlatformFactory() {
|
||||
platform = null;
|
||||
var devicePlatform = gameDataState.platformSelector.devicePlatform;
|
||||
platform = devicePlatform switch {
|
||||
DevicePlatform.Desktop => new DesktopPlatform(initializerSettings.desktopPlatformSettings),
|
||||
DevicePlatform.UnityEditor => new UnityEditorPlatform(initializerSettings.unityEditorPlatformSettings),
|
||||
_ => platform
|
||||
};
|
||||
|
||||
if(!Equals(gameDataState.platformSelector.devicePlatform, DevicePlatform.Desktop) &&
|
||||
PlatformSelector.GetPlatformDefaultInputMode() == InputMode.Desktop) {
|
||||
platform = new DesktopPlatform(initializerSettings.desktopPlatformSettings);
|
||||
}
|
||||
yield return platform?.Initialize(gameDataState);
|
||||
}
|
||||
|
||||
private void CreateApplicationStates() {
|
||||
createApplicationStateMarker.Begin();
|
||||
|
||||
// Save System
|
||||
var saveSettings = SaveSystemSettings.Load();
|
||||
ISaveSerializer saveSerializer = saveSettings.saveFormat == SaveFormat.Json
|
||||
? new JsonSaveSerializer()
|
||||
: new BinarySaveSerializer(saveSettings.obfuscationKey);
|
||||
ISaveStorage saveStorage = new FileSystemSaveStorage(Application.persistentDataPath, saveSettings.saveDirectoryName);
|
||||
ISaveSlotManager saveSlotManager = new SaveSlotManager(saveStorage, saveSettings);
|
||||
saveSystem = new SaveSystem(saveSerializer, saveStorage, saveSlotManager, saveSettings);
|
||||
|
||||
var adventuredata = new AdventureData();
|
||||
var characterSystems = DefaultCharacterSystemsFactory.Create(maxPartySize: 8);
|
||||
var partyCreatorModel = new PartyCreatorModel(characterSystems.CharacterFactory, characterSystems.PartyFactory);
|
||||
|
||||
applicationStates = new Dictionary<GameState, IGameState> {
|
||||
[GameState.BootState] = new SplashGameState(bootstrapReferences, gameDataState),
|
||||
[GameState.MainMenu] = new MainMenuGameState(gameDataState, menuGameStateData, bootstrapReferences, saveSystem, partyCreatorModel, adventuredata),
|
||||
[GameState.GameMode] = new GameModeGameState(gameDataState, bootstrapReferences, platform.PlatformSettings, saveSystem, sceneTransition, adventuredata),
|
||||
};
|
||||
createApplicationStateMarker.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/EntryPoint.cs.meta
Normal file
2
Assets/Code/Core/EntryPoint.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fd8cc6910b9e44718d0bd7733e0b83e
|
||||
31
Assets/Code/Core/GameDataState.cs
Normal file
31
Assets/Code/Core/GameDataState.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Nox.Game;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// This class is meant to hold application essential gameplay state
|
||||
/// </summary>
|
||||
public class GameDataState {
|
||||
public PlatformSelector platformSelector;
|
||||
public string activeSessionId;
|
||||
public Vector3? savedPartyPosition;
|
||||
public GameState ActiveGameState { get; set; }
|
||||
public PlayMode ActivePlayMode { get; set; }
|
||||
public PartyData ActiveParty { get; set; }
|
||||
|
||||
public PlayMode PreviousPlayMode { get; private set; }
|
||||
|
||||
public void ChangeGameState(GameState gameState) {
|
||||
ActiveGameState = gameState;
|
||||
}
|
||||
|
||||
public void ChangePlayMode(PlayMode playMode) {
|
||||
if (ActiveGameState != GameState.GameMode && playMode != PlayMode.None){
|
||||
Debug.LogError("Cannot change Game Mode state in any other Application State than ApplicationState.GameMode");
|
||||
return;
|
||||
}
|
||||
PreviousPlayMode = ActivePlayMode;
|
||||
ActivePlayMode = playMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/GameDataState.cs.meta
Normal file
2
Assets/Code/Core/GameDataState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6ac548e723e24ae2a81ac2d2e4cd571
|
||||
208
Assets/Code/Core/GameModeGameState.cs
Normal file
208
Assets/Code/Core/GameModeGameState.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
#nullable enable
|
||||
using Nox.Game;
|
||||
using Nox.Platform;
|
||||
using Nox.Game.UI;
|
||||
using Jovian.SaveSystem;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
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 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) {
|
||||
this.gameDataState = gameDataState;
|
||||
this.platformSettings = platformSettings;
|
||||
this.saveSystem = saveSystem;
|
||||
this.sceneTransition = sceneTransition;
|
||||
this.adventuredata = adventuredata;
|
||||
|
||||
bootstrapSettings = Addressables.LoadAssetAsync<PlayModeSettings>(bootstrapReferences.playModeSettings).WaitForCompletion();
|
||||
}
|
||||
|
||||
public void EnterGameState() {
|
||||
if(gameDataState.ActivePlayMode == PlayMode.None) {
|
||||
var sceneReference = Object.FindFirstObjectByType<SceneReference>();
|
||||
if(bootstrapSettings.gameModeData.Any(g => g.playMode == sceneReference.playMode)) {
|
||||
gameDataState.ChangePlayMode(sceneReference.playMode);
|
||||
}
|
||||
}
|
||||
advSettingsHandler = Addressables.LoadAssetAsync<AdventureSettings>("Assets/Database/Game/AdventureSettings.asset");
|
||||
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();
|
||||
return adventure?.CaptureNoxSaveData();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/GameModeGameState.cs.meta
Normal file
2
Assets/Code/Core/GameModeGameState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 306626ccbd8594138af9911a5743c82e
|
||||
110
Assets/Code/Core/GameStateRunner.cs
Normal file
110
Assets/Code/Core/GameStateRunner.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System.Collections.Generic;
|
||||
using Nox.Platform;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// This is the class that will execute the update cycles for each game state. This should be the only place using Unity's Monobehaviour specific classes
|
||||
/// </summary>
|
||||
public class GameStateRunner : MonoBehaviour {
|
||||
private IGameState currentState;
|
||||
private GameState currentStateType;
|
||||
private Dictionary<GameState, IGameState> applicationStates;
|
||||
private GameDataState gameDataState;
|
||||
private bool isRunnerUpdated;
|
||||
private bool isUnloading;
|
||||
private IPlatform platform;
|
||||
private ISceneTransition sceneTransition;
|
||||
private GameState pendingStateTransition;
|
||||
private bool isStateTransitioning;
|
||||
private bool waitingForFadeIn;
|
||||
|
||||
public void Initialize(Dictionary<GameState, IGameState> stateLookUp, GameDataState gameDataState, IPlatform selectedPlatform, ISceneTransition sceneTransition) {
|
||||
DontDestroyOnLoad(gameObject);
|
||||
this.platform = selectedPlatform;
|
||||
this.sceneTransition = sceneTransition;
|
||||
applicationStates = stateLookUp;
|
||||
this.gameDataState = gameDataState;
|
||||
ChangeApplicationState(gameDataState.ActiveGameState);
|
||||
}
|
||||
|
||||
public void FixedUpdate() {
|
||||
if(!currentState.IsGameStateInitialized) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
// Pre-ticks area
|
||||
platform.Tick();
|
||||
|
||||
if(waitingForFadeIn) {
|
||||
if(currentState.IsGameStateInitialized) {
|
||||
waitingForFadeIn = false;
|
||||
sceneTransition.FadeIn(() => {
|
||||
isStateTransitioning = false;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(isStateTransitioning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isRunnerUpdated && currentState.IsGameStateInitialized) {
|
||||
isRunnerUpdated = true;
|
||||
}
|
||||
|
||||
var nextState = currentStateType;
|
||||
if(isRunnerUpdated || isUnloading) {
|
||||
nextState = currentState.Tick();
|
||||
if(gameDataState.ActiveGameState != currentStateType) {
|
||||
nextState = gameDataState.ActiveGameState;
|
||||
}
|
||||
}
|
||||
|
||||
if(nextState != currentStateType) {
|
||||
BeginStateTransition(nextState);
|
||||
}
|
||||
|
||||
// Ticks area
|
||||
|
||||
// Post-ticks area
|
||||
}
|
||||
|
||||
public void LateUpdate() {
|
||||
if(isStateTransitioning || !currentState.IsGameStateInitialized) {
|
||||
return;
|
||||
}
|
||||
currentState.LateTick();
|
||||
}
|
||||
|
||||
public void OnDestroy() {
|
||||
currentState.Dispose();
|
||||
}
|
||||
|
||||
private void BeginStateTransition(GameState newGameState) {
|
||||
isStateTransitioning = true;
|
||||
pendingStateTransition = newGameState;
|
||||
sceneTransition.FadeOut(() => {
|
||||
ChangeApplicationState(pendingStateTransition);
|
||||
waitingForFadeIn = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void ChangeApplicationState(GameState newGameState) {
|
||||
if(currentState != null) {
|
||||
currentState.ExitGameState();
|
||||
}
|
||||
|
||||
currentState = applicationStates[newGameState];
|
||||
currentState.EnterGameState();
|
||||
currentStateType = newGameState;
|
||||
gameDataState.ChangeGameState(newGameState);
|
||||
isRunnerUpdated = false;
|
||||
Debug.Log($"Entered {newGameState} ApplicationState");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/GameStateRunner.cs.meta
Normal file
2
Assets/Code/Core/GameStateRunner.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a039e3a8262654d2b9428ec8aa6d3140
|
||||
11
Assets/Code/Core/IGameLifecycle.cs
Normal file
11
Assets/Code/Core/IGameLifecycle.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// Prototype for every behaviour that needs to run tick/frame updates
|
||||
/// </summary>
|
||||
public interface IGameLifecycle {
|
||||
public void Initialize();
|
||||
public void Tick();
|
||||
|
||||
public void Dispose();
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/IGameLifecycle.cs.meta
Normal file
2
Assets/Code/Core/IGameLifecycle.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55887b4438f5b42b891be19046c0c963
|
||||
24
Assets/Code/Core/IGameState.cs
Normal file
24
Assets/Code/Core/IGameState.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// Add or modify project specific game states
|
||||
/// </summary>
|
||||
public enum GameState {
|
||||
Invalid,
|
||||
BootState,
|
||||
Loading,
|
||||
MainMenu,
|
||||
GameMode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prototype for creating application states
|
||||
/// </summary>
|
||||
public interface IGameState {
|
||||
public void EnterGameState();
|
||||
public GameState Tick();
|
||||
public void LateTick();
|
||||
public void ExitGameState();
|
||||
void Dispose();
|
||||
bool IsGameStateInitialized { get; }
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/IGameState.cs.meta
Normal file
2
Assets/Code/Core/IGameState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d01b97d5164454406931704f451edba9
|
||||
23
Assets/Code/Core/IPlayMode.cs
Normal file
23
Assets/Code/Core/IPlayMode.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Nox.Core {
|
||||
public enum PlayMode {
|
||||
None,
|
||||
PauseMenu,
|
||||
Adventure,
|
||||
Town,
|
||||
Rest,
|
||||
Combat
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prototype for crating new game modes
|
||||
/// </summary>
|
||||
public interface IPlayMode {
|
||||
bool IsGameModeInitialized { get;}
|
||||
|
||||
public void EnterPlayMode();
|
||||
public void Tick();
|
||||
public void LateTick();
|
||||
void ExitGameMode();
|
||||
void Dispose();
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/IPlayMode.cs.meta
Normal file
2
Assets/Code/Core/IPlayMode.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fb4f9f9705394782b9ed1852e8f015c
|
||||
9
Assets/Code/Core/ISceneTransition.cs
Normal file
9
Assets/Code/Core/ISceneTransition.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Nox.Core {
|
||||
public interface ISceneTransition {
|
||||
bool IsTransitioning { get; }
|
||||
void FadeOut(Action onComplete = null);
|
||||
void FadeIn(Action onComplete = null);
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/ISceneTransition.cs.meta
Normal file
2
Assets/Code/Core/ISceneTransition.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b503206ce8521d469bf99fd4b0df611
|
||||
12
Assets/Code/Core/InitializerSettingsFile.cs
Normal file
12
Assets/Code/Core/InitializerSettingsFile.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Nox.Platform;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Nox.Core {
|
||||
[CreateAssetMenu(menuName = "Nox/Database/General/InitializerSettingsFile", fileName = "InitializerSettingsFile")]
|
||||
public class InitializerSettingsFile : ScriptableObject {
|
||||
public AssetReferenceT<DesktopPlatformSettings> desktopPlatformSettings;
|
||||
public AssetReferenceT<BootstrapReferences> bootstrapSettings;
|
||||
public AssetReferenceT<UnityEditorPlatformSettings> unityEditorPlatformSettings;
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/InitializerSettingsFile.cs.meta
Normal file
2
Assets/Code/Core/InitializerSettingsFile.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 593adee4e2b3d4537b4d956077816eec
|
||||
20
Assets/Code/Core/LoadingGameState.cs
Normal file
20
Assets/Code/Core/LoadingGameState.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// This is a state which would normally consist of a load screen scene or anything similar
|
||||
/// </summary>
|
||||
public class LoadingGameState : IGameState {
|
||||
public bool IsGameStateInitialized { get; set; }
|
||||
|
||||
public void EnterGameState() {
|
||||
}
|
||||
public GameState Tick() {
|
||||
return GameState.Loading;
|
||||
}
|
||||
public void LateTick() { }
|
||||
public void ExitGameState() {
|
||||
}
|
||||
public void Dispose() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/LoadingGameState.cs.meta
Normal file
2
Assets/Code/Core/LoadingGameState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e20613474534045658e4e2a0b9657ade
|
||||
104
Assets/Code/Core/MainMenuGameState.cs
Normal file
104
Assets/Code/Core/MainMenuGameState.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Nox.Game;
|
||||
using Jovian.SaveSystem;
|
||||
using Nox.UI;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
|
||||
namespace Nox.Core {
|
||||
|
||||
public class MenuGameStateData {
|
||||
public Action<PlayMode> startGameRequests;
|
||||
public Action continueGameRequest;
|
||||
}
|
||||
|
||||
public class MainMenuGameState : IGameState {
|
||||
private readonly GameDataState gameDataState;
|
||||
private readonly MenuGameStateData menuGameStateData;
|
||||
private readonly BootstrapReferences bootstrapReferences;
|
||||
private readonly ISaveSystem saveSystem;
|
||||
private readonly PartyCreatorModel partyCreatorModel;
|
||||
private AdventureData adventureData;
|
||||
private Action<PlayMode> onStartGameRequested;
|
||||
private Action onContinueRequested;
|
||||
private MainMenuView mainMenuView;
|
||||
private AsyncOperationHandle<SceneInstance> loadSceneAsync;
|
||||
public bool IsGameStateInitialized { get; set; }
|
||||
|
||||
public MainMenuGameState(GameDataState gameDataState,
|
||||
MenuGameStateData menuGameStateData,
|
||||
BootstrapReferences bootstrapReferences,
|
||||
ISaveSystem saveSystem,
|
||||
PartyCreatorModel partyCreatorModel,
|
||||
AdventureData adventureData) {
|
||||
this.gameDataState = gameDataState;
|
||||
this.menuGameStateData = menuGameStateData;
|
||||
this.bootstrapReferences = bootstrapReferences;
|
||||
this.saveSystem = saveSystem;
|
||||
this.partyCreatorModel = partyCreatorModel;
|
||||
this.adventureData = adventureData;
|
||||
}
|
||||
|
||||
public void EnterGameState() {
|
||||
IsGameStateInitialized = false;
|
||||
onStartGameRequested = mode => {
|
||||
var party = partyCreatorModel.CreatePartyForNewRun(companionCount: 4);
|
||||
gameDataState.ActiveParty = party;
|
||||
var sessions = saveSystem.GetAllSessions();
|
||||
gameDataState.activeSessionId = sessions.Count > 0
|
||||
? sessions[0].sessionId
|
||||
: saveSystem.CreateSession();
|
||||
gameDataState.savedPartyPosition = new Vector3(7.285129f, 0, 0.4297419f);
|
||||
gameDataState.ChangeGameState(GameState.GameMode);
|
||||
gameDataState.ChangePlayMode(mode);
|
||||
};
|
||||
onContinueRequested = () => {
|
||||
var saveData = NoxSaveData.RestoreSavedData(saveSystem, gameDataState, ref adventureData);
|
||||
if(saveData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
gameDataState.ChangeGameState(GameState.GameMode);
|
||||
gameDataState.ChangePlayMode(saveData.activePlayMode);
|
||||
|
||||
};
|
||||
menuGameStateData.startGameRequests += onStartGameRequested;
|
||||
menuGameStateData.continueGameRequest += onContinueRequested;
|
||||
_ = InitializeGameState();
|
||||
}
|
||||
|
||||
private async Task InitializeGameState() {
|
||||
var sceneHandle = Addressables.LoadSceneAsync(bootstrapReferences.startMenuScene);
|
||||
await sceneHandle.Task;
|
||||
await sceneHandle.Result.ActivateAsync();
|
||||
var assetHandle = Addressables.LoadAssetAsync<MenuPrefabsContainer>(bootstrapReferences.menuPrefabsContainer);
|
||||
await assetHandle.Task;
|
||||
mainMenuView = new MainMenuView(assetHandle.Result, menuGameStateData, saveSystem);
|
||||
mainMenuView.Initialize();
|
||||
IsGameStateInitialized = true;
|
||||
}
|
||||
|
||||
public GameState Tick() {
|
||||
mainMenuView?.Tick();
|
||||
return gameDataState.ActiveGameState;
|
||||
}
|
||||
public void LateTick() { }
|
||||
public void Dispose() { }
|
||||
|
||||
public void ExitGameState() {
|
||||
if(onStartGameRequested != null) {
|
||||
menuGameStateData.startGameRequests -= onStartGameRequested;
|
||||
onStartGameRequested = null;
|
||||
}
|
||||
if(onContinueRequested != null) {
|
||||
menuGameStateData.continueGameRequest -= onContinueRequested;
|
||||
onContinueRequested = null;
|
||||
}
|
||||
mainMenuView?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
2
Assets/Code/Core/MainMenuGameState.cs.meta
Normal file
2
Assets/Code/Core/MainMenuGameState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9453c712e94474abe8eea1a900eb12c4
|
||||
37
Assets/Code/Core/PlatformSelector.cs
Normal file
37
Assets/Code/Core/PlatformSelector.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Nox.Input;
|
||||
using Nox.Platform;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// Base class used by the platform factory to select the current platform and the input
|
||||
/// </summary>
|
||||
public class PlatformSelector {
|
||||
public readonly DevicePlatform devicePlatform;
|
||||
private InputMode inputMode;
|
||||
|
||||
public PlatformSelector(DevicePlatform devicePlatform, InputMode inputMode) {
|
||||
this.devicePlatform = devicePlatform;
|
||||
this.inputMode = inputMode;
|
||||
}
|
||||
|
||||
public void SetInputMode(InputMode newInputMode) {
|
||||
inputMode = newInputMode;
|
||||
}
|
||||
|
||||
public static InputMode GetPlatformDefaultInputMode() {
|
||||
#if UNITY_EDITOR
|
||||
return InputMode.Editor;
|
||||
#else
|
||||
return InputMode.Desktop;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static DevicePlatform GetDevicePlatform() {
|
||||
#if UNITY_EDITOR
|
||||
return DevicePlatform.UnityEditor;
|
||||
#else
|
||||
return DevicePlatform.Desktop;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/PlatformSelector.cs.meta
Normal file
2
Assets/Code/Core/PlatformSelector.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d92359b567a9c4b67882fd1c63a2d28a
|
||||
16
Assets/Code/Core/PlayModeSettings.cs
Normal file
16
Assets/Code/Core/PlayModeSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Nox.Core {
|
||||
[CreateAssetMenu(fileName = "GameModeSettings", menuName = "Nox/Database/General/GameModeSettings")]
|
||||
public class PlayModeSettings : ScriptableObject {
|
||||
public PlayModeData[] gameModeData;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PlayModeData {
|
||||
public PlayMode playMode;
|
||||
public AssetReference scene;
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/PlayModeSettings.cs.meta
Normal file
2
Assets/Code/Core/PlayModeSettings.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00bbbdf0f374243d986d909bc14c6773
|
||||
12
Assets/Code/Core/SceneReference.cs
Normal file
12
Assets/Code/Core/SceneReference.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// Scene generic authoring/reference collection. Can also contain the settings for booting up a particular scene
|
||||
/// </summary>
|
||||
public class SceneReference : MonoBehaviour {
|
||||
public GameState gameState = GameState.Invalid;
|
||||
public PlayMode playMode;
|
||||
}
|
||||
|
||||
}
|
||||
2
Assets/Code/Core/SceneReference.cs.meta
Normal file
2
Assets/Code/Core/SceneReference.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96fc2eb19de9a4236b7ca7d6a7ebd9a8
|
||||
37
Assets/Code/Core/SplashGameState.cs
Normal file
37
Assets/Code/Core/SplashGameState.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Nox.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Nox.Core {
|
||||
/// <summary>
|
||||
/// This is an example for the first game state which in our case would usually contain a gdpr
|
||||
/// This is an example to show how it could be initialized and also how it could boot into the next game state
|
||||
/// Ideally a SceneHandler/Manager of sorts should handle loading and unloading scenes.
|
||||
/// </summary>
|
||||
public class SplashGameState : IGameState {
|
||||
private readonly BootstrapReferences bootStrapInitializer;
|
||||
private readonly GameDataState gameDataState;
|
||||
public bool IsGameStateInitialized { get; set; } = true;
|
||||
|
||||
public SplashGameState(BootstrapReferences bootStrapInitializer, GameDataState gameDataState) {
|
||||
this.bootStrapInitializer = bootStrapInitializer;
|
||||
this.gameDataState = gameDataState;
|
||||
}
|
||||
|
||||
public void EnterGameState() {
|
||||
DisclaimerReference gdprReference = Addressables.InstantiateAsync(bootStrapInitializer.splashUIReference).WaitForCompletion().GetComponent<DisclaimerReference>();
|
||||
gdprReference.continueButton.onClick.AddListener(() => {
|
||||
gameDataState.ChangeGameState(GameState.MainMenu);
|
||||
Object.Destroy(gdprReference.gameObject);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public GameState Tick() {
|
||||
return GameState.BootState;
|
||||
}
|
||||
public void LateTick() { }
|
||||
public void Dispose() { }
|
||||
public void ExitGameState() { }
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Core/SplashGameState.cs.meta
Normal file
2
Assets/Code/Core/SplashGameState.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 607a080faa19b492baa5c1b9ad13302b
|
||||
Reference in New Issue
Block a user