add music bg and embience
This commit is contained in:
@@ -16,12 +16,12 @@ MonoBehaviour:
|
||||
m_GUID: afbd6624ad1875d42b7e3e6259565fe2
|
||||
m_SerializeEntries:
|
||||
- m_GUID: 4e04b7b226d1cc5478651828e338a72e
|
||||
m_Address: music/ambiencestereo/daynormal2.wav
|
||||
m_Address: ambiencestereo/daynormal2.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 5b2928e4e95f7e949a10194be3a7a609
|
||||
m_Address: "music/2014/\u65B0\u624B\u6751/\u5176\u4ED6\u5730\u533A.mp3"
|
||||
m_Address: "2014/\u65B0\u624B\u6751/\u5176\u4ED6\u5730\u533A.mp3"
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1b73830dda2d83841e5ab247afef32f0802c6fd82fefd3b768af57ee7bc35f17
|
||||
size 118175
|
||||
oid sha256:631a23da0c12055ef55e35b21fac40b752599bdbb43d0d2c1c7fd90674d4b791
|
||||
size 118853
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2311d4689c402744abcee34fcd3d14e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f2e6193e2f88fb48961a9fecd3a405c, type: 3}
|
||||
m_Name: WorldMusicDatabase
|
||||
m_EditorClassIdentifier:
|
||||
entries:
|
||||
- worldTag: 161
|
||||
bgmPath: "2014/\u65B0\u624B\u6751/\u5176\u4ED6\u5730\u533A.mp3 "
|
||||
ambiencePath: ambiencestereo/daynormal2.wav
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7602c1f71697aae42a7751212c5144dc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -243,7 +243,7 @@ namespace BrewMonster.Scripts
|
||||
|
||||
try
|
||||
{
|
||||
var handle = Addressables.LoadAssetAsync<AudioClip>(assetPath);
|
||||
var handle = Addressables.LoadAssetAsync<AudioClip>(assetPath.Trim());
|
||||
await handle.Task;
|
||||
if (handle.OperationException != null)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
using System.Collections;
|
||||
using BrewMonster;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
public class AudioManager : MonoBehaviour
|
||||
{
|
||||
public static AudioManager Instance;
|
||||
|
||||
public AudioSource bgmSource;
|
||||
|
||||
[SerializeField] private AudioMixerGroup _bgmMixerGroup;
|
||||
[SerializeField] private AudioMixerGroup _ambienceMixerGroup;
|
||||
|
||||
private AudioSource _ambienceSource;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
@@ -13,23 +21,51 @@ public class AudioManager : MonoBehaviour
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else Destroy(gameObject);
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
DiscoverAudioSources();
|
||||
}
|
||||
|
||||
private void DiscoverAudioSources()
|
||||
{
|
||||
var sources = GetComponents<AudioSource>();
|
||||
|
||||
if (sources.Length > 0)
|
||||
{
|
||||
bgmSource = sources[0];
|
||||
if (_bgmMixerGroup != null)
|
||||
bgmSource.outputAudioMixerGroup = _bgmMixerGroup;
|
||||
}
|
||||
|
||||
if (sources.Length > 1)
|
||||
{
|
||||
_ambienceSource = sources[1];
|
||||
if (_ambienceMixerGroup != null)
|
||||
_ambienceSource.outputAudioMixerGroup = _ambienceMixerGroup;
|
||||
}
|
||||
}
|
||||
|
||||
// ── BGM ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public void PlayBGM(AudioClip clip, float fadeTime = 1f)
|
||||
{
|
||||
StartCoroutine(FadeInBGM(clip, fadeTime));
|
||||
}
|
||||
|
||||
public void StopBGM(float fadeTime = 1f)
|
||||
{
|
||||
StartCoroutine(FadeOut(fadeTime));
|
||||
StartCoroutine(FadeOutBGM(fadeTime));
|
||||
}
|
||||
|
||||
|
||||
IEnumerator FadeInBGM(AudioClip clip, float fadeTime)
|
||||
{
|
||||
BMLogger.LogError($"HoangDev: FadeInBGM fadeTime {fadeTime} clip: {clip.name}" );
|
||||
if (bgmSource.isPlaying)
|
||||
yield return StartCoroutine(FadeOut(fadeTime));
|
||||
yield return StartCoroutine(FadeOutBGM(fadeTime));
|
||||
|
||||
bgmSource.clip = clip;
|
||||
bgmSource.Play();
|
||||
@@ -38,21 +74,77 @@ public class AudioManager : MonoBehaviour
|
||||
while (t < fadeTime)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
bgmSource.volume = Mathf.Lerp(0, 1, t / fadeTime);
|
||||
bgmSource.volume = Mathf.Lerp(0f, 1f, t / fadeTime);
|
||||
yield return null;
|
||||
}
|
||||
bgmSource.volume = 1f;
|
||||
}
|
||||
|
||||
IEnumerator FadeOut(float fadeTime)
|
||||
IEnumerator FadeOutBGM(float fadeTime)
|
||||
{
|
||||
float startVol = bgmSource.volume;
|
||||
float t = 0f;
|
||||
while (t < fadeTime)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
bgmSource.volume = Mathf.Lerp(startVol, 0, t / fadeTime);
|
||||
bgmSource.volume = Mathf.Lerp(startVol, 0f, t / fadeTime);
|
||||
yield return null;
|
||||
}
|
||||
bgmSource.volume = 0f;
|
||||
bgmSource.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// ── World music (BGM + ambience together) ────────────────────────────────
|
||||
|
||||
public void PlayWorldMusic(AudioClip bgm, AudioClip ambience, float fadeTime = 1f)
|
||||
{
|
||||
if (bgm != null)
|
||||
StartCoroutine(FadeInBGM(bgm, fadeTime));
|
||||
|
||||
if (ambience != null && _ambienceSource != null)
|
||||
StartCoroutine(FadeInAmbience(ambience, fadeTime));
|
||||
}
|
||||
|
||||
public void StopWorldMusic(float fadeTime = 1f)
|
||||
{
|
||||
StopBGM(fadeTime);
|
||||
|
||||
if (_ambienceSource != null && _ambienceSource.isPlaying)
|
||||
StartCoroutine(FadeOutAmbience(fadeTime));
|
||||
}
|
||||
|
||||
// ── Ambience ─────────────────────────────────────────────────────────────
|
||||
|
||||
IEnumerator FadeInAmbience(AudioClip clip, float fadeTime)
|
||||
{
|
||||
if (_ambienceSource.isPlaying)
|
||||
yield return StartCoroutine(FadeOutAmbience(fadeTime));
|
||||
|
||||
_ambienceSource.clip = clip;
|
||||
_ambienceSource.loop = true;
|
||||
_ambienceSource.Play();
|
||||
|
||||
float t = 0f;
|
||||
while (t < fadeTime)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
_ambienceSource.volume = Mathf.Lerp(0f, 1f, t / fadeTime);
|
||||
yield return null;
|
||||
}
|
||||
_ambienceSource.volume = 1f;
|
||||
}
|
||||
|
||||
IEnumerator FadeOutAmbience(float fadeTime)
|
||||
{
|
||||
float startVol = _ambienceSource.volume;
|
||||
float t = 0f;
|
||||
while (t < fadeTime)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
_ambienceSource.volume = Mathf.Lerp(startVol, 0f, t / fadeTime);
|
||||
yield return null;
|
||||
}
|
||||
_ambienceSource.volume = 0f;
|
||||
_ambienceSource.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace BrewMonster.Scripts
|
||||
private async UniTask PlayBackgroundMusic()
|
||||
{
|
||||
// use AddressableManager to load the background music and ambient sound
|
||||
var backgroundMusicClip = await AddressableManager.Instance.LoadAudioClipAsync(backgroundMusicPath.ToLower());
|
||||
var ambientSoundClip = await AddressableManager.Instance.LoadAudioClipAsync(ambientSoundPath.ToLower());
|
||||
var backgroundMusicClip = await AddressableManager.Instance.LoadAudioClipAsync(backgroundMusicPath.Trim());
|
||||
var ambientSoundClip = await AddressableManager.Instance.LoadAudioClipAsync(ambientSoundPath.Trim());
|
||||
|
||||
// play the background music and ambient sound
|
||||
backgroundMusicSource.clip = backgroundMusicClip;
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
/// <summary>
|
||||
/// Lives on the persistent "Music" GameObject alongside AudioManager.
|
||||
/// Waits for the host player to be ready (mirroring TemporaryBackgroundMusic),
|
||||
/// then loads BGM + ambience clips via Addressables and plays them through AudioManager.
|
||||
/// </summary>
|
||||
public class WorldMusicController : MonoBehaviour
|
||||
{
|
||||
public static WorldMusicController Instance;
|
||||
|
||||
[SerializeField] private WorldMusicDatabaseSO _worldMusicDB;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from LoginScreenUI when the player selects a character.
|
||||
/// Kicks off the async setup without blocking the caller.
|
||||
/// </summary>
|
||||
public void InitForWorld(int worldTag)
|
||||
{
|
||||
BMLogger.LogError("HoangDev: InitForWorld worldTag:"+worldTag);
|
||||
AudioManager.Instance.StopBGM(1f);
|
||||
SetupAudioSources(worldTag).Forget();
|
||||
}
|
||||
|
||||
private async UniTask SetupAudioSources(int worldTag)
|
||||
{
|
||||
var hostPlayer = CECGameRun.Instance?.GetHostPlayer();
|
||||
while (hostPlayer == null)
|
||||
{
|
||||
await UniTask.DelayFrame(1);
|
||||
hostPlayer = CECGameRun.Instance?.GetHostPlayer();
|
||||
}
|
||||
|
||||
var entry = _worldMusicDB?.Lookup(worldTag);
|
||||
if (entry == null)
|
||||
{
|
||||
Debug.LogWarning($"[WorldMusicController] No music entry found for worldTag {worldTag}");
|
||||
return;
|
||||
}
|
||||
BMLogger.LogError($"HoangDev: SetupAudioSources entry.bgmPath.ToLower():{entry.bgmPath.ToLower()}");
|
||||
BMLogger.LogError($"HoangDev: SetupAudioSources entry.ambiencePath.ToLower()):{entry.ambiencePath.ToLower()}");
|
||||
var bgmClip = await AddressableManager.Instance.LoadAudioClipAsync(entry.bgmPath.ToLower());
|
||||
var ambienceClip = await AddressableManager.Instance.LoadAudioClipAsync(entry.ambiencePath.ToLower());
|
||||
|
||||
AudioManager.Instance.PlayWorldMusic(bgmClip, ambienceClip, 2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f520c80aab01bbc45aa22010a90dfd66
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
[System.Serializable]
|
||||
public class WorldMusicEntry
|
||||
{
|
||||
[Tooltip("Matches RoleInfo.worldtag from the server (e.g. 161 for a61, 169 for a69)")]
|
||||
public int worldTag;
|
||||
|
||||
[Tooltip("Addressable address for the BGM audio clip")]
|
||||
public string bgmPath;
|
||||
|
||||
[Tooltip("Addressable address for the ambience audio clip")]
|
||||
public string ambiencePath;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "WorldMusicDatabase", menuName = "PerfectWorld/World Music Database")]
|
||||
public class WorldMusicDatabaseSO : ScriptableObject
|
||||
{
|
||||
public List<WorldMusicEntry> entries = new List<WorldMusicEntry>();
|
||||
|
||||
public WorldMusicEntry Lookup(int worldTag)
|
||||
=> entries?.Find(e => e.worldTag == worldTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f2e6193e2f88fb48961a9fecd3a405c
|
||||
@@ -1,439 +1,440 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Login Flow:
|
||||
/// 1. Enter username and password
|
||||
/// 2. Click login button
|
||||
/// 3. Login success, get the list of characters
|
||||
/// 4. Open the select character screen
|
||||
/// </summary>
|
||||
public class LoginScreenUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_InputField _usernameInputField;
|
||||
[SerializeField] private TMP_InputField _passwordInputField;
|
||||
[SerializeField] private Button _loginButton;
|
||||
[SerializeField] private SelecScreenCharacter _selectCharacterScreen;
|
||||
|
||||
private List<RoleInfo> _roleInfos;
|
||||
private List<RoleInfo> _currentRoles;
|
||||
private RoleInfo _pendingCreatedRole;
|
||||
private bool _loginInProgress;
|
||||
bool isDoneWorldRender = false;
|
||||
bool isDoneNPCRender = false;
|
||||
private SynchronizationContext context;
|
||||
public AudioClip loginBGM;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Ensure wrapper created early (Tech3C SDK).
|
||||
_ = Tech3CSDKWrapper.Instance;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
_usernameInputField.gameObject.SetActive(true);
|
||||
_passwordInputField.gameObject.SetActive(true);
|
||||
#else
|
||||
_usernameInputField.gameObject.SetActive(false);
|
||||
_passwordInputField.gameObject.SetActive(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Tech3CSDKWrapper.Instance.SetLoginCallback(OnLoginCallback);
|
||||
Tech3CSDKWrapper.Instance.SetLogoutCallback(OnLogoutCallback);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Tech3CSDKWrapper.Instance.RemoveLoginCallback();
|
||||
Tech3CSDKWrapper.Instance.RemoveLogoutCallback();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
AudioManager.Instance.PlayBGM(loginBGM, 1.5f);
|
||||
_loginButton.onClick.AddListener(OnLoginButtonClicked);
|
||||
context = SynchronizationContext.Current;
|
||||
#if UNITY_EDITOR
|
||||
// only load the username and password from the player prefs if in editor
|
||||
_usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
_passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
#endif
|
||||
|
||||
// Default: login UI first, select-role hidden until login succeeds.
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
|
||||
// ApplyLoginEntry(LogoutFlowState.ConsumeNextLoginEntry());
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (_roleInfos != null)
|
||||
{
|
||||
_selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter, OnCreateCharacterComplete);
|
||||
_roleInfos = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Input.GetKeyUp(KeyCode.LeftAlt))
|
||||
{
|
||||
_usernameInputField.text = "test016";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Tab))
|
||||
{
|
||||
_usernameInputField.text = "test017";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public async void OnLoginButtonClicked()
|
||||
{
|
||||
if (_loginInProgress)
|
||||
{
|
||||
BMLogger.LogWarning("[LoginScreenUI] Login already in progress (ignored click).");
|
||||
return;
|
||||
}
|
||||
|
||||
_loginInProgress = true;
|
||||
if (_loginButton != null) _loginButton.interactable = false;
|
||||
|
||||
// If username or password is empty, use Tech3C SDK login UI.
|
||||
if (string.IsNullOrEmpty(_usernameInputField.text) || string.IsNullOrEmpty(_passwordInputField.text))
|
||||
{
|
||||
// Use Tech3C SDK login UI.
|
||||
bool started = Tech3CSDKWrapper.Instance.Login();
|
||||
if (!started)
|
||||
{
|
||||
// Fallback: manual username/password login (useful in dev if SDK not configured).
|
||||
BMLogger.LogWarning("[LoginScreenUI] Tech3CSDKWrapper.Login() failed, fallback to manual login.");
|
||||
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise use manual username/password login.
|
||||
BMLogger.LogError("[LoginScreenUI] Username/password empty.");
|
||||
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task BeginGameLoginAsync(string username, string password)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
BMLogger.LogError("[LoginScreenUI] Username/password empty.");
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BMLogger.Log("OnLoginButtonClicked");
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", username);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
BMLogger.Log($"[LoginScreenUI] Connecting+login start user='{username}'");
|
||||
await UnityGameSession.Login(username, password, OnLoginComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply how LoginScene should look after a logout flow.
|
||||
/// Call this when LoginScene is already loaded (additive) and you need to switch UI without reloading the scene.
|
||||
/// </summary>
|
||||
public void ApplyLoginEntry(BrewMonster.Network.LogoutFlowState.LoginEntryTarget entry)
|
||||
{
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
|
||||
// Always refresh fields from PlayerPrefs (LogoutAccount clears them).
|
||||
if (_usernameInputField != null) _usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
if (_passwordInputField != null) _passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
|
||||
if (entry == BrewMonster.Network.LogoutFlowState.LoginEntryTarget.SelectRole)
|
||||
{
|
||||
// If we're returning to select role, skip straight to select role without showing login UI again, since we never fully left the game session.
|
||||
OnLoginComplete(true);
|
||||
return;
|
||||
|
||||
// Auto-login to reach Select Role like the original client, without showing Tech3C auth UI again.
|
||||
if (!string.IsNullOrEmpty(_usernameInputField.text) && !string.IsNullOrEmpty(_passwordInputField.text))
|
||||
{
|
||||
BMLogger.Log("[LoginScreenUI] Auto-login triggered (return-to-select-role).");
|
||||
_loginInProgress = true;
|
||||
if (_loginButton != null) _loginButton.interactable = false;
|
||||
_ = BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the login is complete.
|
||||
/// Then get the list of characters
|
||||
/// </summary>
|
||||
private void OnLoginComplete(bool result)
|
||||
{
|
||||
BMLogger.Log($"[LoginScreenUI] OnLoginComplete result={result}");
|
||||
if (!result)
|
||||
{
|
||||
BMLogger.LogError("Login failed");
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
UnityGameSession.GetRoleListAsync(OnGetRoleListComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the list of characters is retrieved.
|
||||
/// Then move to the select character screen
|
||||
/// </summary>
|
||||
private void OnGetRoleListComplete(List<RoleInfo> roleInfos)
|
||||
{
|
||||
if (roleInfos == null)
|
||||
{
|
||||
BMLogger.LogError("OnGetRoleListComplete: roleInfos is null");
|
||||
// Keep whatever is currently shown; don't overwrite UI state with null.
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge pending created role in case backend list hasn't updated yet.
|
||||
if (_pendingCreatedRole != null)
|
||||
{
|
||||
bool exists = false;
|
||||
for (int i = 0; i < roleInfos.Count; i++)
|
||||
{
|
||||
if (roleInfos[i].roleid == _pendingCreatedRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
// Copy list so we don't mutate a list owned elsewhere.
|
||||
var merged = new List<RoleInfo>(roleInfos.Count + 1);
|
||||
merged.AddRange(roleInfos);
|
||||
merged.Add(_pendingCreatedRole);
|
||||
roleInfos = merged;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Backend now includes the role; clear pending.
|
||||
_pendingCreatedRole = null;
|
||||
}
|
||||
}
|
||||
|
||||
BMLogger.Log($"OnGetRoleListComplete: roles={roleInfos.Count}");
|
||||
_roleInfos = roleInfos;
|
||||
_currentRoles = roleInfos;
|
||||
|
||||
// Login flow finished; keep login button disabled (origin-like) once you're at select role.
|
||||
_loginInProgress = false;
|
||||
}
|
||||
|
||||
private void OnClickSelectCharacter(RoleInfo roleInfo)
|
||||
{
|
||||
LoadingSceneController.Instance.ShowLoadingScene(true);
|
||||
UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when a new character is created.
|
||||
/// Refreshes the role list and keeps the character selection screen visible.
|
||||
/// </summary>
|
||||
private void OnCreateCharacterComplete(RoleInfo createdRole)
|
||||
{
|
||||
BMLogger.Log("Character created, refreshing role list...");
|
||||
if (_selectCharacterScreen != null)
|
||||
{
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Ensure the newly created role is visible immediately even if the server role list
|
||||
// hasn't updated yet.
|
||||
if (createdRole != null)
|
||||
{
|
||||
_pendingCreatedRole = createdRole;
|
||||
if (_currentRoles == null)
|
||||
{
|
||||
_currentRoles = new List<RoleInfo>();
|
||||
}
|
||||
|
||||
bool exists = false;
|
||||
for (int i = 0; i < _currentRoles.Count; i++)
|
||||
{
|
||||
if (_currentRoles[i].roleid == createdRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
_currentRoles.Add(createdRole);
|
||||
}
|
||||
|
||||
_roleInfos = _currentRoles;
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError("OnCreateCharacterComplete: createdRole is null (create-role callback returned null)");
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// Immediately requesting the role list after create has been observed to disconnect
|
||||
// in some server builds. We rely on the createdRole callback to update UI instantly.
|
||||
// A server sync can be done later (e.g., next time you open this screen / re-login).
|
||||
}
|
||||
|
||||
private void OnSelectRoleComplete(RoleInfo roleInfo)
|
||||
{
|
||||
context.Post(_ =>
|
||||
{
|
||||
isDoneWorldRender = false;
|
||||
isDoneNPCRender = false;
|
||||
Action actLoadChar = () =>
|
||||
{
|
||||
if (!isDoneNPCRender || !isDoneWorldRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading;
|
||||
SceneLoader.LoadingProgress = 0;
|
||||
#if TESTFAST
|
||||
string nameScene = "LoginScene";
|
||||
SceneManager.UnloadSceneAsync(nameScene);
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
#else
|
||||
string nameScene = UnityGameSession.Instance.GetWorldInstanceName();
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single,
|
||||
(progress) =>
|
||||
{
|
||||
LoadingSceneController.Instance.SetProgress(progress);
|
||||
},
|
||||
(value) =>
|
||||
{
|
||||
isDoneWorldRender = value;
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
|
||||
});
|
||||
#endif
|
||||
}, null);
|
||||
}
|
||||
|
||||
private async void OnEnterWorldComplete()
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
// Request all known packages: 0=Inventory,1=Equipment,2=Task
|
||||
UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2);
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.RequestCheckSecurityPassWd("");
|
||||
// C++ friend_GetList(); required before Add Friend
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.Friend_GetList();
|
||||
}
|
||||
|
||||
//private void OnInventoryReceived(List<InventoryItem> inventoryData)
|
||||
//{
|
||||
// _inventoryUI.DisplayInventory(inventoryData);
|
||||
//}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (_usernameInputField == null)
|
||||
{
|
||||
// find childrend with name "username"
|
||||
_usernameInputField = transform.Find("username").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_passwordInputField == null)
|
||||
{
|
||||
// find childrend with name "password"
|
||||
_passwordInputField = transform.Find("password").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_loginButton == null)
|
||||
{
|
||||
// find childrend with name "LoginBtn"
|
||||
_loginButton = transform.Find("LoginBtn").GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private async void OnLoginCallback(int errorCode, string userId, string password)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log($"Login success -- userId: {userId} - {password}");
|
||||
// UnityGameSession.SetConnectionInfo("103.182.22.52", 29000);
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", userId);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
await BeginGameLoginAsync(userId, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it failed, the userId will be the error message
|
||||
BMLogger.LogError($"Login failed -- errorCode: {errorCode}: {userId}");
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutCallback(int errorCode, string errorMessage)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log("Logout success");
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError($"Logout failed -- errorCode: {errorCode}: {errorMessage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Login Flow:
|
||||
/// 1. Enter username and password
|
||||
/// 2. Click login button
|
||||
/// 3. Login success, get the list of characters
|
||||
/// 4. Open the select character screen
|
||||
/// </summary>
|
||||
public class LoginScreenUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_InputField _usernameInputField;
|
||||
[SerializeField] private TMP_InputField _passwordInputField;
|
||||
[SerializeField] private Button _loginButton;
|
||||
[SerializeField] private SelecScreenCharacter _selectCharacterScreen;
|
||||
|
||||
private List<RoleInfo> _roleInfos;
|
||||
private List<RoleInfo> _currentRoles;
|
||||
private RoleInfo _pendingCreatedRole;
|
||||
private bool _loginInProgress;
|
||||
bool isDoneWorldRender = false;
|
||||
bool isDoneNPCRender = false;
|
||||
private SynchronizationContext context;
|
||||
public AudioClip loginBGM;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Ensure wrapper created early (Tech3C SDK).
|
||||
_ = Tech3CSDKWrapper.Instance;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
_usernameInputField.gameObject.SetActive(true);
|
||||
_passwordInputField.gameObject.SetActive(true);
|
||||
#else
|
||||
_usernameInputField.gameObject.SetActive(false);
|
||||
_passwordInputField.gameObject.SetActive(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Tech3CSDKWrapper.Instance.SetLoginCallback(OnLoginCallback);
|
||||
Tech3CSDKWrapper.Instance.SetLogoutCallback(OnLogoutCallback);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Tech3CSDKWrapper.Instance.RemoveLoginCallback();
|
||||
Tech3CSDKWrapper.Instance.RemoveLogoutCallback();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
AudioManager.Instance.PlayBGM(loginBGM, 1.5f);
|
||||
_loginButton.onClick.AddListener(OnLoginButtonClicked);
|
||||
context = SynchronizationContext.Current;
|
||||
#if UNITY_EDITOR
|
||||
// only load the username and password from the player prefs if in editor
|
||||
_usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
_passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
#endif
|
||||
|
||||
// Default: login UI first, select-role hidden until login succeeds.
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
|
||||
// ApplyLoginEntry(LogoutFlowState.ConsumeNextLoginEntry());
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (_roleInfos != null)
|
||||
{
|
||||
_selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter, OnCreateCharacterComplete);
|
||||
_roleInfos = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Input.GetKeyUp(KeyCode.LeftAlt))
|
||||
{
|
||||
_usernameInputField.text = "test016";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Tab))
|
||||
{
|
||||
_usernameInputField.text = "test017";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public async void OnLoginButtonClicked()
|
||||
{
|
||||
if (_loginInProgress)
|
||||
{
|
||||
BMLogger.LogWarning("[LoginScreenUI] Login already in progress (ignored click).");
|
||||
return;
|
||||
}
|
||||
|
||||
_loginInProgress = true;
|
||||
if (_loginButton != null) _loginButton.interactable = false;
|
||||
|
||||
// If username or password is empty, use Tech3C SDK login UI.
|
||||
if (string.IsNullOrEmpty(_usernameInputField.text) || string.IsNullOrEmpty(_passwordInputField.text))
|
||||
{
|
||||
// Use Tech3C SDK login UI.
|
||||
bool started = Tech3CSDKWrapper.Instance.Login();
|
||||
if (!started)
|
||||
{
|
||||
// Fallback: manual username/password login (useful in dev if SDK not configured).
|
||||
BMLogger.LogWarning("[LoginScreenUI] Tech3CSDKWrapper.Login() failed, fallback to manual login.");
|
||||
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise use manual username/password login.
|
||||
BMLogger.LogError("[LoginScreenUI] Username/password empty.");
|
||||
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task BeginGameLoginAsync(string username, string password)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
BMLogger.LogError("[LoginScreenUI] Username/password empty.");
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BMLogger.Log("OnLoginButtonClicked");
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", username);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
BMLogger.Log($"[LoginScreenUI] Connecting+login start user='{username}'");
|
||||
await UnityGameSession.Login(username, password, OnLoginComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply how LoginScene should look after a logout flow.
|
||||
/// Call this when LoginScene is already loaded (additive) and you need to switch UI without reloading the scene.
|
||||
/// </summary>
|
||||
public void ApplyLoginEntry(BrewMonster.Network.LogoutFlowState.LoginEntryTarget entry)
|
||||
{
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
|
||||
// Always refresh fields from PlayerPrefs (LogoutAccount clears them).
|
||||
if (_usernameInputField != null) _usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
if (_passwordInputField != null) _passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
|
||||
if (entry == BrewMonster.Network.LogoutFlowState.LoginEntryTarget.SelectRole)
|
||||
{
|
||||
// If we're returning to select role, skip straight to select role without showing login UI again, since we never fully left the game session.
|
||||
OnLoginComplete(true);
|
||||
return;
|
||||
|
||||
// Auto-login to reach Select Role like the original client, without showing Tech3C auth UI again.
|
||||
if (!string.IsNullOrEmpty(_usernameInputField.text) && !string.IsNullOrEmpty(_passwordInputField.text))
|
||||
{
|
||||
BMLogger.Log("[LoginScreenUI] Auto-login triggered (return-to-select-role).");
|
||||
_loginInProgress = true;
|
||||
if (_loginButton != null) _loginButton.interactable = false;
|
||||
_ = BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the login is complete.
|
||||
/// Then get the list of characters
|
||||
/// </summary>
|
||||
private void OnLoginComplete(bool result)
|
||||
{
|
||||
BMLogger.Log($"[LoginScreenUI] OnLoginComplete result={result}");
|
||||
if (!result)
|
||||
{
|
||||
BMLogger.LogError("Login failed");
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
UnityGameSession.GetRoleListAsync(OnGetRoleListComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the list of characters is retrieved.
|
||||
/// Then move to the select character screen
|
||||
/// </summary>
|
||||
private void OnGetRoleListComplete(List<RoleInfo> roleInfos)
|
||||
{
|
||||
if (roleInfos == null)
|
||||
{
|
||||
BMLogger.LogError("OnGetRoleListComplete: roleInfos is null");
|
||||
// Keep whatever is currently shown; don't overwrite UI state with null.
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge pending created role in case backend list hasn't updated yet.
|
||||
if (_pendingCreatedRole != null)
|
||||
{
|
||||
bool exists = false;
|
||||
for (int i = 0; i < roleInfos.Count; i++)
|
||||
{
|
||||
if (roleInfos[i].roleid == _pendingCreatedRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
// Copy list so we don't mutate a list owned elsewhere.
|
||||
var merged = new List<RoleInfo>(roleInfos.Count + 1);
|
||||
merged.AddRange(roleInfos);
|
||||
merged.Add(_pendingCreatedRole);
|
||||
roleInfos = merged;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Backend now includes the role; clear pending.
|
||||
_pendingCreatedRole = null;
|
||||
}
|
||||
}
|
||||
|
||||
BMLogger.Log($"OnGetRoleListComplete: roles={roleInfos.Count}");
|
||||
_roleInfos = roleInfos;
|
||||
_currentRoles = roleInfos;
|
||||
|
||||
// Login flow finished; keep login button disabled (origin-like) once you're at select role.
|
||||
_loginInProgress = false;
|
||||
}
|
||||
|
||||
private void OnClickSelectCharacter(RoleInfo roleInfo)
|
||||
{
|
||||
LoadingSceneController.Instance.ShowLoadingScene(true);
|
||||
UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when a new character is created.
|
||||
/// Refreshes the role list and keeps the character selection screen visible.
|
||||
/// </summary>
|
||||
private void OnCreateCharacterComplete(RoleInfo createdRole)
|
||||
{
|
||||
BMLogger.Log("Character created, refreshing role list...");
|
||||
if (_selectCharacterScreen != null)
|
||||
{
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Ensure the newly created role is visible immediately even if the server role list
|
||||
// hasn't updated yet.
|
||||
if (createdRole != null)
|
||||
{
|
||||
_pendingCreatedRole = createdRole;
|
||||
if (_currentRoles == null)
|
||||
{
|
||||
_currentRoles = new List<RoleInfo>();
|
||||
}
|
||||
|
||||
bool exists = false;
|
||||
for (int i = 0; i < _currentRoles.Count; i++)
|
||||
{
|
||||
if (_currentRoles[i].roleid == createdRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
_currentRoles.Add(createdRole);
|
||||
}
|
||||
|
||||
_roleInfos = _currentRoles;
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError("OnCreateCharacterComplete: createdRole is null (create-role callback returned null)");
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// Immediately requesting the role list after create has been observed to disconnect
|
||||
// in some server builds. We rely on the createdRole callback to update UI instantly.
|
||||
// A server sync can be done later (e.g., next time you open this screen / re-login).
|
||||
}
|
||||
|
||||
private void OnSelectRoleComplete(RoleInfo roleInfo)
|
||||
{
|
||||
context.Post(_ =>
|
||||
{
|
||||
isDoneWorldRender = false;
|
||||
isDoneNPCRender = false;
|
||||
Action actLoadChar = () =>
|
||||
{
|
||||
if (!isDoneNPCRender || !isDoneWorldRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading;
|
||||
SceneLoader.LoadingProgress = 0;
|
||||
#if TESTFAST
|
||||
string nameScene = "LoginScene";
|
||||
SceneManager.UnloadSceneAsync(nameScene);
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
WorldMusicController.Instance.InitForWorld(roleInfo.worldtag);
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
#else
|
||||
string nameScene = UnityGameSession.Instance.GetWorldInstanceName();
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single,
|
||||
(progress) =>
|
||||
{
|
||||
LoadingSceneController.Instance.SetProgress(progress);
|
||||
},
|
||||
(value) =>
|
||||
{
|
||||
isDoneWorldRender = value;
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
WorldMusicController.Instance.InitForWorld(roleInfo.worldtag);
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
});
|
||||
#endif
|
||||
}, null);
|
||||
}
|
||||
|
||||
private async void OnEnterWorldComplete()
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
// Request all known packages: 0=Inventory,1=Equipment,2=Task
|
||||
UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2);
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.RequestCheckSecurityPassWd("");
|
||||
// C++ friend_GetList(); required before Add Friend
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.Friend_GetList();
|
||||
}
|
||||
|
||||
//private void OnInventoryReceived(List<InventoryItem> inventoryData)
|
||||
//{
|
||||
// _inventoryUI.DisplayInventory(inventoryData);
|
||||
//}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (_usernameInputField == null)
|
||||
{
|
||||
// find childrend with name "username"
|
||||
_usernameInputField = transform.Find("username").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_passwordInputField == null)
|
||||
{
|
||||
// find childrend with name "password"
|
||||
_passwordInputField = transform.Find("password").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_loginButton == null)
|
||||
{
|
||||
// find childrend with name "LoginBtn"
|
||||
_loginButton = transform.Find("LoginBtn").GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private async void OnLoginCallback(int errorCode, string userId, string password)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log($"Login success -- userId: {userId} - {password}");
|
||||
// UnityGameSession.SetConnectionInfo("103.182.22.52", 29000);
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", userId);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
await BeginGameLoginAsync(userId, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it failed, the userId will be the error message
|
||||
BMLogger.LogError($"Login failed -- errorCode: {errorCode}: {userId}");
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutCallback(int errorCode, string errorMessage)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log("Logout success");
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError($"Logout failed -- errorCode: {errorCode}: {errorMessage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user