using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Events; using Debug = UnityEngine.Debug; using Timer = System.Timers.Timer; namespace BITKit.Http { public class HttpService : MonoBehaviour { [Header(Constant.Header.Settings)] [SerializeReference,SubclassSelector] private IReference url; [SerializeField] private double interval; [SerializeField] private CollisionDetectionMode detectionMode; [Header(Constant.Header.Output)] [SerializeField] private UnityEvent output; [SerializeField] private UnityEvent onException; [SerializeField] private UnityEvent onCalculateLength; [Header(Constant.Header.Optional)] [SerializeField] private Optional overrideResponse; [Header(Constant.Header.Debug)] [SerializeField, ReadOnly] private double time; [SerializeField, ReadOnly] private bool isConnected; private readonly Timer timer = new() { AutoReset = true }; private readonly HttpClient _httpClient = new(); private bool _enabled; private void OnEnable() { _enabled = true; } private void OnDisable() { _enabled = false; } private void Start() { timer.Interval = interval*1000; timer.Elapsed += (x, y) => OnUpdate(); timer.AutoReset = detectionMode switch { CollisionDetectionMode.ContinuousDynamic => true, CollisionDetectionMode.ContinuousSpeculative => true, CollisionDetectionMode.Continuous => true, CollisionDetectionMode.Discrete => false, _ => throw new ArgumentOutOfRangeException() }; timer.Start(); destroyCancellationToken.ThrowIfCancellationRequested(); } private void OnDestroy() { timer.Stop(); timer.Dispose(); } private async void OnUpdate() { try { if (_enabled) { if (overrideResponse.Allow) { await UniTask.SwitchToMainThread(); try { output.Invoke(overrideResponse.Value); } catch (Exception e) { Debug.LogException(e); } isConnected = true; } else { Stopwatch stopwatch = new(); stopwatch.Start(); //var result = await _httpClient.GetStringAsync(url.Value); var response = await _httpClient.GetAsync(url.Value,destroyCancellationToken); if (destroyCancellationToken.IsCancellationRequested) return; var result =await response.Content.ReadAsStringAsync(); if (destroyCancellationToken.IsCancellationRequested) return; stopwatch.Stop(); time =System.TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds; await UniTask.SwitchToMainThread(); if (destroyCancellationToken.IsCancellationRequested) return; try { var length = int.Parse(response.Content.Headers.First(h => h.Key.Equals("Content-Length")).Value.First()); onCalculateLength.Invoke(length); } catch (InvalidOperationException) { } if (response.StatusCode is not System.Net.HttpStatusCode.OK) { onException.Invoke(result); } else { try { output.Invoke(result); } catch (Exception e) { Debug.LogException(e); } } isConnected = true; } } } catch(OperationCanceledException){} catch (Exception e) { BIT4Log.LogException(e); isConnected = false; } if (timer.AutoReset == false) { if(destroyCancellationToken.IsCancellationRequested)return; timer.Start(); } } } }