示例#1
0
        //private static TickMessage _tickMessage;

        //private static bool _applyCommands = true;

        public void StopWorker()
        {
            LogProxy.Warning("Director: Stop Worker");
            _terminateSignal.Set();
            _updateSignal.Reset();
            _updateCompleteSignal.Set();
        }
示例#2
0
 public UIEntity(string entityTypeName, string name, Director director)
 {
     _director = director;
     if (TryInistantiateEntity(entityTypeName, name) == false)
     {
         LogProxy.Warning($"Unknown entity type '{entityTypeName}'");
     }
 }
示例#3
0
        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;
            }
        }
示例#4
0
        /// <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]);
        }
示例#5
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);
         }
     }
 }
示例#6
0
 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}");
     }
 }
示例#7
0
        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}'");
            }
        }
示例#8
0
 /// <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);
     }
 }
示例#9
0
        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());
        }
示例#10
0
        /// <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());
        }
示例#11
0
        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);
            }
        }
示例#12
0
        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.");
        }