//private static TickMessage _tickMessage; //private static bool _applyCommands = true; public void StopWorker() { LogProxy.Warning("Director: Stop Worker"); _terminateSignal.Set(); _updateSignal.Reset(); _updateCompleteSignal.Set(); }
public UIEntity(string entityTypeName, string name, Director director) { _director = director; if (TryInistantiateEntity(entityTypeName, name) == false) { LogProxy.Warning($"Unknown entity type '{entityTypeName}'"); } }
public bool Initialize(SimulationRoot simulationRoot, int playerServerId, List <ITAlertPlayer> players) { try { SimulationRoot = simulationRoot; Players = players; LogProxy.Warning($"Initializing Director for simulation Instance {InstanceId}"); //TODO: get rid of this hacky sack PlayerCommands.Director = this; ItemPanel = transform.FindComponent <ItemPanel>("Canvas/ItemPanel"); _queuedMessages = new Queue <TickMessage>(); ResetDirector(); // all of this must happen after reset // TODO: this should probably be pushed into the ECS if (SimulationRoot.ECS.TryGetSystem <ICommandSystem>(out var commandSystem) == false) { throw new SimulationIntegrationException("Could not locate command processing system"); } CommandSystem = commandSystem; CalculateNetworkOffset(); CreateInitialEntities(); SetupPlayers(players, playerServerId); // item panel must come after players GetComponentsInChildren <Canvas>(true).ToList().ForEach(c => c.gameObject.SetActive(true)); ItemPanel.Initialize(); ItemPanel.ExplicitUpdate(); SimulationRoot.ECS.EntityRegistry.EntityDestroyed += EntityRegistryOnEntityDestroyed; if (SimulationRoot.ECS.TryGetSystem(out _endGameSystem) == false) { throw new SimulationIntegrationException("Could not locate end game system"); } CultureInfo.CurrentCulture = new CultureInfo("en"); _updatethread = new Thread(ThreadWorker) { IsBackground = true }; _updatethread.Start(); return(true); } catch (Exception ex) { LogProxy.Error($"Error initializing Director: {ex}"); throw; } }
/// <summary> /// Breadth first search for game objects. /// /// Root cannot be inactive. /// </summary> /// <param name="absolutePath"></param> /// <returns></returns> public static Transform Find(string absolutePath) { var results = FindAll(absolutePath); if (results.Length != 1) { LogProxy.Warning(results.Length == 0 ? $"Couldn't find any objects matching the path: \"{absolutePath}\"" : $"Found {results.Length} objects matching the path: \"{absolutePath}\""); return(null); } return(results[0]); }
private void UpdateScale() { if (_rectTransform.localScale != _scale) { LogProxy.Warning("Director: RectTransform scale updated"); _scale = _rectTransform.localScale; CalculateNetworkOffset(); foreach (var entity in _trackedEntities.Values.Concat(_untrackedEntities)) { entity.EntityBehaviour.UpdateScale(_scale); } } }
public UIEntity(Entity entity, Director director) { _director = director; if (entity.TryGetComponent(out IEntityType entityTypeFlag)) { var entityTypeName = entityTypeFlag.GetType().Name; if (TryInistantiateEntity(entityTypeName, entity.Id.ToString()) == false) { LogProxy.Warning($"Unknown entity type '{entityTypeName}' on entity {entity.Id}"); } } else { throw new Exception($"Entity type flag missing for entity {entity.Id}"); } }
private void SetupPlayers(List <ITAlertPlayer> players, int playerServerId) { LogProxy.Info("Director: Setup Players"); foreach (var player in players) { try { LogProxy.Info($"Director: Setup Players: Player {player.PhotonId}"); var internalPlayer = SimulationRoot.Configuration.PlayerConfiguration.Single(pc => pc.ExternalId == player.PhotonId); if (_trackedEntities.TryGetValue(internalPlayer.EntityId, out var playerUiEntity)) { var playerBehaviour = (PlayerBehaviour)playerUiEntity.EntityBehaviour; playerBehaviour.PhotonId = player.PhotonId; if (player.PhotonId == playerServerId) { LogProxy.Info($"Selected active player with id {playerServerId}: entity {playerBehaviour.Entity.Id}"); Player = playerBehaviour; playerUiEntity.GameObject.GetComponent <Canvas>().sortingLayerName = UIConstants.ActivePlayerSortingLayer; playerUiEntity.GameObject.GetComponent <TrailRenderer>().sortingLayerName = UIConstants.ActivePlayerSortingLayer; if (player.ExternalId.HasValue) { playerBehaviour.ExternalId = player.ExternalId.Value; } } } else { LogProxy.Warning($"No player entity with id: {internalPlayer.EntityId}"); } } catch (Exception ex) { throw new SimulationIntegrationException($"Error mapping photon player '{playerServerId}' to simulation", ex); } } if (Player == null) { throw new SimulationIntegrationException($"Error mapping actiove photon player '{playerServerId}'"); } }
/// <summary> /// This should never be called when there is no _photonClient.CurrentRoom as /// voice functionality cannot exist outside of a room. /// </summary> public void HandleVoiceInput() { try { if (VoiceClient != null && _photonClient.CurrentRoom.Players.Count > 1) { if (_getActivated()) { if (!VoiceClient?.IsTransmitting ?? false) { VoiceClient.StartTransmission(); LogProxy.Warning("Starting voice transmission"); if (_director?.Player != null) { _photonClient?.CurrentRoom?.Messenger.SendMessage(new PlayerVoiceActivatedMessage { PlayerId = _director.Player.Id }); } } } if (_getDeactivated()) { if ((bool)VoiceClient?.IsTransmitting) { VoiceClient.StopTransmission(); if (_director?.Player != null) { _photonClient?.CurrentRoom?.Messenger.SendMessage(new PlayerVoiceDeactivatedMessage { PlayerId = _director.Player.Id }); } } } } } catch (Exception ex) { throw new PhotonVoiceException("Error processing voice communication", ex); } }
public static GameObject[] FindAllChildren(string absolutePath) { var result = Find(absolutePath); var childCount = result.childCount; if (childCount < 1) { LogProxy.Warning($"Couldn't find any children of the object matching the path: \"{absolutePath}\""); return(null); } var children = new List <Transform>(); for (var i = 0; i < childCount; i++) { children.Add(result.GetChild(i)); } return(children.Select(t => t.gameObject).ToArray()); }
/// <summary> /// Breadth first search for game objects. /// /// Root cannot be inactive. /// </summary> /// <param name="absolutePath"></param> /// <returns></returns> public static Transform[] FindAll(string absolutePath) { var segments = absolutePath.Split('/'); var level = 0; var childObject = GameObject.Find(segments[level]); if (childObject == null) { LogProxy.Warning("Couldn't find any object at path: " + absolutePath); return(null); } var rootTransform = childObject.transform; var currentLevel = new List <Transform> { rootTransform }; var nextLevel = new List <Transform>(); var matches = FindMatches(++level, segments, currentLevel, nextLevel); return(matches.ToArray()); }
private void UpdateEntityStates() { try { foreach (var entity in SimulationRoot.ECS.Entities) { try { if (_terminateSignal.WaitOne(0)) { LogProxy.Warning("Aborting UpdateEntityStates."); return; } if (TryGetEntity(entity.Key, out var uiEntity)) { uiEntity.UpdateEntityState(); } else { var newUiEntity = CreateEntity(entity.Value); newUiEntity.EntityBehaviour?.Initialize(entity.Value, this); } } catch (Exception ex) { throw new SimulationIntegrationException($"Error updating entity {entity.Key}", ex); } } int[] destroyedEntities; lock (_destroyedEntityLock) { destroyedEntities = _destroyedEntities.ToArray(); _destroyedEntities.Clear(); } foreach (var entityToRemove in destroyedEntities) { if (_terminateSignal.WaitOne(0)) { LogProxy.Warning("Aborting UpdateEntityStates."); return; } if (TryGetEntity(entityToRemove, out var uiEntity)) { Destroy(uiEntity.GameObject); } _trackedEntities.Remove(entityToRemove); } foreach (var untrackedEntity in _untrackedEntities) { if (_terminateSignal.WaitOne(0)) { LogProxy.Warning("Aborting UpdateEntityStates."); return; } untrackedEntity.UpdateEntityState(); } if (_terminateSignal.WaitOne(0)) { return; } ItemPanel.ExplicitUpdate(); _updateCompleteSignal.Set(); } catch (Exception exception) { LogProxy.Error($"Error updating Director {InstanceId} state: {exception}"); throw new SimulationIntegrationException("Error updating Director state", exception); } }
private void ThreadWorker() { while (true) { try { var handle = WaitHandle.WaitAny(new WaitHandle[] { _terminateSignal, _messageSignal }); if (handle == 0) { LogProxy.Warning("Director: Terminating thread worker."); break; } if (handle == 1) { if (!_queueBeingProcessed) { _queueBeingProcessed = true; var queuedMessages = new List <Tuple <TickMessage, Tick> >(); lock (_queueLock) { var orderedMessages = _queuedMessages.Select(m => new Tuple <TickMessage, Tick>(m, ConfigurationSerializer.Deserialize <Tick>(m.TickString))).OrderBy(m => m.Item2.CurrentTick).ToArray(); _queuedMessages.Clear(); if (orderedMessages.Length > 50) { if (SimulationRoot.ECS.CurrentTick + 1 > orderedMessages[0].Item2.CurrentTick) { orderedMessages = orderedMessages.Where(m => m.Item2.CurrentTick >= SimulationRoot.ECS.CurrentTick + 1).ToArray(); } while (SimulationRoot.ECS.CurrentTick + 1 < orderedMessages[0].Item2.CurrentTick) { SimulationRoot.ECS.Tick(); } } for (var m = 0; m < orderedMessages.Length; m++) { if (m + SimulationRoot.ECS.CurrentTick + 1 == orderedMessages[m].Item2.CurrentTick) { queuedMessages.Add(orderedMessages[m]); } else { _queuedMessages.Enqueue(orderedMessages[m].Item1); } } } var i = 1; foreach (var tickMessage in queuedMessages) { var fastForward = i++ < queuedMessages.Count; var success = true; foreach (var command in tickMessage.Item2.CommandQueue) { success &= CommandSystem.TryHandleCommand(command, tickMessage.Item2.CurrentTick); } if (success != true) { throw new SimulationIntegrationException("Local Simulation failed to apply command(s)."); } SimulationRoot.ECS.Tick(); if (fastForward) { LogProxy.Warning($"Simulation fast forwarding tick {SimulationRoot.ECS.CurrentTick}"); } else { if (tickMessage.Item2.CurrentTick != SimulationRoot.ECS.CurrentTick) { throw new SimulationSynchronisationException($"Simulation out of sync: Local tick {SimulationRoot.ECS.CurrentTick} doesn't not match master {tickMessage.Item2.CurrentTick}"); } var localTick = SimulationRoot.ECS.CurrentTick; SimulationRoot.GetEntityState(out var crc); #if LOG_ENTITYSTATE System.IO.File.WriteAllText($"d:\\temp\\{SimulationRoot.ECS.CurrentTick}.{Player.PhotonId}.json", state); #endif if (tickMessage.Item1.CRC != crc) { throw new SimulationSynchronisationException($"Simulation out of sync at tick {localTick}: Local CRC {crc} doest not match master {tickMessage.Item1.CRC}"); } } } _updateSignal.Set(); _updateCompleteSignal.WaitOne(); _queueBeingProcessed = false; } else { LogProxy.Warning("ProcessQueuedMessages not called as already running"); } } } catch (Exception ex) { LogProxy.Error($"Simulation worker thread terminating due to error: {ex}"); ThreadWorkerException = new SimulationIntegrationException("Terminating simulation worker thread", ex); _workerThreadExceptionSignal.Set(); break; } } LogProxy.Warning("Director: Thread Worker Terminated."); }