Files

222 lines
7.2 KiB
C#

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<Task> 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<Task> 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<Text>(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));
}
}