/// <summary> /// Operation extracts an asset from the loaded bundle /// </summary> /// <param name="asyncOperation"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async UniTask <T> GetAssetComponentAsync <T>(AssetBundleRequest asyncOperation, IProgress <float> progress, CancellationToken cancellationToken) where T : UnityEngine.Object { while (!asyncOperation.isDone) { if (cancellationToken.IsCancellationRequested) { return(null); } await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); //Supressing this so it doesnt step over GetBundleFromStreamingAssetsAsync or GetBundleFromWebOrCacheAsync //progress?.Report(asyncOperation.progress); Logger.Log($"GetAssetComponentAsync {Bundle.name} progress: {asyncOperation.progress * 100f}%", Colors.LightSalmon); } if (!asyncOperation.asset) { throw new Exception("RunAssetBundleRequestOperation: Error getting bundle."); } //Current use case returns the component, if this changes then deal with it downstream but for now this should be ok var go = asyncOperation.asset as GameObject; return(go.GetComponent <T>()); }
/// <summary> /// Saves data into a file. /// </summary> /// <param name="data"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public async UniTask Save <T>(T data) where T : IStorable { await Task.Run(() => { if (data is MonoBehaviour) { Logger.LogError($"Persistent Data Service: Monobehaviours cannot be serialized. Aborting."); return; } var filename = data.FileName + _configuration.DataFileExtension; try { using (var file = File.Open(_dataDirectory + "/" + filename, FileMode.Create)) { var bf = new BinaryFormatter(); bf.Serialize(file, data); //todo: need to find an async way of doing this file.Flush(); file.Close(); Logger.Log($"Persistent Data Service: Saving to - {_dataDirectory + "/" + filename}", Colors.LightPink); } } catch (Exception e) { Logger.LogError($"Persistent Data Service: error saving to - {_dataDirectory + "/" + filename}, {e.Message}"); } }); }
/// <summary> /// Loads serialized data into an object /// </summary> /// <param name="filename"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public async UniTask <T> Load <T>(string filename) where T : IStorable { return(await Task.Run(() => { filename += _configuration.DataFileExtension; if (!File.Exists(_dataDirectory + "/" + filename)) { Logger.LogWarning($"Persistent Data Service: File {_dataDirectory + "/" + filename} does not exists."); return default(T); } try { using (var file = File.Open(_dataDirectory + "/" + filename, FileMode.Open)) { var bf = new BinaryFormatter(); var data = (T)bf.Deserialize(file); //todo: need to find an async way of doing this file.Close(); Logger.Log($"Persistent Data Service: Reading from - {_dataDirectory + "/" + filename}", Colors.LightPink); return data; } } catch (Exception e) { Logger.LogError($"Persistent Data Service: Error - {e.Message}"); } return default(T); })); }
/// <summary> /// Utility method to request multiple assets. /// </summary> /// <param name="requests">Bundle requests</param> /// <param name="progress">Reports loading progress percentage</param> /// <param name="forceLoadFromStreamingAssets"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async UniTask <Dictionary <string, LoadedBundle> > LoadMultipleBundles(List <BundleRequest> requests, bool forceLoadFromStreamingAssets = false, IProgress <float> progress = null, CancellationToken cancellationToken = default(CancellationToken)) { var tempCount = 0; var total = requests.Count; var bundles = new Dictionary <string, LoadedBundle>(); foreach (var request in requests) { if (cancellationToken.IsCancellationRequested) { return(null); } await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); var bundle = await _assetBundlebundleLoader.LoadBundle(request, forceLoadFromStreamingAssets, cancellationToken : cancellationToken); bundles.Add(request.BundleName, bundle); tempCount++; progress?.Report(tempCount * 100 / total); Logger.Log($"LoadMultipleAssets: {tempCount} of {total} | {tempCount * 100 / total}%", Colors.Aquamarine); } return(bundles); }
public override void InstallBindings() { //Initialize SignalBus SignalBusInstaller.Install(Container); //This allows SignalBus to be injected in any class instantiated here, or any of its children. //Add Game Scoped Signals Container.DeclareSignal <OnGameStartedSignal>().OptionalSubscriber(); Container.DeclareSignal <OnGamePaused>().OptionalSubscriber(); Container.DeclareSignal <OnGameResumed>().OptionalSubscriber(); Container.DeclareSignal <OnGameGotFocus>().OptionalSubscriber(); Container.DeclareSignal <OnGameLostFocus>().OptionalSubscriber(); Container.DeclareSignal <OnGameQuit>().OptionalSubscriber(); Logger.Log($"Binding {coreSystems.Count} systems", Colors.Lime); //Create system objects and bind them foreach (var prefab in coreSystems) { Container.Bind(prefab.GetType()) .FromComponentInNewPrefab(prefab) .AsSingle() .OnInstantiated((InjectContext context, ICoreSystem system) => { if (system is FactoryCoreSystem factory) { factory.SetDiContainer(Container); } }) .NonLazy(); Logger.Log($"----{prefab.name}", Colors.Lime); } Logger.Log("GameConfiguration: Service binding complete", Colors.Lime); }
public async UniTask <T> OpenUI <T>(UIElement window, IProgress <float> progress = null, CancellationToken cancellationToken = default(CancellationToken)) where T : UIElement { if (cancellationToken.IsCancellationRequested) { return(null); } var obj = _factoryService.Instantiate(window, DetermineRenderPriorityCanvas(window.UIType)); obj.name = window.name; obj.OnClosed().Subscribe(x => { UIElementClosed(x).Run(); }); if (!_activeUIElements.ContainsKey(obj.name)) { _activeUIElements.Add(obj.name, obj); } if (obj.PauseGameWhenOpen) { PauseResume(true); } Logger.Log($"UI Service: Loaded window - {obj.name}", Colors.LightBlue); await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); return(obj as T); }
private void OnServerTick(uint deltaTick) { try { if (!_serverCachedPackets.IsEmpty) { var command = _serverCachedPackets.PopFront(); if (_currentCommand == null) { _currentCommand = command; } if (_currentCommand.Tick > command.Tick) { _serverCachedPackets.PushBack(command); } _currentCommand = command; var vector = new Vector3(_currentCommand.Position.x, 0, _currentCommand.Position.y); _moveVector = vector; } } catch (Exception e) { Logger.LogError(e); } }
/// <summary> /// Loads a component from a prefab AssetReference. /// Use this when a component is needed from a prefab. (Particle System, Canvas, Image, etc) /// </summary> /// <param name="reference"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public async UniTask <T> LoadPrefabAssetFromReferenceAsync <T>(AssetReference reference, IProgress <float> progress = null, CancellationToken cancellationToken = default) where T : UnityEngine.Object { var asset = await LoadAssetFromReferenceAsync <GameObject>(reference, progress, cancellationToken); Logger.Log($"Loaded component: {asset.name}".ColoredLog(Colors.Pink)); return(asset.GetComponent <T>()); }
/// <summary> /// Facilitates communication with Put and Get requests from server API. /// </summary> /// <param name="observer"></param> /// <param name="requestType"></param> /// <param name="uri"></param> /// <param name="putData"></param> /// <returns></returns> private static IEnumerator RequestAsync(IObserver <string> observer, RequestType requestType, string uri, string putData) { var request = CreateRequest(requestType, uri, putData); request.SetRequestHeader("poop", "pappa"); yield return(request.SendWebRequest()); if (IsError(request, out var error)) { observer.OnError(new Exception(error)); } else { if (requestType == RequestType.Put) { Logger.Log($"{uri} | ".ColoredLog(Colors.Aqua) + $"{putData} | {request.downloadHandler.text}".ColoredLog(Colors.Coral)); } else { Logger.Log($"{uri} | ".ColoredLog(Colors.Aqua) + $"{request.downloadHandler.text}".Colored(Colors.Coral)); } observer.OnNext(request.downloadHandler.text); observer.OnCompleted(); } }
/// <summary> /// Loads an asset from an AssetReference. Textures, Materials, Sound Clips, etc. /// </summary> /// <param name="reference"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public async UniTask <T> LoadAssetFromReferenceAsync <T>(AssetReference reference, IProgress <float> progress = null, CancellationToken cancellationToken = default) where T : UnityEngine.Object { var asyncOperation = reference.LoadAssetAsync <T>(); var asset = await GetAsyncOperationResultAsync(asyncOperation, progress, cancellationToken); Logger.Log($"Loaded asset: {asset.name}".ColoredLog(Colors.Pink)); return(asset); }
/// <summary> /// Unload scene. /// </summary> /// <param name="scene"></param> /// <returns></returns> public async UniTask UnLoadScene(string scene) { await SceneManager.UnloadSceneAsync(scene); await _assetService.UnloadAsset(scene, true); Logger.Log(("SceneLoaderService: Unloaded scene - " + scene), Colors.LightBlue); }
public override void InstallBindings() { Logger.LogLevel = debugLevel; //Initialize SignalBus SignalBusInstaller.Install(Container); //This allows SignalBus to be injected in any class instantiated here, or any of its children. //Add Game Scoped Signals Container.DeclareSignal <OnGameStartedSignal>().OptionalSubscriber(); Container.DeclareSignal <OnGamePaused>().OptionalSubscriber(); Container.DeclareSignal <OnGameResumed>().OptionalSubscriber(); Container.DeclareSignal <OnGameGotFocus>().OptionalSubscriber(); Container.DeclareSignal <OnGameLostFocus>().OptionalSubscriber(); Container.DeclareSignal <OnGameQuit>().OptionalSubscriber(); Logger.Log("GameConfiguration: Starting Services", Colors.Lime); foreach (var service in services) { Logger.Log($"--- Starting: {service.name}", Colors.Cyan); if (service is AssetServiceConfiguration) { Container.BindInterfacesAndSelfTo <AssetService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <AssetServiceConfiguration>().AsSingle().NonLazy(); Container.Bind <AssetBundleLoader>().AsSingle().NonLazy(); } else if (service is SceneLoaderServiceConfiguration) { Container.BindInterfacesAndSelfTo <SceneLoaderService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <SceneLoaderServiceConfiguration>().AsSingle().NonLazy(); } else if (service is UIServiceConfiguration) { Container.BindInterfacesAndSelfTo <UIService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <UIServiceConfiguration>().AsSingle().NonLazy(); } else if (service is FactoryServiceConfiguration) { Container.BindInterfacesAndSelfTo <FactoryService>().AsSingle().WithArguments(service, Container).NonLazy(); Container.Bind <FactoryServiceConfiguration>().AsSingle().NonLazy(); } else if (service is AudioServiceConfiguration) { Container.BindInterfacesAndSelfTo <AudioService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <AudioServiceConfiguration>().AsSingle().NonLazy(); } else if (service is SocialServiceConfiguration) { Container.BindInterfacesAndSelfTo <SocialService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <SocialServiceConfiguration>().AsSingle().NonLazy(); } else if (service is PersistentDataServiceConfiguration) { Container.BindInterfacesAndSelfTo <PersistentDataService>().AsSingle().WithArguments(service).NonLazy(); Container.Bind <PersistentDataServiceConfiguration>().AsSingle().NonLazy(); } } }
/// <summary> /// Loads a scene from an AssetReference /// </summary> /// <param name="reference"></param> /// <param name="loadSceneMode"></param> /// <param name="activateOnLoad"></param> /// <param name="priority"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async UniTask <Scene> LoadSceneFromReferenceAsync(AssetReference reference, LoadSceneMode loadSceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100, IProgress <float> progress = null, CancellationToken cancellationToken = default) { var asyncOperation = Addressables.LoadSceneAsync(reference, loadSceneMode, activateOnLoad, priority); var sceneInstance = await GetAsyncOperationResultAsync(asyncOperation, progress, cancellationToken); Logger.Log($"Loaded Scene: {sceneInstance.Scene.name}".ColoredLog(Colors.Pink)); return(sceneInstance.Scene); }
static Startup() { if (EditorPreferences.EditorprefFirstTimeUse) { Logger.Log("First time use. Enabling asset bundle simulation mode.", Colors.Yellow); EditorPreferences.EditorprefSimulateAssetBundles = true; EditorPreferences.EditorprefFirstTimeUse = false; } }
public override void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { if (messageType == UnconnectedMessageType.Broadcast) { Logger.Log("[SERVER] Received discovery request. Send discovery response".ColoredLog(Colors.Yellow)); var resp = new NetDataWriter(); resp.Put(1); SendUnconnectedMessage(resp, remoteEndPoint); } }
/// <summary> /// Method attemps to get a bundle from the web/cloud /// </summary> /// <param name="bundleRequest">Bundle to request</param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> private async UniTask <AssetBundle> GetBundleFromWebOrCacheAsync(BundleRequest bundleRequest, IProgress <float> progress, CancellationToken cancellationToken) { var uwr = new UnityWebRequest(); Logger.Log($"AssetBundleLoader: {_assetService.AssetCacheState} | Requesting: {bundleRequest.AssetName} {bundleRequest.BundleName}", Colors.Aqua); if (_assetService.CloudBuildManifest != null && _assetService.AssetCacheState == AssetCacheState.Cache) { //cache bundles by using Unity Cloud Build manifest uint buildNumber = 0; buildNumber = Convert.ToUInt32(_assetService.CloudBuildManifest.buildNumber); uwr = UnityWebRequestAssetBundle.GetAssetBundle(bundleRequest.GetAssetPath(_assetService.Configuration), buildNumber, 0); } else if (_assetService.CloudBuildManifest == null || _assetService.AssetCacheState == AssetCacheState.NoCache) { if (_assetService.AssetCacheState == AssetCacheState.Cache) { Logger.Log("AssetBundleLoader: Caching is enabled, but Unity Cloud Build Manifest was missing, bundle was not cached.", Colors.Aqua); } //No caching, just get the bundle uwr = UnityWebRequestAssetBundle.GetAssetBundle(bundleRequest.GetAssetPath(_assetService.Configuration)); } //Wait until uwr is done. var asyncOperation = uwr.SendWebRequest(); while (!asyncOperation.isDone) { if (cancellationToken.IsCancellationRequested) { return(null); } await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); progress?.Report(asyncOperation.progress); Logger.Log($"GetBundleFromWebOrCacheAsync {bundleRequest.BundleName} progress: {asyncOperation.progress * 100f}%", Colors.LightSalmon); } //get bundle var bundle = DownloadHandlerAssetBundle.GetContent(uwr); if (uwr.isNetworkError) { throw new System.Exception($"AssetBundleLoader: {uwr.error}"); } uwr.Dispose(); return(bundle); }
public override void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { if (!ServerNetworkEntities.ContainsKey((ushort)peer.Id)) { return; } var entity = ServerNetworkEntities[(ushort)peer.Id]; ServerNetworkEntities.Remove(entity.PeerId); _onPeerDisconnected.OnNext(entity.PeerId); Logger.Log($"[SERVER] Peer {entity.PeerId} disconnected because {disconnectInfo.Reason}".ColoredLog(Colors.Yellow)); }
private async void LoadBuildManifestAsync() { var cloudManifest = await UnityCloufBuildManifestLoader.LoadBuildManifest(); if (cloudManifest != null) { Logger.Log(("---- AssetService: Unity Cloud Build Manifest present. Build Version: " + cloudManifest.buildNumber), Colors.Aqua); _cloudBuildManifest = cloudManifest; } else { Logger.Log("---- AssetService: Unity Cloud Build Manifest missing. This is ok. Ignoring.", Colors.Aqua); } }
private async UniTask UIElementClosed(UIElement window) { Logger.Log(("UI Service: Closed window - " + window.name), Colors.LightBlue); _activeUIElements.Remove(window.name); await _assetService.UnloadAsset(window.name, true); if (window.PauseGameWhenOpen) { PauseResume(false); } UnityEngine.Object.Destroy(window.gameObject); }
private void OnNetworkEntityJoined(NetworkEntityJoinedGamePacket packet) { CreateEntity(packet.PeerId, packet.NetworkObjectId); //Send network objects if (IsHost) { foreach (var key in _serverInstantiatedObjects.Keys) { InstantiateNetworkObject(packet.PeerId, _serverInstantiatedObjects[key].PeerId, _serverInstantiatedObjects[key].NetworkObjectId, ""); } } _onPlayerJoined.OnNext(Unit.Default); Logger.Log($"[CLIENT] Player Joined!! {packet.PeerId}".ColoredLog(Colors.HotPink)); }
/// <summary> /// Loads an asset inside this bundle /// </summary> /// <param name="name"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async UniTask <T> LoadAssetAsync <T>(string name, IProgress <float> progress, CancellationToken cancellationToken) where T : UnityEngine.Object { #if UNITY_EDITOR if (EditorPreferences.EditorprefSimulateAssetBundles) { Logger.Log(("LoadAssetAsync Simulated: loading asset: " + name), Colors.Yellow); var comp = _simulatedAsset.GetComponent <T>(); await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); return(comp); } #endif Logger.Log(("LoadAssetAsync: loading asset: " + name), Colors.Yellow); return(await GetAssetComponentAsync <T>(Bundle.LoadAssetAsync(name), progress, cancellationToken)); }
private static bool IsError(UnityWebRequest request, out string error, bool isBinary = false) { if (!isBinary && request.downloadHandler.text.Contains("error")) { Logger.LogError($"URI: {request.uri} | {request.downloadHandler.text}".ColoredLog(Colors.Red)); error = $"URI: {request.uri} - {request.downloadHandler.text}"; return(true); } if (request.isNetworkError || request.error != null) { Logger.LogError($"URI: {request.uri} | {request.error}".ColoredLog(Colors.Red)); error = request.error; return(true); } error = string.Empty; return(false); }
private void OnPlayerJoinRequestAccepted(PlayerJoinRequestAcceptedPacket packet) { CreateEntity(packet.PeerId, packet.NetworkObjectId, true); PeerId = packet.PeerId; Client.SyncTick(packet.Tick); foreach (var peer in packet.CurrentPeers) { if (!Client.ConnectedPeers.ContainsKey(peer.PeerId)) { CreateEntity(peer.PeerId, peer.NetworkObjectId); } } if (IsHost) { InstantiateNetworkObject(PeerId, PeerId, GetNewNetworkObjectId(), ""); } Logger.Log($"[CLIENT] We joined. Id: {packet.PeerId} Existing players: {packet.CurrentPeers.Length}".ColoredLog(Colors.HotPink)); }
/// <summary> /// Gets a scene from an asset bundle /// </summary> /// <param name="scene"></param> /// <param name="mode"> </param> /// <param name="forceLoadFromStreamingAssets"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async UniTask <UnityEngine.Object> GetScene(string scene, LoadSceneMode mode, bool forceLoadFromStreamingAssets, IProgress <float> progress, CancellationToken cancellationToken) { if (_assetService.GetLoadedBundle(scene)) { throw new Exception("Scene " + scene + " is already loaded and open. Opening the same scene twice is not supported."); } var sceneObject = await _assetService.GetScene(new BundleRequest(AssetCategoryRoot.Scenes, scene, scene), forceLoadFromStreamingAssets, progress, cancellationToken); if (sceneObject && !cancellationToken.IsCancellationRequested) { Logger.Log(("SceneLoaderService: Loaded scene - " + scene), Colors.LightBlue); await SceneManager.LoadSceneAsync(scene, mode); Logger.Log(("SceneLoaderService: Opened scene - " + scene), Colors.LightBlue); } return(sceneObject); }
/// <summary> /// Gets bundle from streaming assets directory /// </summary> /// <param name="bundleRequest"> Bundle to request </param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> private async UniTask <AssetBundle> GetBundleFromStreamingAssetsAsync(BundleRequest bundleRequest, IProgress <float> progress, CancellationToken cancellationToken) { Logger.Log($"AssetBundleLoader: Using StreamingAssets - Requesting: {bundleRequest.AssetCategory} {bundleRequest.BundleName}", Colors.Aqua); var path = Path.Combine(Application.streamingAssetsPath, bundleRequest.AssetPathFromLocalStreamingAssets); var asyncOperation = AssetBundle.LoadFromFileAsync(path); while (!asyncOperation.isDone) { if (cancellationToken.IsCancellationRequested) { return(null); } await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); progress?.Report(asyncOperation.progress); Logger.Log($"GetBundleFromStreamingAssetsAsync {bundleRequest.BundleName} progress: {asyncOperation.progress * 100f}%", Colors.LightSalmon); } return(asyncOperation.assetBundle); }
/// <summary> /// Observable wrapper for RequestAsync /// </summary> /// <param name="requestType"></param> /// <param name="uri"></param> /// <param name="putData"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static IObservable <T> Request <T>(RequestType requestType, string uri, string putData = "") { return(Observable.Create( (IObserver <T> requestObserver) => { return Observable.FromCoroutine <string>(observer => RequestAsync(observer, requestType, uri, putData)) .CatchIgnore((Exception ex) => { requestObserver.OnError(ex); }) .Subscribe(json => { try { requestObserver.OnNext(JsonUtility.FromJson <T>(json)); requestObserver.OnCompleted(); } catch (Exception e) { Logger.LogError(e); throw e; } }); })); }
/// <summary> /// Saves data into a file. /// </summary> /// <param name="data"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public void Save <T>(T data) where T : IStorable { //TODO: improve this with async https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/using-async-for-file-access if (data is MonoBehaviour) { throw new Exception($"Persistent Data Service: Monobehaviours cannot be serialized. Aborting."); } var filename = data.FileName + dataFileExtension; var file = File.Open(_dataDirectory + "/" + filename, FileMode.Create); try { var bf = new BinaryFormatter(); bf.Serialize(file, data); //todo: need to find an async way of doing this file.Flush(); file.Close(); Logger.Log($"Persistent Data Service: Saving to - {_dataDirectory + "/" + filename}", Colors.LightPink); } catch (Exception e) { throw e; } }
/// <summary> /// Loads serialized data into an object /// </summary> /// <param name="filename"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> private async UniTask <T> Load <T>(string filename) where T : IStorable { filename += dataFileExtension; if (!File.Exists(_dataDirectory + "/" + filename)) { throw new Exception($"Persistent Data Service: File {_dataDirectory + "/" + filename} does not exists."); } var file = File.Open(_dataDirectory + "/" + filename, FileMode.Open); try { var bf = new BinaryFormatter(); var data = (T)bf.Deserialize(file); //todo: need to find an async way of doing this Logger.Log($"Persistent Data Service: Reading from - {_dataDirectory + "/" + filename}", Colors.LightPink); return(data); } catch (Exception e) { throw e; } }
public override void OnPeerConnected(NetPeer peer) { Logger.Log($"[SERVER] Client connected: {peer.Id}".ColoredLog(Colors.Yellow)); }
public override void OnNetworkError(IPEndPoint endPoint, SocketError socketError) { Logger.Log($"[SERVER] received error {socketError}".ColoredLog(Colors.Yellow)); }