427 lines
17 KiB
C#
427 lines
17 KiB
C#
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
using System;
|
|
using Cinemachine;
|
|
using GameCult.Aetheria.State.Verse;
|
|
using GameCult.Mesh;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Serialization;
|
|
using UnityEngine.UI;
|
|
using float2 = Unity.Mathematics.float2;
|
|
using float3 = Unity.Mathematics.float3;
|
|
|
|
public class ActionGameManager : MonoBehaviour
|
|
{
|
|
private AetheriaDaemonObserver _daemonObserver;
|
|
private AetheriaUnityPilotCommandSender _pilotCommands;
|
|
private AetheriaUnityObservedEntityRestorer _observedEntityRestorer;
|
|
private AetheriaUnityCurrentEntityBinder _currentEntityBinder;
|
|
private AetheriaUnityPilotFrameController _pilotFrameController;
|
|
private AetheriaUnityPilotOperationController _pilotOperationController;
|
|
private AetheriaUnityObservedFrameApplier _observedFrameApplier;
|
|
private AetheriaUnityEntityBlueprintMaterializer _entityBlueprintMaterializer;
|
|
private AetheriaUnityMenuShell _menuShell;
|
|
private AetheriaUnityGameplayInputShell _gameplayInputShell;
|
|
private AetheriaUnityCockpitHudShell _cockpitHudShell;
|
|
private AetheriaUnityGameplayLoopShell _gameplayLoopShell;
|
|
private AetheriaUnityGameplayBootShell _gameplayBootShell;
|
|
private AetheriaUnityGameplaySceneWiring _sceneWiring;
|
|
private AetheriaClientState _gameplayState;
|
|
private AetheriaClientState GameplayState =>
|
|
_gameplayState ??= AetheriaUnityRuntimeClientProvider.RuntimeState("unity-action-game-manager");
|
|
|
|
private AetheriaUnityPilotCommandSender PilotCommands =>
|
|
_pilotCommands ??= new AetheriaUnityPilotCommandSender(
|
|
() => AetheriaUnityRuntimeClientProvider.Control("unity-pilot-commands"),
|
|
() => Time.unscaledTime);
|
|
private AetheriaUnityObservedEntityRestorer ObservedEntityRestorer =>
|
|
_observedEntityRestorer ??= new AetheriaUnityObservedEntityRestorer(
|
|
_presentationEntityIndex,
|
|
ItemManager,
|
|
EntityBlueprintMaterializer.MaterializeObservedEntity,
|
|
_loadoutItemFactory.CreateLoadoutItem,
|
|
Debug.LogWarning);
|
|
private AetheriaUnityObservedZoneContextFactory ObservedZoneContextFactory { get; set; }
|
|
private AetheriaUnityCurrentEntityBinder CurrentEntityBinder =>
|
|
_currentEntityBinder ??= new AetheriaUnityCurrentEntityBinder
|
|
{
|
|
ZoneRenderer = ZoneRenderer,
|
|
DeathPost = DeathPost,
|
|
GameplayUI = GameplayUI,
|
|
CurrentEntityPresentation = _currentEntityPresentation,
|
|
TargetPresentation = _targetPresentation,
|
|
GetCurrentEntity = () => CurrentEntity,
|
|
ResolveDockParent = ResolveDockParentFromCurrentDocking,
|
|
SetCurrentEntity = entity => CurrentEntity = entity,
|
|
GetViewDirection = () => _viewDirection,
|
|
SetViewDirection = direction => _viewDirection = direction,
|
|
ResolveZoneRender = () => ResolveDaemonObserver()?.LastRenderView?.ZoneRender,
|
|
ApplyActionBarBindings = _ => _actionBarPresentation?.ApplyLocalBindings(),
|
|
EnablePlayerInput = EnablePlayerInput,
|
|
DisablePlayerInput = DisablePlayerInput,
|
|
PlayMusic = PlayMusic,
|
|
UpdateTargetPanel = target => CockpitHudShell.UpdateTarget(target, CurrentEntity)
|
|
};
|
|
private AetheriaUnityPilotFrameController PilotFrameController =>
|
|
_pilotFrameController ??= new AetheriaUnityPilotFrameController(direction => _viewDirection = direction)
|
|
{
|
|
ZoneRenderer = ZoneRenderer,
|
|
Input = Input,
|
|
TargetPresentation = _targetPresentation,
|
|
PilotCommands = PilotCommands,
|
|
HeatstrokePost = HeatstrokePost,
|
|
SevereHeatstrokePost = SevereHeatstrokePost,
|
|
Sensitivity = Sensitivity
|
|
};
|
|
private AetheriaUnityPilotOperationController PilotOperationController =>
|
|
_pilotOperationController ??= new AetheriaUnityPilotOperationController(
|
|
() => PilotCommands,
|
|
_presentationEntityIndex,
|
|
() => _viewDirection,
|
|
() => CurrentEntity);
|
|
private AetheriaUnityObservedFrameApplier ObservedFrameApplier =>
|
|
_observedFrameApplier ??= new AetheriaUnityObservedFrameApplier(
|
|
ResolveDaemonObserver,
|
|
ObservedZoneContextFactory.ResolveGalaxyZone,
|
|
() => Zone,
|
|
zone => Zone = zone,
|
|
_presentationEntityIndex,
|
|
ObservedEntityRestorer,
|
|
ObservedZoneContextFactory,
|
|
() => ZoneRenderer,
|
|
() => CurrentEntity,
|
|
entity => CurrentEntityBinder.RestoreBinding(entity),
|
|
Debug.LogWarning);
|
|
private AetheriaUnityEntityBlueprintMaterializer EntityBlueprintMaterializer =>
|
|
_entityBlueprintMaterializer ??= new AetheriaUnityEntityBlueprintMaterializer(_loadoutItemFactory);
|
|
private AetheriaUnityMenuShell MenuShell =>
|
|
_menuShell ??= new AetheriaUnityMenuShell
|
|
{
|
|
MainMenu = MainMenu,
|
|
HelpScreen = HelpScreen,
|
|
InputDisplayLayout = InputDisplayLayout,
|
|
UiRoot = UiRoot,
|
|
Menu = Menu,
|
|
GameplayUI = GameplayUI,
|
|
ResolveCurrentEntity = () => CurrentEntity,
|
|
IsCurrentEntityUndocked = IsCurrentEntityObservedUndocked,
|
|
ResolveObservedTarget = entity => _targetPresentation.GetObservedTarget(entity),
|
|
SetPaused = paused => GameplayLoopShell.Paused = paused,
|
|
EnablePlayerInput = EnablePlayerInput,
|
|
DisablePlayerInput = DisablePlayerInput,
|
|
UpdatePlayerPanel = () => CockpitHudShell.UpdatePlayer(CurrentEntity),
|
|
UpdateTargetPanel = target => CockpitHudShell.UpdateTarget(target, CurrentEntity)
|
|
};
|
|
private AetheriaUnityGameplayInputShell GameplayInputShell =>
|
|
_gameplayInputShell ??= new AetheriaUnityGameplayInputShell
|
|
{
|
|
RuntimePlayerSettings = RuntimePlayerSettings,
|
|
InputDisplayLayout = InputDisplayLayout,
|
|
Dialog = Dialog,
|
|
MainMenu = MainMenu,
|
|
Menu = Menu,
|
|
MenuMap = MenuMap,
|
|
GameplayUI = GameplayUI,
|
|
ActionBar = ActionBar,
|
|
ActionBarSlot = ActionBarSlot,
|
|
ZoneRenderer = ZoneRenderer,
|
|
MenuShell = MenuShell,
|
|
DragSession = _dragSession,
|
|
ActionBarPresentation = _actionBarPresentation,
|
|
PilotOperationController = PilotOperationController,
|
|
ResolveCurrentEntity = () => CurrentEntity,
|
|
SetInput = input => Input = input
|
|
};
|
|
private AetheriaUnityCockpitHudShell CockpitHudShell =>
|
|
_cockpitHudShell ??= new AetheriaUnityCockpitHudShell
|
|
{
|
|
ShipPanel = ShipPanel,
|
|
TargetShipPanel = TargetShipPanel,
|
|
SchematicDisplay = SchematicDisplay,
|
|
TargetSchematicDisplay = TargetSchematicDisplay,
|
|
TargetIndicator = TargetIndicator
|
|
};
|
|
private AetheriaUnityGameplayLoopShell GameplayLoopShell =>
|
|
_gameplayLoopShell ??= new AetheriaUnityGameplayLoopShell
|
|
{
|
|
ResolveCurrentEntity = () => CurrentEntity,
|
|
IsCurrentEntityUndocked = IsCurrentEntityObservedUndocked,
|
|
ApplyLatestZoneRender = () => ObservedFrameApplier.ApplyLatestZoneRender(),
|
|
CurrentEntityPresentation = _currentEntityPresentation,
|
|
PilotFrameController = PilotFrameController,
|
|
TargetPresentation = _targetPresentation
|
|
};
|
|
private AetheriaUnityGameplayBootShell GameplayBootShell =>
|
|
_gameplayBootShell ??= new AetheriaUnityGameplayBootShell
|
|
{
|
|
Settings = Settings,
|
|
ZoneRenderer = ZoneRenderer,
|
|
CockpitHudShell = CockpitHudShell,
|
|
Log = Debug.Log
|
|
};
|
|
private AetheriaUnityGameplaySceneWiring SceneWiring =>
|
|
_sceneWiring ??= new AetheriaUnityGameplaySceneWiring
|
|
{
|
|
ZoneRenderer = ZoneRenderer,
|
|
DockCamera = DockCamera,
|
|
FollowCamera = FollowCamera,
|
|
Menu = Menu,
|
|
TradeMenu = TradeMenu,
|
|
GameplayUI = GameplayUI,
|
|
Inventory = Inventory,
|
|
ShipPanel = ShipPanel,
|
|
TargetShipPanel = TargetShipPanel,
|
|
SchematicDisplay = SchematicDisplay,
|
|
TargetSchematicDisplay = TargetSchematicDisplay,
|
|
Crosshairs = Crosshairs,
|
|
LockIndicator = LockIndicator,
|
|
HitMarker = HitMarker,
|
|
HitMarkerDuration = HitMarkerDuration,
|
|
TargetShieldsBackground = TargetShieldsBackground,
|
|
TargetShieldsIcon = TargetShieldsIcon,
|
|
ShieldColor = ShieldColor,
|
|
NoShieldColor = NoShieldColor,
|
|
ShieldIcon = ShieldIcon,
|
|
NoShieldIcon = NoShieldIcon,
|
|
HostileTargetIndicator = HostileTargetIndicator,
|
|
FriendlyTargetIndicator = FriendlyTargetIndicator,
|
|
ViewDot = ViewDot,
|
|
TargetIndicator = TargetIndicator,
|
|
TargetHitpointsFill = TargetHitpointsFill,
|
|
TargetVisibilityFill = TargetVisibilityFill,
|
|
VisibilityToTargetFill = VisibilityToTargetFill,
|
|
TargetShieldsFill = TargetShieldsFill,
|
|
MainMenu = MainMenu
|
|
};
|
|
private readonly AetheriaUnityPresentationEntityIndex _presentationEntityIndex = new AetheriaUnityPresentationEntityIndex();
|
|
private static RuntimePlayerSettings RuntimePlayerSettings
|
|
=> AetheriaUnityRuntimeClientProvider.PlayerSettings;
|
|
|
|
public GameSettings Settings;
|
|
//public string StarterShipTemplate = "Longinus";
|
|
public float2 Sensitivity;
|
|
|
|
[Header("Postprocessing")]
|
|
public Volume DeathPost;
|
|
public Volume HeatstrokePost;
|
|
public Volume SevereHeatstrokePost;
|
|
|
|
[Header("Scene Links")]
|
|
public GameObject UiRoot;
|
|
public GameObject HelpScreen;
|
|
public InputDisplayLayout InputDisplayLayout;
|
|
public Transform ActionBar;
|
|
public ActionBarSlot ActionBarSlot;
|
|
public ZoneRenderer ZoneRenderer;
|
|
public CinemachineVirtualCamera DockCamera;
|
|
public CinemachineVirtualCamera FollowCamera;
|
|
|
|
[Header("Menu UI")]
|
|
public MainMenu MainMenu;
|
|
public MenuPanel Menu;
|
|
public MapRenderer MenuMap;
|
|
public TradeMenu TradeMenu;
|
|
public InventoryMenu Inventory;
|
|
public InventoryPanel ShipPanel;
|
|
public InventoryPanel TargetShipPanel;
|
|
public ConfirmationDialog Dialog;
|
|
|
|
[Header("Gameplay UI")]
|
|
public CanvasGroup GameplayUI;
|
|
public Prototype HostileTargetIndicator;
|
|
public Prototype FriendlyTargetIndicator;
|
|
public PlaceUIElementWorldspace ViewDot;
|
|
public Prototype LockIndicator;
|
|
public PlaceUIElementWorldspace[] Crosshairs;
|
|
public GameObject HitMarker;
|
|
public float HitMarkerDuration;
|
|
public SchematicDisplay SchematicDisplay;
|
|
public SchematicDisplay TargetSchematicDisplay;
|
|
|
|
[Header("Target Indicator")]
|
|
public PlaceUIElementWorldspace TargetIndicator;
|
|
public Image TargetHitpointsFill;
|
|
public Image TargetVisibilityFill;
|
|
public Image VisibilityToTargetFill;
|
|
public Image TargetShieldsBackground;
|
|
public Image TargetShieldsFill;
|
|
public Image TargetShieldsIcon;
|
|
public Color ShieldColor;
|
|
public Color NoShieldColor;
|
|
public Sprite ShieldIcon;
|
|
public Sprite NoShieldIcon;
|
|
|
|
//public PlayerInput Input;
|
|
|
|
// private CinemachineFramingTransposer _transposer;
|
|
// private CinemachineComposer _composer;
|
|
|
|
private Entity _currentEntity;
|
|
|
|
// private ShipInput _shipInput;
|
|
private float3 _viewDirection;
|
|
private readonly AetheriaUnityCurrentEntityPresentation _currentEntityPresentation = new AetheriaUnityCurrentEntityPresentation();
|
|
private readonly AetheriaUnityTargetPresentation _targetPresentation = new AetheriaUnityTargetPresentation();
|
|
public AetheriaInput Input { get; private set; }
|
|
|
|
private Entity CurrentEntity
|
|
{
|
|
get => _currentEntity;
|
|
set => _currentEntity = value;
|
|
}
|
|
|
|
private ItemManager ItemManager { get; set; }
|
|
private AetheriaUnityLoadoutItemFactory _loadoutItemFactory;
|
|
private Zone Zone { get; set; }
|
|
|
|
private readonly AetheriaUnityDragSession _dragSession = new AetheriaUnityDragSession();
|
|
private readonly AetheriaUnityActionBarPresentation _actionBarPresentation = new AetheriaUnityActionBarPresentation();
|
|
|
|
private void OnDisable()
|
|
{
|
|
_gameplayInputShell?.Dispose();
|
|
AetheriaUnityRuntimeClientProvider.Dispose();
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
var boot = GameplayBootShell.Boot();
|
|
ItemManager = boot.ItemManager;
|
|
_loadoutItemFactory = boot.LoadoutItemFactory;
|
|
ObservedZoneContextFactory = new AetheriaUnityObservedZoneContextFactory(
|
|
ItemManager,
|
|
Settings.PlanetSettings,
|
|
boot.ObservedGalaxy,
|
|
Debug.LogWarning,
|
|
PlayMusic);
|
|
SceneWiring.ConfigureCurrentEntityPresentation(_currentEntityPresentation, boot.RuntimeCatalog);
|
|
SceneWiring.ConfigureTargetPresentation(
|
|
_targetPresentation,
|
|
boot.RuntimeCatalog,
|
|
_presentationEntityIndex);
|
|
SceneWiring.ConfigureInventoryDragSession(_dragSession);
|
|
SceneWiring.ConfigureActionBarPresentation(
|
|
_actionBarPresentation,
|
|
GameplayInputShell,
|
|
boot.RuntimeCatalog,
|
|
Settings,
|
|
() => CurrentEntity,
|
|
() => AetheriaUnityRuntimeClientProvider.Control("unity-action-bar"));
|
|
SceneWiring.ConfigureRuntimeInputScreenShell(MenuShell);
|
|
SceneWiring.ConfigurePresentationEntityIndex(_presentationEntityIndex);
|
|
|
|
// TODO: Process Stories
|
|
|
|
GameplayInputShell.Bootstrap();
|
|
|
|
StartGame();
|
|
}
|
|
|
|
private void EnablePlayerInput()
|
|
{
|
|
GameplayInputShell.EnablePlayerInput();
|
|
}
|
|
|
|
private void DisablePlayerInput()
|
|
{
|
|
GameplayInputShell.DisablePlayerInput();
|
|
}
|
|
|
|
private void StartGame()
|
|
{
|
|
ObservedFrameApplier.ApplyLatestZoneRender();
|
|
}
|
|
|
|
private bool IsCurrentEntityObservedUndocked()
|
|
{
|
|
var docking = CurrentDockingSnapshot();
|
|
if (CurrentEntity == null ||
|
|
docking == null ||
|
|
docking.CurrentEntityIndex != CurrentEntity.DaemonEntityIndex)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (_presentationEntityIndex.TryGetRecordKeyForPresentationEntity(CurrentEntity, out var currentEntityKey) &&
|
|
!string.IsNullOrWhiteSpace(docking.CurrentEntityKey) &&
|
|
!string.Equals(docking.CurrentEntityKey, currentEntityKey, StringComparison.Ordinal))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return !docking.IsDocked;
|
|
}
|
|
|
|
private Entity ResolveDockParentFromCurrentDocking(Entity currentEntity)
|
|
{
|
|
var docking = CurrentDockingSnapshot();
|
|
if (currentEntity == null ||
|
|
docking == null ||
|
|
!docking.IsDocked ||
|
|
docking.CurrentEntityIndex != currentEntity.DaemonEntityIndex ||
|
|
string.IsNullOrWhiteSpace(docking.DockParentEntityKey))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (_presentationEntityIndex.TryGetRecordKeyForPresentationEntity(currentEntity, out var currentEntityKey) &&
|
|
!string.IsNullOrWhiteSpace(docking.CurrentEntityKey) &&
|
|
!string.Equals(docking.CurrentEntityKey, currentEntityKey, StringComparison.Ordinal))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return _presentationEntityIndex.TryGetPresentationEntityByRecordKey(docking.DockParentEntityKey, out var dockParent)
|
|
? dockParent
|
|
: null;
|
|
}
|
|
|
|
private AetheriaRuntimeCurrentDockingDocument CurrentDockingSnapshot()
|
|
{
|
|
try
|
|
{
|
|
return GameplayState.CurrentDocking.Latest();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogWarning($"Failed to read Aetheria current docking for gameplay manager: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// public void ToggleEditMode()
|
|
// {
|
|
// _editMode = !_editMode;
|
|
// FollowCamera.gameObject.SetActive(!_editMode);
|
|
// TopDownCamera.gameObject.SetActive(_editMode);
|
|
// }
|
|
|
|
public void PlayMusic(MusicType type)
|
|
{
|
|
// TODO: SFX: Music
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
GameplayLoopShell.Tick(Time.deltaTime, Time.time);
|
|
}
|
|
|
|
private AetheriaDaemonObserver ResolveDaemonObserver()
|
|
{
|
|
if (_daemonObserver != null)
|
|
{
|
|
return _daemonObserver;
|
|
}
|
|
|
|
_daemonObserver = FindAnyObjectByType<AetheriaDaemonObserver>();
|
|
return _daemonObserver;
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
GameplayLoopShell.LateTick();
|
|
}
|
|
}
|