Files
bansonic_beta_main/Assets/songsDatabase/SongDlcContentResolver.cs
T
2026-06-30 21:21:30 +08:00

284 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public static class SongDlcContentResolver
{
private const string RuntimeResourcesFolder = "so/songDlcContents";
private const string EditorSearchFolder = "Assets/Resources/so/songDlcContents";
private static SongDlcContentSO[] cachedAllContents;
private static readonly Dictionary<int, List<SongDlcContentSO>> CachedBySongId = new Dictionary<int, List<SongDlcContentSO>>();
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticState()
{
cachedAllContents = null;
CachedBySongId.Clear();
}
public static void InvalidateCache()
{
cachedAllContents = null;
CachedBySongId.Clear();
}
public static SongDlcContentSO GetContent(SongData song)
{
if (song == null)
{
return null;
}
EnsureCacheBuilt();
if (!CachedBySongId.TryGetValue(song.songID, out List<SongDlcContentSO> list) || list == null || list.Count == 0)
{
return null;
}
string preferredDlcKey = song.belongsTo_whichDLC ?? string.Empty;
for (int i = 0; i < list.Count; i++)
{
SongDlcContentSO item = list[i];
if (item == null)
{
continue;
}
if (IsMatchingDlc(item, preferredDlcKey))
{
return item;
}
}
return list[0];
}
public static TextAsset GetChartFile(SongData song, int difficulty)
{
SongDlcContentSO content = GetContent(song);
if (content == null || content.chartOverrides == null)
{
return null;
}
for (int i = 0; i < content.chartOverrides.Count; i++)
{
SongDlcChartOverrideEntry entry = content.chartOverrides[i];
if (entry == null || entry.difficulty != difficulty || entry.chartFile == null)
{
continue;
}
return entry.chartFile;
}
return null;
}
public static AudioClip GetSettlementMusic(SongData song)
{
SongDlcContentSO content = GetContent(song);
if (content != null && content.settlementMusic != null)
{
return content.settlementMusic;
}
dlcData owningDlc = GetOwningDlc(song);
return owningDlc != null ? owningDlc.settlementMusic : null;
}
public static dlcData GetOwningDlc(SongData song)
{
if (song == null)
{
return null;
}
SongDlcContentSO content = GetContent(song);
if (content != null && content.ownerDlc != null)
{
return content.ownerDlc;
}
dlcData[] allDlcs = RuntimeResourcesCache.LoadAllDlcs();
string preferredDlcKey = song.belongsTo_whichDLC ?? string.Empty;
dlcData fallback = null;
for (int i = 0; i < allDlcs.Length; i++)
{
dlcData dlc = allDlcs[i];
if (dlc == null)
{
continue;
}
if (dlc.songList != null && dlc.songList.Contains(song))
{
if (IsMatchingDlc(dlc, preferredDlcKey))
{
return dlc;
}
fallback = fallback ?? dlc;
}
}
return fallback;
}
public static SongDlcContentSO[] LoadAllSongDlcContents()
{
EnsureCacheBuilt();
return cachedAllContents ?? Array.Empty<SongDlcContentSO>();
}
private static bool IsMatchingDlc(SongDlcContentSO content, string preferredDlcKey)
{
if (content == null)
{
return false;
}
if (!string.IsNullOrWhiteSpace(preferredDlcKey))
{
if (!string.IsNullOrWhiteSpace(content.sourceDlcId) &&
string.Equals(content.sourceDlcId.Trim(), preferredDlcKey.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (content.ownerDlc != null)
{
if (string.Equals(content.ownerDlc.dlcName ?? string.Empty, preferredDlcKey.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (string.Equals(content.ownerDlc.dlcID.ToString(), preferredDlcKey.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
}
private static bool IsMatchingDlc(dlcData dlc, string preferredDlcKey)
{
if (dlc == null || string.IsNullOrWhiteSpace(preferredDlcKey))
{
return false;
}
string safeKey = preferredDlcKey.Trim();
return string.Equals(dlc.dlcName ?? string.Empty, safeKey, StringComparison.OrdinalIgnoreCase)
|| string.Equals(dlc.dlcID.ToString(), safeKey, StringComparison.OrdinalIgnoreCase);
}
private static void EnsureCacheBuilt()
{
if (cachedAllContents != null)
{
return;
}
cachedAllContents = LoadAllContentsInternal();
CachedBySongId.Clear();
for (int i = 0; i < cachedAllContents.Length; i++)
{
SongDlcContentSO content = cachedAllContents[i];
if (content == null || content.songId <= 0)
{
continue;
}
if (!CachedBySongId.TryGetValue(content.songId, out List<SongDlcContentSO> list) || list == null)
{
list = new List<SongDlcContentSO>();
CachedBySongId[content.songId] = list;
}
list.Add(content);
}
foreach (KeyValuePair<int, List<SongDlcContentSO>> pair in CachedBySongId)
{
pair.Value.Sort(CompareContent);
}
}
private static int CompareContent(SongDlcContentSO left, SongDlcContentSO right)
{
if (ReferenceEquals(left, right))
{
return 0;
}
if (left == null)
{
return 1;
}
if (right == null)
{
return -1;
}
int ownerCompare = string.CompareOrdinal(left.sourceDlcId ?? string.Empty, right.sourceDlcId ?? string.Empty);
if (ownerCompare != 0)
{
return ownerCompare;
}
return string.CompareOrdinal(left.GetResolvedContentId(), right.GetResolvedContentId());
}
private static SongDlcContentSO[] LoadAllContentsInternal()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
string[] searchFolders = { EditorSearchFolder };
string[] guids = AssetDatabase.FindAssets("t:SongDlcContentSO", searchFolders);
if (guids != null && guids.Length > 0)
{
List<SongDlcContentSO> result = new List<SongDlcContentSO>(guids.Length);
for (int i = 0; i < guids.Length; i++)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
SongDlcContentSO content = AssetDatabase.LoadAssetAtPath<SongDlcContentSO>(assetPath);
if (content != null)
{
result.Add(content);
}
}
return result.ToArray();
}
string[] fallbackGuids = AssetDatabase.FindAssets("t:SongDlcContentSO");
List<SongDlcContentSO> fallback = new List<SongDlcContentSO>(fallbackGuids.Length);
for (int i = 0; i < fallbackGuids.Length; i++)
{
string assetPath = AssetDatabase.GUIDToAssetPath(fallbackGuids[i]);
SongDlcContentSO content = AssetDatabase.LoadAssetAtPath<SongDlcContentSO>(assetPath);
if (content != null)
{
fallback.Add(content);
}
}
return fallback.ToArray();
}
#endif
return RuntimeResourcesCache.LoadAllSongDlcContents() ?? Array.Empty<SongDlcContentSO>();
}
}