Files
soccar2d/Assets/Scripts/MainMenuManager.cs
T
2026-05-16 05:13:34 +05:30

337 lines
9.8 KiB
C#

using System.Collections;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class MainMenuManager : MonoBehaviour
{
public const string MainMenuSceneName = "MainMenu";
const string CryptoAddressPrefsKey = "MainMenu.CryptoAddress";
/// <summary>500 CC fee to process a withdrawal.</summary>
const int WithdrawalFeeCc = 500;
/// <summary>$20 USD = 20.0 RC, stored in DB as 80 rc coins (4 coins per 1.0 RC).</summary>
const int MinimumWithdrawalRcCoins = 80;
[Header("Stats")]
[SerializeField] private GameObject statsPanel;
[SerializeField] private TMP_Text usernameText;
[SerializeField] private TMP_Text ccText;
[SerializeField] private TMP_Text rcText;
[Header("Screens")]
public GameObject mainMenuScreen;
public GameObject gameModesScreen;
public GameObject dummyBuyScreen;
public GameObject withdrawalScreen;
[Header("Play")]
public Button btnPlay;
public TMP_Text rcPlayText;
public TMP_Text entryFeeTxt;
public TMP_Text rcPrizeTxt;
[Header("Dummy Buy")]
public Button btnBuyUsd5;
public Button btnBuyUsd20;
public Button btnBuyUsd50;
[Header("Withdrawal")]
public Button btnWithdrawal;
public Button btnPaste;
public TMP_InputField inputCryptoAddress;
public TMP_Text txtWithdrawStatus;
private bool isCoinBuyInProgress;
[Header("Audio")]
public ToggleButton toggleSfx;
public ToggleButton toggleMusic;
/// <summary>Default play cost (coin units) if <c>/settings</c> is not loaded yet.</summary>
const int FallbackEntryFeeCoins = 21;
int _matchEntryFeeCoins = FallbackEntryFeeCoins;
public static MainMenuManager instance;
void Awake()
{
if(LoginManager.instance==null){
SceneManager.LoadScene(0);
}
instance = this;
}
void Start()
{
LoginManager.OnUserDataUpdated += OnUserUpdated;
usernameText.text = "";
ccText.text = "";
rcText.text = "";
LoginManager.instance.GetUserData((success, error, user) => {
if (success)
{
OnUserUpdated(user);
}
else
{
if (btnPlay != null)
btnPlay.interactable = false;
if (rcPlayText != null)
rcPlayText.text = string.IsNullOrEmpty(error) ? "Could not load profile. Try again." : error;
}
});
btnBuyUsd5.onClick.AddListener(() => OnBuy(RcPack.Usd5));
btnBuyUsd20.onClick.AddListener(() => OnBuy(RcPack.Usd20));
btnBuyUsd50.onClick.AddListener(() => OnBuy(RcPack.Usd50));
if (inputCryptoAddress != null)
{
inputCryptoAddress.text = PlayerPrefs.GetString(CryptoAddressPrefsKey, string.Empty);
inputCryptoAddress.onValueChanged.AddListener(OnCryptoAddressChanged);
}
UpdateWithdrawalStatus();
if (btnPaste != null)
btnPaste.onClick.AddListener(OnPasteFromClipboard);
btnPlay.onClick.AddListener(OnPlay);
toggleSfx.onToggleValueChanged.AddListener(OnToggleSfx);
toggleMusic.onToggleValueChanged.AddListener(OnToggleMusic);
toggleSfx.SetIsOn(AudioManager.instance.IsSFXOn());
toggleMusic.SetIsOn(AudioManager.instance.IsMusicOn());
if (!LevelLoadManager.BlocksMainMenuSettingsBootstrap)
StartCoroutine(CoBootstrapSettingsWithoutLoader());
}
void OnDestroy(){
LoginManager.OnUserDataUpdated -= OnUserUpdated;
toggleSfx.onToggleValueChanged.RemoveListener(OnToggleSfx);
toggleMusic.onToggleValueChanged.RemoveListener(OnToggleMusic);
}
void OnToggleSfx(bool isOn)
{
AudioManager.instance.SetSfxVolume(isOn ? 1f : 0f);
}
void OnToggleMusic(bool isOn)
{
AudioManager.instance.SetMusicVolume(isOn ? 1f : 0f);
}
void OnPlay()
{
if (LoginManager.CurrentUser == null)
{
Debug.LogError("Play blocked: user profile not loaded.");
return;
}
if (LoginManager.CurrentUser.rc < _matchEntryFeeCoins)
{
Debug.LogError("Not enough RC to play");
return;
}
if (CupidLobby.instance == null)
{
Debug.LogError("Play blocked: CupidLobby is missing from this scene.");
return;
}
CupidLobby.instance.Matchmake();
}
void OnCryptoAddressChanged(string value)
{
PlayerPrefs.SetString(CryptoAddressPrefsKey, value ?? string.Empty);
PlayerPrefs.Save();
UpdateWithdrawalStatus();
}
void UpdateWithdrawalStatus(UserData user = null)
{
if (txtWithdrawStatus == null)
return;
UserData u = user ?? LoginManager.CurrentUser;
if (u == null)
return;
if (inputCryptoAddress != null && string.IsNullOrWhiteSpace(inputCryptoAddress.text))
{
txtWithdrawStatus.text = "Enter a valid wallet address to withdraw safely.";
return;
}
if (u.rc < MinimumWithdrawalRcCoins)
{
txtWithdrawStatus.text = "Your RC balance is below the minimum withdrawal amount ($20 USD / 20.0 RC).";
return;
}
if (u.cc < WithdrawalFeeCc)
{
txtWithdrawStatus.text = "Withdrawal costs 500 CC. Your CC balance is below 500 CC.";
return;
}
txtWithdrawStatus.text = string.Empty;
}
void OnPasteFromClipboard()
{
if (inputCryptoAddress == null)
return;
string clip = GUIUtility.systemCopyBuffer;
if (!string.IsNullOrEmpty(clip))
inputCryptoAddress.text = clip;
}
void OnBuy(string packId){
if (isCoinBuyInProgress)
return;
isCoinBuyInProgress = true;
SetCoinBuyButtonsInteractable(false);
LoginManager.instance.PurchaseRcPack(packId, (success, error) => {
if(success){
OnUserUpdated(LoginManager.CurrentUser);
AudioManager.instance.PlayCoinsSfx();
}
isCoinBuyInProgress = false;
SetCoinBuyButtonsInteractable(true);
});
}
void SetCoinBuyButtonsInteractable(bool interactable)
{
if (btnBuyUsd5 != null)
btnBuyUsd5.interactable = interactable;
if (btnBuyUsd20 != null)
btnBuyUsd20.interactable = interactable;
if (btnBuyUsd50 != null)
btnBuyUsd50.interactable = interactable;
}
// Update is called once per frame
void Update()
{
}
void OnUserUpdated(UserData user){
usernameText.text = user.username;
ccText.text = user.cc.ToString("N0") + " CC";
rcText.text = CoinHelper.FormatString(user.rc) + " RC";
if (LoginManager.CurrentUser.rc < _matchEntryFeeCoins)
{
rcPlayText.text = "Not enough RC to play";
btnPlay.interactable = false;
}
else
{
rcPlayText.text = "";
btnPlay.interactable = true;
}
UpdateWithdrawalStatus(user);
}
/// <summary>Called by <see cref="LevelLoadManager"/> so the loading overlay stays until matchmaker settings are refreshed.</summary>
public IEnumerator FinishLoadingScreenAndApplySettings()
{
yield return CoReadyMatchmakerSettingsThenApply();
}
IEnumerator CoBootstrapSettingsWithoutLoader()
{
yield return null;
yield return CoReadyMatchmakerSettingsThenApply();
}
IEnumerator CoReadyMatchmakerSettingsThenApply()
{
const float endpointWaitSec = 30f;
float deadline = Time.realtimeSinceStartup + endpointWaitSec;
while (!Cupid.IsEndpointReady && Time.realtimeSinceStartup < deadline)
yield return null;
yield return Cupid.CoRefreshSettings();
ApplyMatchmakerFeeUi();
if (LoginManager.CurrentUser != null)
OnUserUpdated(LoginManager.CurrentUser);
}
void ApplyMatchmakerFeeUi()
{
if (Cupid.Settings == null)
{
_matchEntryFeeCoins = FallbackEntryFeeCoins;
if (entryFeeTxt != null)
entryFeeTxt.text = "—";
if (rcPrizeTxt != null)
rcPrizeTxt.text = "—";
return;
}
CupidSettings s = Cupid.Settings;
_matchEntryFeeCoins = s.entry_fee > 0 ? s.entry_fee : FallbackEntryFeeCoins;
if (entryFeeTxt != null)
{
entryFeeTxt.text = s.entry_fee > 0
? CoinHelper.FormatString(s.entry_fee) + " RC"
: "—";
}
if (rcPrizeTxt != null)
{
rcPrizeTxt.text = s.rc_prize > 0
? CoinHelper.FormatString(s.rc_prize) + " RC"
: "—";
}
}
public void ShowMainMenuScreen(){
statsPanel.SetActive(true);
mainMenuScreen.SetActive(true);
gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(false);
}
public void ShowGameModesScreen(){
statsPanel.SetActive(true);
mainMenuScreen.SetActive(false);
gameModesScreen.SetActive(true);
dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(false);
}
public void ShowDummyBuyScreen(){
statsPanel.SetActive(false);
mainMenuScreen.SetActive(false);
gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(true);
withdrawalScreen.SetActive(false);
}
public void ShowWithdrawalScreen(){
statsPanel.SetActive(false);
mainMenuScreen.SetActive(false);
gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(true);
UpdateWithdrawalStatus();
}
}