using System; using System.Collections; using System.Threading.Tasks; using GameServer.Client; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX using Steamworks; #endif public class friendSearchPrefab : MonoBehaviour { [SerializeField] private Image profileImage; [SerializeField] private Text friendName; [SerializeField] private Text friendSourceInfomation; [SerializeField] private Button addFriendButton; [SerializeField] private Text addFriendButtonText; private Coroutine _avatarLoadRoutine; private Coroutine _buttonCooldownRoutine; private string _defaultAddButtonText; private void Awake() { Text buttonText = ResolveAddButtonText(); _defaultAddButtonText = buttonText != null ? buttonText.text : string.Empty; } private void OnDestroy() { if (_avatarLoadRoutine != null) { StopCoroutine(_avatarLoadRoutine); _avatarLoadRoutine = null; } if (_buttonCooldownRoutine != null) { StopCoroutine(_buttonCooldownRoutine); _buttonCooldownRoutine = null; } } public void Bind(ProfileData profile, bool canAdd, string disabledButtonText, Func onAddClicked, float cooldownSeconds) { if (friendName != null) { friendName.text = profile != null ? NetworkManager.ResolveDisplayName(profile.display_name, profile.steam_id, false) : string.Empty; } if (addFriendButton != null) { addFriendButton.onClick.RemoveAllListeners(); addFriendButton.interactable = canAdd; Text buttonText = ResolveAddButtonText(); if (buttonText != null) { buttonText.text = !canAdd && !string.IsNullOrWhiteSpace(disabledButtonText) ? disabledButtonText : _defaultAddButtonText; } if (canAdd && onAddClicked != null) { addFriendButton.onClick.AddListener(() => { if (_buttonCooldownRoutine != null) { return; } _ = HandleAddClickedAsync(onAddClicked, cooldownSeconds); }); } } if (_avatarLoadRoutine != null) { StopCoroutine(_avatarLoadRoutine); } if (profileImage != null && profile != null) { profileImage.sprite = null; string avatarUrl = NetworkManager.ResolveAvatarUrl(profile.avatar_url, profile.steam_id); _avatarLoadRoutine = StartCoroutine(LoadAvatarRoutine(profile.steam_id, avatarUrl)); } } private async Task HandleAddClickedAsync(Func onAddClicked, float cooldownSeconds) { if (addFriendButton != null) { addFriendButton.interactable = false; } _buttonCooldownRoutine = StartCoroutine(ButtonCooldownRoutine(cooldownSeconds)); await onAddClicked(); } private IEnumerator ButtonCooldownRoutine(float cooldownSeconds) { yield return new WaitForSecondsRealtime(cooldownSeconds); if (addFriendButton != null) { addFriendButton.interactable = true; } _buttonCooldownRoutine = null; } private IEnumerator LoadAvatarRoutine(string steamId, string avatarUrl) { if (profileImage == null) { yield break; } bool loaded = false; if (playerMessagePrefab.TryGetCachedAvatarSprite(steamId, avatarUrl, out Sprite cachedSprite) && cachedSprite != null) { profileImage.sprite = cachedSprite; loaded = true; } if (!loaded && NetworkManager.IsUsableAvatarUrl(avatarUrl) && !avatarUrl.StartsWith(NetworkManager.SteamAvatarUrlPrefix, StringComparison.OrdinalIgnoreCase)) { using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(avatarUrl)) { yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { Texture2D texture = DownloadHandlerTexture.GetContent(request); if (texture != null) { profileImage.sprite = Sprite.Create( texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f)); loaded = true; } } } } if (!loaded) { yield return LoadSteamAvatarRoutine(steamId); } _avatarLoadRoutine = null; } private IEnumerator LoadSteamAvatarRoutine(string steamId) { #if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) yield break; #else if (!SteamManager.Initialized || string.IsNullOrWhiteSpace(steamId) || profileImage == null || !ulong.TryParse(steamId, out ulong rawSteamId)) { yield break; } CSteamID targetSteamId = new CSteamID(rawSteamId); SteamFriends.RequestUserInformation(targetSteamId, false); float deadline = Time.realtimeSinceStartup + 5f; while (Time.realtimeSinceStartup < deadline) { int imageId = SteamFriends.GetLargeFriendAvatar(targetSteamId); if (imageId <= 0) { imageId = SteamFriends.GetMediumFriendAvatar(targetSteamId); } if (imageId > 0 && SteamUtils.GetImageSize(imageId, out uint width, out uint height) && width > 0 && height > 0) { byte[] buffer = new byte[width * height * 4]; if (SteamUtils.GetImageRGBA(imageId, buffer, buffer.Length)) { profileImage.sprite = CreateFlippedSteamAvatarSprite(buffer, (int)width, (int)height); yield break; } } yield return new WaitForSecondsRealtime(0.25f); } #endif } private Text ResolveAddButtonText() { if (addFriendButtonText != null) { return addFriendButtonText; } return addFriendButton != null ? addFriendButton.GetComponentInChildren(true) : null; } private static Sprite CreateFlippedSteamAvatarSprite(byte[] rgbaBuffer, int width, int height) { Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); texture.LoadRawTextureData(rgbaBuffer); texture.Apply(); Texture2D flipped = new Texture2D(width, height, TextureFormat.RGBA32, false); for (int y = 0; y < height; y++) { Color[] pixels = texture.GetPixels(0, y, width, 1); flipped.SetPixels(0, height - 1 - y, width, 1, pixels); } flipped.Apply(); return Sprite.Create(flipped, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f)); } }