Skip to content

Refactor architecture: consolidate managers and update namespaces#378

Open
Shombith03 wants to merge 811 commits into
developmentfrom
claude/merge-dev-fix-menu-PsCnG
Open

Refactor architecture: consolidate managers and update namespaces#378
Shombith03 wants to merge 811 commits into
developmentfrom
claude/merge-dev-fix-menu-PsCnG

Conversation

@Shombith03

Copy link
Copy Markdown
Contributor

Summary

This PR refactors the application architecture by consolidating manager prefabs, updating namespace organization, and reorganizing asset directories. The changes modernize the codebase structure while maintaining functionality.

Key Changes

  • Manager Consolidation: Removed separate GameManager and NetworkStatsManager prefabs, consolidated into new AppManager and PartyServices prefabs for cleaner dependency management
  • Namespace Updates: Updated FTUE (First Time User Experience) scripts to use new namespace structure (CosmicShore.Core, CosmicShore.UI, CosmicShore.Data) instead of old CosmicShore.App.Systems.CTA and CosmicShore.FTUE namespaces
  • Code Organization: Wrapped PrismMeshGenerator in CosmicShore.Editor.MeshGeneration namespace for better organization
  • Prefab Updates:
    • Added ContainerScope prefab for dependency injection
    • Updated GameCanvas prefab references to removed components
    • Modified various projectile and creature prefabs to include new components
  • Asset Reorganization: Moved vessel-related graphics and models to organized subdirectories under _Graphics and _Models
  • Configuration: Added ReflexSettings.asset for dependency injection configuration
  • Deprecated Assets: Removed Deprecated- MainMenuDependencyLoader and Arcade prefabs

Implementation Details

  • Updated all FTUE-related scripts to reference new namespaces while preserving functionality
  • Modified prefab references in GameCanvas to point to new manager structure
  • Added namespace declarations to interface files for better code organization
  • Maintained backward compatibility by updating all dependent scripts to use new namespace paths

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux

claude and others added 30 commits March 1, 2026 04:27
… mode

Changes gameplay vCam binding mode from LockToTargetWithWorldUp to
LockToTargetNoRoll so the camera stays behind the vessel through yaw
and pitch, giving a proper third-person chase feel without roll-induced
instability.

https://claude.ai/code/session_017EQYHoiaCwLqjqCLBhx3KT
…tead of custom vCam

Reverts gameplay camera to use CameraManager.SetupGamePlayCameras(),
which activates CM PlayerCam with the vessel's own CameraSettingsSO
applied via VesselCameraCustomizer. This restores the per-vessel camera
behavior (e.g. Squirrel's specific follow offset and damping) that was
replaced by a dynamically created Cinemachine vCam with hardcoded offsets.

Removed:
- _gameplayFollowOffset serialized field
- _gameplayVCam dynamic creation (CreateGameplayVCam)
- Cinemachine priority-based switching for gameplay camera
- Unity.Cinemachine.TargetTracking using directive

https://claude.ai/code/session_017EQYHoiaCwLqjqCLBhx3KT
… states

Provides a simple inspector-driven way to control which UI panels start
active or inactive when Menu_Main loads, without manually toggling
GameObjects in the scene hierarchy.

https://claude.ai/code/session_013oWqfLV9PdCoMh3CrDwT1n
…es-zewzl

Add InitialPanelStateApplier for UI panel state initialization
…position-RYqgP

Refactor MainMenuCameraController to delegate gameplay camera setup
… priority blending

Replace the instant cut between menu orbit camera (CinemachineCamera) and
gameplay camera (CustomCameraController) with a smooth Cinemachine blend.

A new "CM Freestyle" CinemachineCamera is created as a sibling of
"CM Main Menu" on CameraManager. Both feed into the same CinemachineBrain.
Transitions are driven by priority swaps — the brain handles the blend
automatically. This eliminates the need to activate/deactivate separate
Camera objects, keeping the entire menu camera pipeline within Cinemachine.

Changes:
- MainMenuCameraController: add EnsureFreestyleVCam() that creates/finds
  a "CM Freestyle" vCam with CinemachineFollow + CinemachineRotationComposer.
  ActivateGameplayCamera() now configures the freestyle vCam's tracking target
  and follow offset from the vessel's CameraSettingsSO, then switches priorities.
  ActivateMenuCamera() raises menu vCam priority and lowers freestyle priority,
  keeping both active so the CinemachineBrain can blend between them.
- VesselCameraCustomizer: expose public Settings getter so
  MainMenuCameraController can read the vessel's CameraSettingsSO for the
  freestyle vCam's follow offset.

Blend duration/curve is controlled by the CinemachineBrain's DefaultBlend
setting on the main camera.

https://claude.ai/code/session_01V2hxWA5gN1U4ceF68hoLLP
… Menu_Main UI

Add SetVisible/IsVisible extension methods to GameObjectExtension that use
CanvasGroup (alpha, interactable, blocksRaycasts) instead of
GameObject.SetActive to avoid Unity canvas rebuild costs when toggling
UI element visibility at runtime.

Converted 41 files across screens, views, modals, and elements:
- ScreenSwitcher (navbar, nav icons, freestyle toggle)
- All screen implementations (Home, Arcade, Episode, Hangar, Leaderboards, Store)
- All modal windows (ModalWindowManager base, Profile, PurchaseConfirmation, etc.)
- All view panels (Friends, OnlinePlayers, Party, AddFriend, etc.)
- All button/card elements (LoadoutCard, DailyRewardCard, GameplayRewardButton, etc.)
- InitialPanelStateApplier panel initialization

Custom SetActive methods on NavLink, HangarTrainingGameButton,
IntensitySelectButton, and HangarShipSelectNavLink are left unchanged
as they control visual state (sprites/crossfade), not visibility.

https://claude.ai/code/session_01ENB9tCSnmqK37EoS7W7bgj
…-Y7rbR

Add comprehensive unit testing guide for Cosmic Shore
Two issues prevented the initial PlayModeSOProtector from working:

1. Race condition: [InitializeOnLoad] registers its callback before
   SOAP ScriptableVariable.OnEnable(), so our restore ran first, then
   SOAP's ResetToInitialValue() re-dirtied every asset with default(T)
   via EditorUtility.SetDirty(). Fix: defer restore with delayCall.

2. Asset discovery: FindAssets("t:ScriptableVariableBase") may return
   empty for abstract base types. Fix: scan all .asset files under
   Assets/_SO_Assets/ via Directory.GetFiles instead.

Also switched from AssetDatabase.Refresh() to per-file ImportAsset
with ForceUpdate to ensure Unity reloads each SO from disk and clears
dirty flags left by SOAP's callbacks.

https://claude.ai/code/session_01TEVgqk3GbdPKYvzfxb275q
The freestyle CinemachineCamera was using the default binding mode, which
interprets FollowOffset in world space — so the camera didn't rotate with
the vessel and ended up at the wrong position/orientation.

Fix: set TrackerSettings.BindingMode = LockToTarget both at creation time
and when applying per-vessel settings. LockToTarget interprets FollowOffset
in the target's local space, matching CustomCameraController's
_followTarget.rotation * _followOffset behavior (camera stays behind the
vessel as it pitches/yaws/rolls).

Also:
- Apply TrackerSettings.PositionDamping from CameraSettingsSO.followSmoothTime
  so follow responsiveness matches the gameplay camera.
- Use dynamicMinDistance directly (matching CustomCameraController.ApplySettings)
  instead of negating it.

https://claude.ai/code/session_01V2hxWA5gN1U4ceF68hoLLP
…anges-PMDLC

Add PlayModeSOProtector to prevent runtime mutations to ScriptableObjects
The default Cinemachine blend linearly interpolates position between the
menu orbit camera and the freestyle camera. Since these cameras are in
very different positions (orbit around crystal vs behind vessel), the
linear path cuts through arbitrary space during the transition.

Fix: set CinemachineBlendHint.InheritPosition on the freestyle vCam.
When it goes live, the camera starts from the current Unity Camera
position (wherever the menu orbit camera was) and CinemachineFollow's
own damping smoothly converges to the correct position behind the vessel.
No linear blend = no weird intermediate positions.

https://claude.ai/code/session_01V2hxWA5gN1U4ceF68hoLLP
The SetVisible extension method is defined on GameObject, not MonoBehaviour.
IntensitySelectButton and PlayerCountButton are MonoBehaviours, so .gameObject
must be used to access the extension.

https://claude.ai/code/session_01ENB9tCSnmqK37EoS7W7bgj
…ain-5NUH3

Replace SetActive with SetVisible for UI visibility management
…priority-BdYGR

Refactor menu camera to use Cinemachine priority blending
CinemachineBlendHint.InheritPosition does not exist in Cinemachine 3.1.2,
causing a compile error. The default CinemachineBrain blend already provides
simple position/rotation lerping between the menu orbit and freestyle follow
cameras, which is the desired behavior.

https://claude.ai/code/session_01Km4HzptY9EXzg1Q9W13AuX
…lity

Add an editor window (Tools > Cosmic Shore > Canvas Group Editor) that
scans the active scene for all CanvasGroup GameObjects and displays them
in a hierarchy tree. Each CanvasGroup node has a toggle to configure
whether it should be visible or hidden at game start, stored in the
scene's InitialPanelStateApplier component.

Features:
- Hierarchy tree matching Unity's scene structure
- Search filter to find panels by name
- Expand/Collapse all, Add All, Show All, Hide All bulk actions
- Click names to ping/select in hierarchy
- Bold labels for tracked panels, "untracked" indicator for others
- Remove (×) button to untrack individual panels
- Clean Nulls to purge deleted references
- Auto-refreshes on hierarchy changes and undo/redo

Also updates InitialPanelStateApplier.Awake() to call SetActive(true)
on deactivated panels before SetVisible, ensuring editor state doesn't
affect runtime initial visibility.

https://claude.ai/code/session_01WRYM3VarPbnxMWqEDs8t5x
Remove CinemachineRotationComposer from the freestyle vCam — it had
its own damping that caused rotation to converge faster than position.
With BindingMode.LockToTarget, the tracker already drives rotation to
match the vessel's orientation (camera Up = vessel Up, camera forward =
vessel forward). Setting RotationDamping = PositionDamping ensures both
reach the vessel at the same time.

https://claude.ai/code/session_01Km4HzptY9EXzg1Q9W13AuX
PanelEntry now has both fields:
- bool startActive: controls GameObject.SetActive at game start
- float startAlpha: controls CanvasGroup.alpha (0-1) at game start

Editor window shows both per row: an active toggle and an alpha float
field. Bulk actions: Activate All, Deactivate All. Column headers added
for clarity.

https://claude.ai/code/session_01WRYM3VarPbnxMWqEDs8t5x
… target

The freestyle camera was not reading SquirrelCameraSettingsSO because
GetComponent<VesselCameraCustomizer>() was called on CameraFollowTarget,
which can be a different Transform than VesselStatus's GameObject.
VesselCameraCustomizer is a [RequireComponent] on VesselStatus, so
fetching it via player.Vessel.VesselStatus.VesselCameraCustomizer is
guaranteed to find it.

Also: FixedCamera mode now uses zero damping (snap) matching
CustomCameraController behavior, while DynamicCamera uses followSmoothTime.

https://claude.ai/code/session_01Km4HzptY9EXzg1Q9W13AuX
claude and others added 30 commits March 5, 2026 08:07
…ntdown

- MultiplayerDomainGamesController: compare readyClientCount against
  NetworkManager.ConnectedClientsIds.Count (humans only) instead of
  gameData.SelectedPlayerCount (which includes AI backfill)
- MultiplayerWildlifeBlitzMiniGame: same fix
- ArcadeConfigSyncManager: use Max(PartyMembers count, ConnectedClients)
  for _expectedHumanCount to guard against stale party data

Previously only the host's click was needed because SelectedPlayerCount
could include AI players who never click Ready, or PartyMembers count
could be stale when the modal opened.

https://claude.ai/code/session_01AyfN2EWC1Z7zL7mRJs33Nk
…n-rpc-OsjWf

Add multiplayer arcade config sync with per-client vessel selection
…rcadeConfigSyncManager

New file from app-shell-polish merge had a [SerializeField] SO_GameList
that should use DI like the other consumers.

https://claude.ai/code/session_01TUBT6px6Mh54VG4WpagZFh
…inject-GUVGK

Inject SO_GameList via DI instead of SerializeField
…on-host clients

On non-host clients, the countdown ClientRpc can arrive before
ClientPlayerVesselInitializer has resolved all player-vessel pairs.
This causes a NullReferenceException at Vessel.StartVessel() because
the Player was added to gameData.Players (in OnNetworkSpawn) before
its Vessel was assigned (in InitializePair).

Add a null guard with warning log, matching the existing pattern in
Player.ResetForPlay() which handles the same transient Netcode state.

https://claude.ai/code/session_01XnzpyCSBAkzLeGiHE2N8mP
…on-host clients

On non-host clients, the countdown ClientRpc can arrive before
ClientPlayerVesselInitializer has resolved all player-vessel pairs.
This causes a NullReferenceException at Vessel.StartVessel() because
the Player was added to gameData.Players (in OnNetworkSpawn) before
its Vessel was assigned (in InitializePair).

Guard at top of method before ToggleActive — a player with no Vessel
should not be marked active. Matches the existing null-Vessel pattern
in Player.ResetForPlay().

https://claude.ai/code/session_01XnzpyCSBAkzLeGiHE2N8mP
…nt MissingReferenceException

The SpawnLoopAsync UniTask continuation could race with GameObject destruction,
accessing transform.position after the object was destroyed. Linking the CTS
with GetCancellationTokenOnDestroy() ensures the token cancels immediately on
destroy, before any queued continuation can run.

https://claude.ai/code/session_017GuQ3FnZurZc8KtZxBHnPC
…nstead of stale PartyMembers

PartyMembers is a SOAP list updated by a 3-second polling loop in
HostConnectionService.RefreshPartyMembersAsync(). When the host
launches a game before the next refresh cycle, PartyMembers only
contains the host (count=1), causing ConfigurePlayerCounts to
compute AI=1 even when a second human player is connected.

Use NetworkManager.ConnectedClientsIds.Count as the ground truth
for connected human players. This is always accurate regardless
of the SOAP refresh timing. Fall back to PartyMembers.Count for
non-host instances.

Also deduplicate the humanCount computation in
SyncAllGameDataForLaunch() to reuse the CurrentPartyHumanCount
property.

https://claude.ai/code/session_01XnzpyCSBAkzLeGiHE2N8mP
…plash during Menu_Main reload

VesselController.DestroyVessel() and Player.DestroyPlayer() silently skipped
destruction for networked objects (IsSpawned guard). This left stale
NetworkObjects registered with Netcode, causing MissingReferenceException
when delta messages arrived for destroyed GameObjects. Now calls
NetworkObject.Despawn(true) on the server before returning.

HostConnectionService.ReloadMenuSceneIfActive() now fades to black before
reloading Menu_Main during the local-to-Relay host transition, and fades
back in when the new scene signals ready via OnClientReady.

https://claude.ai/code/session_017GuQ3FnZurZc8KtZxBHnPC
…ference-nFoyt

Handle null Vessel in StartPlayer to prevent initialization race
…eference-SM2ZL

Link spawn cancellation token to GameObject destruction
Brings in all development work since PR #329 including:
- Quest progression system (intensity-based unlocks, vessel hangar gate)
- Hangar grid + detail panel UI overhaul with vessel unlock flow
- VesselUnlockSystem with crystal currency purchasing
- Cloud data persistence (UGS) for quest/hangar/profile
- Impact effect refactors (overtake, elemental systems)
- Cell membrane exploration
- Toast notification system
- Element pips and elemental bars UI

Conflict resolution strategy:
- Quest/Hangar/Vessel SOs: took development (newer fields)
- Scene files: kept app-shell-polish (newer menu layout)
- ScreenSwitcher: kept app-shell-polish (Reflex DI, arcade CanvasGroup)
- PlayerDataService: merged both (singleton Instance + Reflex DI auth)
- Editor/UI infrastructure: kept app-shell-polish (newer architecture)
- Arcade game assets: took development (latest game mode data)

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
- FriendsPanel: slide-up show with OutBack ease, fade-out hide,
  animated tab transitions with crossfade, staggered friend list
  population (50ms delay per entry), badge punch-scale on request count change
- FriendEntryView: breathing pulse animation on online indicator (InOutSine loop),
  pop-in scale animation on invite-sent indicator (OutBack)
- FriendRequestEntryView: punch-scale on accept, fade-out on decline/cancel
- AddFriendPanel: feedback text scale-in with OutBack ease,
  extra punch on success feedback

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
… merge

Files from the development branch used old namespace conventions
(CosmicShore.App.*, CosmicShore.Game.*, CosmicShore.Models.*,
CosmicShore.Integrations.*, CosmicShore.Services.*) that were
reorganized in app-shell-polish.

Fixes across 19 files:
- CosmicShore.App.Profile → CosmicShore.UI (PlayerDataService)
- CosmicShore.App.Systems.Audio → CosmicShore.Core (AudioSystem)
- CosmicShore.Game.Analytics → CosmicShore.Gameplay (VesselStatsCloudData)
- CosmicShore.Game.IO → CosmicShore.Gameplay (HapticController)
- CosmicShore.Models.Enums → CosmicShore.Data (Element, VesselClassType)
- CosmicShore.Services.Auth → CosmicShore.Core (AuthenticationController)
- CosmicShore.Integrations.PlayFab.* → CosmicShore.Core
- CosmicShore.Utilities → CosmicShore.Utility (typo fix)
- Delete duplicate Models/ScriptableObjects/SO_Captain.cs
- Fix ScriptableObjects/SO_Captain.cs: SO_Ship→SO_Vessel (SO_Ship never existed)
- Change VesselOvertakeBySkimmerEffectSO namespace to CosmicShore.Gameplay
- Change CaptainManager namespace to CosmicShore.Core

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
- Replace SO_Ship → SO_Vessel and SO_ShipList → SO_VesselList across 8 files
- Update game.Captains → game.Vessels and captain.Ship → captain.Vessel for
  SO_ArcadeGame/SO_Captain data model renames
- Remove duplicate ShipSelectionSlot struct from VesselSelectionView.cs
- Create stub classes for missing types: ConnectingPanel,
  DoTweenTypewriterAnimator, ConnectingDotsAnimator, HangarOverviewView
- Comment out Arcade.Instance references (singleton removed in app-shell-polish)

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
Add namespace imports for types that moved during app-shell-polish
reorganization. Files from development reference types like Element,
GameModes, Domains, SO_Element, SO_TrainingGame, CrystalManager,
VesselHUDController, etc. that now live in CosmicShore.Data,
CosmicShore.Gameplay, CosmicShore.ScriptableObjects, CosmicShore.UI,
and CosmicShore.Game.Cinematics namespaces.

28 files updated with correct using directives.

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
- Fix SOAP event subscription pattern (OnRaised) in NetworkCrystalManager,
  EndGameCinematicController, GameModeProgressionService
- Replace AudioSystem.Instance with [Inject] DI in CountdownTimer,
  HangarTrainingModal, EndGameCinematicController
- Add using CosmicShore.Core to all 10 CloudData repository files for UGSKeys
- Add xp field to PlayerProfileData and GetXP/AddXP methods to PlayerDataService
- Fix AuthenticationController.Instance in UGSDataService to use
  AuthenticationService.Instance directly
- Add ElementBars property to SilhouetteController for overtake effect
- Fix SnowChanger.crystalLattice → shards reference
- Fix PlayerDataService Utility.Tools.LogControlWindow path
- Add using CosmicShore.App.Systems for DailyChallengeSystem in 5 UI files
- Fix DoTweenTypewriterAnimator async UniTaskVoid

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
… errors

- Add using CosmicShore.App.Systems.CloudData to PlayerDataService for UGSDataService
- Change instance access to static CaptainManager.OnLoadCaptainData in HangarCaptainsView
- Replace nameof(HangarScreen) with string literal (different namespace)

https://claude.ai/code/session_01S3Fet87FpCsgUg1hJ5Bjux
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants