Files
bansonic_beta_main/Assets/playerDisplay/UI_Player.cs
T

509 lines
14 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Steamworks;
using UnityEngine;
using UnityEngine.UI;
public class UI_Player : MonoBehaviour
{
private const string FirstLaunchDatePrefKey = "player.first_launch_date";
private const string SongResourcesPath = "song_songIndex";
private const string VersionLabel = "\u5185\u90e8\u6d4b\u8bd5v207b35";
private const string ChannelLabel = "Steam";
private const float MaxDisplayedRksForSlider = 100f;
private static readonly Color SteamOnlineColor = new Color32(20, 120, 45, 255);
[Header("prefab")]
public GameObject pInfoPrefab;
public Transform pInfoParent;
[Header("so")]
[SerializeField] private Player_SO pSO;
[Header("uData")]
public Image userProfileImage;
public Text userNameText;
public Text userIDText;
public Text user_registDate;
[Header("uSource")]
public Text userSource;
[Header("uRecord")]
public Text fcAmount;
public Text firstFCsong;
public Text totalPlayTime;
[Header("uRks")]
public Slider uRksSlider;
public Text uRksText;
[Header("buttons")]
public Button quitButton;
private readonly List<GameObject> spawnedInfoEntries = new List<GameObject>();
private Color defaultInfoColor = Color.black;
private void Start()
{
BindQuitButton();
PlayerRksService.OnRksChanged += HandleRksChanged;
StartCoroutine(InitializeAsync());
}
private void OnEnable()
{
RefreshRksUi();
}
private void OnDestroy()
{
PlayerRksService.OnRksChanged -= HandleRksChanged;
if (quitButton != null)
{
quitButton.onClick.RemoveListener(ClosePanel);
}
}
private void BindQuitButton()
{
if (quitButton == null)
{
return;
}
quitButton.onClick.RemoveListener(ClosePanel);
quitButton.onClick.AddListener(ClosePanel);
}
private void ClosePanel()
{
gameObject.SetActive(false);
}
private IEnumerator InitializeAsync()
{
StoreOwnershipLedger.EnsureInstance().InitializeIfNeeded();
StoreOwnershipLedger.EnsureInstance().ForceSyncMirrorFlags();
PlayerRksService.EnsureLoaded(pSO);
string registerDate = EnsureFirstLaunchDate();
UserInfoSnapshot snapshot = BuildUserInfoSnapshot(registerDate);
ApplyLegacyTextMirrors(snapshot);
RebuildInfoEntries(snapshot);
RefreshRksUi();
yield return null;
yield return StartCoroutine(LoadSteamProfileAsync(snapshot.isSteamOnline));
}
private void HandleRksChanged(float _)
{
RefreshRksUi();
}
private void RefreshRksUi()
{
float currentRks = PlayerRksService.RefreshAndPersist(pSO);
if (uRksText != null)
{
uRksText.text = currentRks.ToString("F2");
}
if (uRksSlider != null)
{
uRksSlider.minValue = 0f;
uRksSlider.maxValue = MaxDisplayedRksForSlider;
uRksSlider.value = Mathf.Clamp(currentRks, 0f, MaxDisplayedRksForSlider);
}
}
private string EnsureFirstLaunchDate()
{
string playerPrefsDate = PlayerPrefs.GetString(FirstLaunchDatePrefKey, string.Empty);
string finalDate = !string.IsNullOrWhiteSpace(playerPrefsDate)
? playerPrefsDate
: DateTime.Now.ToString("yyyy-MM-dd");
if (playerPrefsDate != finalDate)
{
PlayerPrefs.SetString(FirstLaunchDatePrefKey, finalDate);
PlayerPrefs.Save();
}
if (pSO != null && pSO.firstLaunchDate != finalDate)
{
pSO.firstLaunchDate = finalDate;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
UnityEditor.EditorUtility.SetDirty(pSO);
}
#endif
}
return finalDate;
}
private UserInfoSnapshot BuildUserInfoSnapshot(string registerDate)
{
SongStats songStats = CollectSongStats();
return new UserInfoSnapshot
{
registerDate = registerDate,
ownedHeroCount = CountOwnedHeroes(),
ownedSongCount = songStats.ownedSongCount,
totalGameEnterCount = songStats.totalGameEnterCount,
totalPlaySeconds = songStats.totalPlaySeconds,
isSteamOnline = IsSteamOnline()
};
}
private void ApplyLegacyTextMirrors(UserInfoSnapshot snapshot)
{
if (user_registDate != null)
{
user_registDate.text = snapshot.registerDate;
}
if (userSource != null)
{
userSource.text = ChannelLabel;
userSource.color = snapshot.isSteamOnline ? SteamOnlineColor : Color.black;
}
if (totalPlayTime != null)
{
totalPlayTime.text = FormatPlayTime(snapshot.totalPlaySeconds);
}
if (fcAmount != null && string.IsNullOrWhiteSpace(fcAmount.text))
{
fcAmount.text = "-";
}
if (firstFCsong != null && string.IsNullOrWhiteSpace(firstFCsong.text))
{
firstFCsong.text = "-";
}
}
private void RebuildInfoEntries(UserInfoSnapshot snapshot)
{
ClearInfoEntries();
CacheDefaultInfoColor();
SpawnInfoEntry("\u6ce8\u518c\u65e5\u671f", snapshot.registerDate);
SpawnInfoEntry("\u62e5\u6709\u89d2\u8272\u6570\u91cf", snapshot.ownedHeroCount.ToString());
SpawnInfoEntry("\u62e5\u6709\u6b4c\u66f2\u6570\u91cf", snapshot.ownedSongCount.ToString());
SpawnInfoEntry("\u603b\u6e38\u620f\u6b21\u6570", snapshot.totalGameEnterCount.ToString());
SpawnInfoEntry("\u6e38\u73a9\u603b\u65f6\u957f", FormatPlayTime(snapshot.totalPlaySeconds));
SpawnInfoEntry("\u6e20\u9053", ChannelLabel, snapshot.isSteamOnline ? SteamOnlineColor : defaultInfoColor);
SpawnInfoEntry("\u7248\u672c", VersionLabel);
}
private void ClearInfoEntries()
{
for (int i = 0; i < spawnedInfoEntries.Count; i++)
{
if (spawnedInfoEntries[i] != null)
{
Destroy(spawnedInfoEntries[i]);
}
}
spawnedInfoEntries.Clear();
}
private void CacheDefaultInfoColor()
{
if (pInfoPrefab == null)
{
return;
}
pInfoPrefab sample = pInfoPrefab.GetComponent<pInfoPrefab>();
if (sample != null && sample.this_iDetail != null)
{
defaultInfoColor = sample.this_iDetail.color;
}
}
private void SpawnInfoEntry(string title, string detail, Color? detailColor = null)
{
if (pInfoPrefab == null || pInfoParent == null)
{
return;
}
GameObject entryObject = Instantiate(pInfoPrefab, pInfoParent);
spawnedInfoEntries.Add(entryObject);
pInfoPrefab entry = entryObject.GetComponent<pInfoPrefab>();
if (entry == null)
{
return;
}
if (entry.this_iTitle != null)
{
entry.this_iTitle.text = title;
}
if (entry.this_iDetail != null)
{
entry.this_iDetail.text = detail;
entry.this_iDetail.color = detailColor ?? defaultInfoColor;
}
}
private static int CountOwnedHeroes()
{
AllyHero_SO[] loadedHeroes = Resources.LoadAll<AllyHero_SO>(string.Empty);
HashSet<int> uniqueHeroIds = new HashSet<int>();
int ownedCount = 0;
AllyHeroDeployLedger ledger = AllyHeroDeployLedger.EnsureInstance();
ledger.InitializeIfNeeded();
for (int i = 0; i < loadedHeroes.Length; i++)
{
AllyHero_SO hero = loadedHeroes[i];
if (hero == null || !uniqueHeroIds.Add(hero.ally_heroID))
{
continue;
}
hero.ally_battleDeployCount = ledger.GetDeployCount(hero.ally_heroID);
if (hero.isUnlocked)
{
ownedCount++;
}
}
return ownedCount;
}
private static SongStats CollectSongStats()
{
SongData[] songs = Resources.LoadAll<SongData>(SongResourcesPath);
HashSet<int> uniqueSongIds = new HashSet<int>();
SongStats stats = new SongStats();
for (int i = 0; i < songs.Length; i++)
{
SongData song = songs[i];
if (song == null || !uniqueSongIds.Add(song.songID))
{
continue;
}
song.LoadPersistent();
if (song.isUnlocked)
{
stats.ownedSongCount++;
}
stats.totalGameEnterCount += Mathf.Max(0, song.game_enterTimes);
stats.totalPlaySeconds += Math.Max(0f, song.time_totalPlayingTime);
}
return stats;
}
private static string FormatPlayTime(double totalSeconds)
{
TimeSpan span = TimeSpan.FromSeconds(Math.Max(0d, totalSeconds));
if (span.TotalHours >= 1d)
{
return string.Format("{0:D2}\u5c0f\u65f6{1:D2}\u5206\u949f", (int)span.TotalHours, span.Minutes);
}
if (span.TotalMinutes >= 1d)
{
return string.Format("{0:D2}\u5206\u949f{1:D2}\u79d2", (int)span.TotalMinutes, span.Seconds);
}
return string.Format("{0:D2}\u79d2", Math.Max(0, span.Seconds));
}
private IEnumerator LoadSteamProfileAsync(bool isSteamOnline)
{
int initRetry = 0;
while (initRetry < 25 && !SteamManager.Initialized)
{
initRetry++;
yield return new WaitForSecondsRealtime(0.2f);
}
if (!SteamManager.Initialized)
{
ApplySteamUnavailable();
yield break;
}
int retryCount = 0;
while (retryCount < 20)
{
if (TryPopulateSteamProfile(isSteamOnline))
{
yield break;
}
retryCount++;
yield return new WaitForSecondsRealtime(0.25f);
}
ApplySteamUnavailable();
}
private void ApplySteamUnavailable()
{
if (userNameText != null)
{
userNameText.text = "Steam Unavailable";
}
if (userIDText != null)
{
userIDText.text = "-";
}
if (userSource != null)
{
userSource.text = ChannelLabel;
userSource.color = Color.black;
}
}
private static bool IsSteamOnline()
{
if (!SteamManager.Initialized)
{
return false;
}
try
{
return SteamFriends.GetPersonaState() != EPersonaState.k_EPersonaStateOffline;
}
catch
{
return false;
}
}
private bool TryPopulateSteamProfile(bool isSteamOnline)
{
try
{
CSteamID steamId = SteamUser.GetSteamID();
string personaName = SteamFriends.GetPersonaName();
if (!steamId.IsValid() || string.IsNullOrWhiteSpace(personaName))
{
return false;
}
if (userNameText != null)
{
userNameText.text = personaName;
}
if (userIDText != null)
{
userIDText.text = steamId.m_SteamID.ToString();
}
if (userSource != null)
{
userSource.text = ChannelLabel;
userSource.color = isSteamOnline ? SteamOnlineColor : Color.black;
}
return TryApplySteamAvatar(steamId) || userProfileImage == null;
}
catch
{
return false;
}
}
private bool TryApplySteamAvatar(CSteamID steamId)
{
if (userProfileImage == null)
{
return true;
}
int imageId = SteamFriends.GetLargeFriendAvatar(steamId);
if (imageId == -1)
{
return false;
}
if (imageId == 0)
{
imageId = SteamFriends.GetMediumFriendAvatar(steamId);
}
if (imageId < 0)
{
return false;
}
uint width;
uint height;
if (!SteamUtils.GetImageSize(imageId, out width, out height) || width == 0 || height == 0)
{
return false;
}
byte[] imageBuffer = new byte[width * height * 4];
if (!SteamUtils.GetImageRGBA(imageId, imageBuffer, imageBuffer.Length))
{
return false;
}
Texture2D sourceTexture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false);
sourceTexture.LoadRawTextureData(imageBuffer);
sourceTexture.Apply();
Texture2D flippedTexture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false);
for (int y = 0; y < (int)height; y++)
{
Color[] rowPixels = sourceTexture.GetPixels(0, y, (int)width, 1);
flippedTexture.SetPixels(0, (int)height - 1 - y, (int)width, 1, rowPixels);
}
flippedTexture.Apply();
userProfileImage.sprite = Sprite.Create(
flippedTexture,
new Rect(0, 0, flippedTexture.width, flippedTexture.height),
new Vector2(0.5f, 0.5f));
return true;
}
private struct UserInfoSnapshot
{
public string registerDate;
public int ownedHeroCount;
public int ownedSongCount;
public int totalGameEnterCount;
public double totalPlaySeconds;
public bool isSteamOnline;
}
private struct SongStats
{
public int ownedSongCount;
public int totalGameEnterCount;
public double totalPlaySeconds;
}
}