using System; using System.Collections; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using GameServer.Client; #if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) #define FRIEND_DISABLE_STEAMWORKS #endif #if !FRIEND_DISABLE_STEAMWORKS using Steamworks; #endif public class friendCardPrefab : MonoBehaviour { [SerializeField] private Image profileBorder; [SerializeField] private Image friendProfile; [SerializeField] private Text friendName; [SerializeField] private Text friendStatus; [SerializeField] private Button friendDetails; [SerializeField] private Button startPersonalConversation; [SerializeField] private Toggle isStarFriend; [SerializeField] private Image friendOffline_blackMask; [Header("offline heibai")] [SerializeField] private Material offline_material; private Material _profileBorderMaterial; private Material _friendProfileMaterial; private Coroutine _avatarLoadRoutine; private Sprite _runtimeAvatarSprite; private Texture2D _runtimeAvatarTexture; private Texture2D _runtimeSteamAvatarTexture; private Texture2D _runtimeSteamAvatarFlippedTexture; private string _steamId; private Action _starChanged; private Action _openDetails; private Action _openPrivateConversation; private bool _bindingToggle; private void Awake() { _profileBorderMaterial = profileBorder != null ? profileBorder.material : null; _friendProfileMaterial = friendProfile != null ? friendProfile.material : null; } private void OnDestroy() { if (_avatarLoadRoutine != null) { StopCoroutine(_avatarLoadRoutine); _avatarLoadRoutine = null; } ReleaseRuntimeAvatarResources(); } public void Bind(FriendCardViewData data, Action onStarChanged, Action onOpenDetails, Action onOpenPrivateConversation) { _steamId = data != null ? data.SteamId : string.Empty; _starChanged = onStarChanged; _openDetails = onOpenDetails; _openPrivateConversation = onOpenPrivateConversation; if (friendName != null) { friendName.text = data != null ? data.DisplayName ?? string.Empty : string.Empty; } if (friendStatus != null) { friendStatus.text = data != null ? data.StatusText ?? string.Empty : string.Empty; } ApplyOnlineVisualState(data != null && data.IsOnline); if (isStarFriend != null) { isStarFriend.onValueChanged.RemoveAllListeners(); _bindingToggle = true; isStarFriend.isOn = data != null && data.IsStarred; _bindingToggle = false; isStarFriend.onValueChanged.AddListener(HandleStarToggleChanged); } if (friendDetails != null) { friendDetails.onClick.RemoveAllListeners(); friendDetails.onClick.AddListener(HandleOpenDetails); } if (startPersonalConversation != null) { startPersonalConversation.onClick.RemoveAllListeners(); startPersonalConversation.onClick.AddListener(HandleStartPrivateConversation); } if (_avatarLoadRoutine != null) { StopCoroutine(_avatarLoadRoutine); } _avatarLoadRoutine = StartCoroutine(LoadAvatarRoutine(data)); } private void HandleStarToggleChanged(bool isOn) { if (_bindingToggle) { return; } _starChanged?.Invoke(_steamId, isOn); } private void HandleOpenDetails() { _openDetails?.Invoke(_steamId); } private void HandleStartPrivateConversation() { _openPrivateConversation?.Invoke(_steamId); } private void ApplyOnlineVisualState(bool isOnline) { if (friendOffline_blackMask != null) { friendOffline_blackMask.gameObject.SetActive(!isOnline); } Material borderMaterial = isOnline ? _profileBorderMaterial : offline_material; Material profileMaterial = isOnline ? _friendProfileMaterial : offline_material; if (profileBorder != null) { profileBorder.material = borderMaterial; } if (friendProfile != null) { friendProfile.material = profileMaterial; } } private IEnumerator LoadAvatarRoutine(FriendCardViewData data) { if (friendProfile == null || data == null) { yield break; } ReleaseRuntimeAvatarResources(); string resolvedAvatarUrl = NetworkManager.ResolveAvatarUrl(data.AvatarUrl, data.SteamId); bool loaded = false; if (NetworkManager.IsUsableAvatarUrl(resolvedAvatarUrl) && !resolvedAvatarUrl.StartsWith(NetworkManager.SteamAvatarUrlPrefix, StringComparison.OrdinalIgnoreCase)) { using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(resolvedAvatarUrl)) { yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { Texture2D texture = DownloadHandlerTexture.GetContent(request); if (texture != null) { _runtimeAvatarTexture = texture; _runtimeAvatarSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); friendProfile.sprite = _runtimeAvatarSprite; loaded = true; } } } } if (!loaded) { yield return LoadSteamAvatarRoutine(data.SteamId); } _avatarLoadRoutine = null; } private IEnumerator LoadSteamAvatarRoutine(string steamId) { #if FRIEND_DISABLE_STEAMWORKS yield break; #else if (!SteamManager.Initialized || string.IsNullOrWhiteSpace(steamId) || friendProfile == null || !ulong.TryParse(steamId, out ulong rawSteamId)) { yield break; } var targetSteamId = new CSteamID(rawSteamId); SteamFriends.RequestUserInformation(targetSteamId, false); const float timeout = 5f; float deadline = Time.realtimeSinceStartup + timeout; 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)) { _runtimeSteamAvatarTexture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false); _runtimeSteamAvatarTexture.LoadRawTextureData(buffer); _runtimeSteamAvatarTexture.Apply(); _runtimeSteamAvatarFlippedTexture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false); for (int y = 0; y < height; y++) { Color[] pixels = _runtimeSteamAvatarTexture.GetPixels(0, (int)y, (int)width, 1); _runtimeSteamAvatarFlippedTexture.SetPixels(0, (int)height - 1 - (int)y, (int)width, 1, pixels); } _runtimeSteamAvatarFlippedTexture.Apply(); _runtimeAvatarSprite = Sprite.Create(_runtimeSteamAvatarFlippedTexture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f)); friendProfile.sprite = _runtimeAvatarSprite; yield break; } } yield return new WaitForSecondsRealtime(0.25f); } #endif } private void ReleaseRuntimeAvatarResources() { if (_runtimeAvatarSprite != null) { Destroy(_runtimeAvatarSprite); _runtimeAvatarSprite = null; } if (_runtimeAvatarTexture != null) { Destroy(_runtimeAvatarTexture); _runtimeAvatarTexture = null; } if (_runtimeSteamAvatarFlippedTexture != null) { Destroy(_runtimeSteamAvatarFlippedTexture); _runtimeSteamAvatarFlippedTexture = null; } if (_runtimeSteamAvatarTexture != null) { Destroy(_runtimeSteamAvatarTexture); _runtimeSteamAvatarTexture = null; } } }