Example #1
0
        public void Execute()
        {
            foreach (var input in _spawnInputs.GetEntities().Where(entity => entity.tick.value == _gameStateContext.tick.value))
            {
                var actor        = _actorContext.GetEntityWithId(input.actorId.value);
                var nextEntityId = actor.entityCount.value;

                var e = _gameContext.CreateEntity();

                e.isNew = true;
                _services.Get <ILogService>().Trace(actor.id.value + " -> " + nextEntityId);

                //composite primary key
                e.AddId(nextEntityId);
                e.AddActorId(input.actorId.value);

                //unique id for internal usage
                e.AddLocalId(_localIdCounter);

                //some default components that every game-entity must have
                e.AddVelocity(Vector2.Zero);
                e.AddPosition(input.coordinate.value);

                _viewService.LoadView(e, input.entityConfigId.value);

                actor.ReplaceEntityCount(nextEntityId + 1);
                _localIdCounter += 1;
            }
        }
 public void CreatePlayer(byte actorId, int type){
     var bornPos = _gameConstStateService.playerBornPoss[actorId % _gameConstStateService.playerBornPoss.Count];
     var createPos = bornPos + base._gameConfigService.TankBornOffset;
     _gameEffectService.ShowBornEffect(createPos);
     _gameAudioService.PlayClipBorn();
     EDir dir = EDir.Up;
     DelayCall(base._gameConfigService.TankBornDelay, () => {
         var entity = CreateUnit(createPos, _gameConfigService.playerPrefabs, type, dir);
         var actor = _actorContext.GetEntityWithId(actorId);
         if (actor != null) {
             actor.ReplaceGameLocalId(entity.localId.value);
             entity.ReplaceActorId(actorId);
         }
         else {
             Debug.LogError(
                 $"can not find a actor after create a game player actorId:{actorId} localId{entity.localId.value}");
         }
     });
 }
Example #3
0
        public void Execute()
        {
            foreach (var input in _spawnInputs.GetEntities().Where(entity => entity.tick.value == _gameStateContext.tick.value))
            {
                var actor        = _actorContext.GetEntityWithId(input.actorId.value);
                var nextEntityId = actor.entityCount.value;

                var e = _gameContext.CreateEntity();

                Log.Trace(this, actor.id.value + " -> " + nextEntityId);

                //composite primary key
                e.AddId(nextEntityId);
                e.AddActorId(input.actorId.value);

                //unique id for internal usage
                e.AddLocalId(_localIdCounter);

                //some default components that every game-entity must have
                e.AddVelocity(Vector2.Zero);
                e.AddPosition(input.coordinate.value);

                _viewService.LoadView(e, input.entityConfigId.value);

                if (e.isNavigable)
                {
                    //TODO: factory method to create entity?
                    //Default agent settings
                    e.AddRadius(F64.C1);
                    e.AddMaxSpeed(F64.C2);
                    e.AddRvoAgentSettings(Vector2.Zero, 5, new List <KeyValuePair <Fix64, uint> >());
                }

                actor.ReplaceEntityCount(nextEntityId + 1);
                _localIdCounter += 1;
            }
        }
Example #4
0
        /// <summary>
        /// Revert all changes that were done during or after the given tick
        /// </summary>
        /// <param name="tick"></param>
        public void RevertToTick(uint tick)
        {
            Services.Get <ILogService>().Trace("Rollback to " + tick);
            //Get the actual tick that we have a snapshot for
            var resultTick = Services.Get <ISnapshotIndexService>().GetFirstIndexBefore(tick);

            /*
             * ====================== Revert actors ======================
             * most importantly: the entity-count per actor gets reverted so the composite key (Id + ActorId) of GameEntities stays in sync
             */

            var backedUpActors = _actorContext.GetEntities(ActorMatcher.Backup).Where(e => e.backup.tick == resultTick);

            foreach (var backedUpActor in backedUpActors)
            {
                backedUpActor.CopyTo(
                    _actorContext.GetEntityWithId(backedUpActor.backup.actorId),                                    //Current Actor
                    true,                                                                                           //Replace components
                    backedUpActor.GetComponentIndices().Except(new [] { ActorComponentsLookup.Backup }).ToArray()); //Copy everything except the backup-component
            }


            /*
             * ====================== Revert game-entities ======================
             */

            var currentEntities = _gameContext.GetEntities(GameMatcher.LocalId);
            var backupEntities  = _gameContext.GetEntities(GameMatcher.Backup).Where(e => e.backup.tick == resultTick).ToList();
            var backupEntityIds = backupEntities.Select(entity => entity.backup.localEntityId);

            //Entities that were created in the prediction have to be destroyed
            var invalidEntities = currentEntities.Where(entity => !backupEntityIds.Contains(entity.localId.value)).ToList();

            foreach (var invalidEntity in invalidEntities)
            {
                //Here we have the actual entities, we can safely refer to them via the internal id
                _view.DeleteView(invalidEntity.localId.value);
                invalidEntity.Destroy();
            }

            foreach (var invalidBackupEntity in _gameContext.GetEntities(GameMatcher.Backup).Where(e => e.backup.tick > resultTick))
            {
                Services.Get <ISnapshotIndexService>().RemoveIndex(invalidBackupEntity.backup.tick);
                invalidBackupEntity.Destroy();
            }

            //Copy old state to the entity
            foreach (var backupEntity in backupEntities)
            {
                var target = _gameContext.GetEntityWithLocalId(backupEntity.backup.localEntityId);
                var additionalComponentIndices = target.GetComponentIndices().Except(
                    backupEntity
                    .GetComponentIndices()
                    .Except(new[] { GameComponentsLookup.Backup })
                    .Concat(new[] { GameComponentsLookup.Id, GameComponentsLookup.ActorId, GameComponentsLookup.LocalId }))
                ;
                foreach (var index in additionalComponentIndices)
                {
                    target.RemoveComponent(index);
                }

                backupEntity.CopyTo(target, true, backupEntity.GetComponentIndices().Except(new [] { GameComponentsLookup.Backup }).ToArray());


                if (!Services.Get <IDebugService>().Validate(resultTick, backupEntity.backup.localEntityId, target.position.value))
                {
                    throw new Exception();
                }
            }

            //TODO: restore locally destroyed entities

            Contexts.gameState.ReplaceTick(resultTick);
        }
Example #5
0
        /// <summary>
        /// Reverts all changes that were done during or after the given tick
        /// </summary>
        public void RollbackTo(int tick, int missFrameTick, bool isNeedClear = true)
        {
            var snapshotIndices = _snapshotContext.GetEntities(SnapshotMatcher.Tick)
                                  .Where(entity => entity.tick.value <= tick).Select(entity => entity.tick.value).ToList();

            if (snapshotIndices.Count <= 0)
            {
                return;
            }
            snapshotIndices.Sort();
            UnityEngine.Debug.Assert(snapshotIndices.Count > 0 && snapshotIndices[0] <= tick,
                                     $"Error! no correct history frame to revert minTick{(snapshotIndices.Count > 0 ? snapshotIndices[0] : 0)} targetTick {tick}");
            int i = snapshotIndices.Count - 1;

            for (; i >= 0; i--)
            {
                if (snapshotIndices[i] <= tick)
                {
                    break;
                }
            }

            var resultTick = snapshotIndices[i];

            if (resultTick == Tick)
            {
                Logging.Debug.Log("SelfTick should not rollback");
                return;
            }
            var snaps = "";

            foreach (var idx in snapshotIndices)
            {
                snaps += idx + " ";
            }

            Logging.Debug.Log(
                $"Rolling back {Tick}->{tick} :final from {resultTick} to {_gameStateContext.tick.value}  " +
                $"missTick:{missFrameTick} total:{Tick - resultTick} ");

            /*
             * ====================== Revert actors ======================
             * most importantly: the entity-count per actor gets reverted so the composite key (Id + ActorId) of GameEntities stays in sync
             */

            var backedUpActors =
                _actorContext.GetEntities(ActorMatcher.Backup).Where(e => e.backup.tick == resultTick);

            foreach (var backedUpActor in backedUpActors)
            {
                var target = _actorContext.GetEntityWithId(backedUpActor.backup.actorId);
                if (target == null)
                {
                    target = _actorContext.CreateEntity();
                    target.AddId(backedUpActor.backup.actorId);
                }

                //CopyTo does NOT remove additional existing components, so remove them first
                var additionalComponentIndices = target.GetComponentIndices().Except(
                    backedUpActor.GetComponentIndices()
                    .Except(new[] { ActorComponentsLookup.Backup })
                    .Concat(new[] { ActorComponentsLookup.Id }));

                foreach (var index in additionalComponentIndices)
                {
                    target.RemoveComponent(index);
                }

                backedUpActor.CopyTo(target, true,
                                     backedUpActor.GetComponentIndices().Except(new[] { ActorComponentsLookup.Backup }).ToArray());
            }

            /*
             * ====================== Revert game-entities ======================
             */
            var currentEntities = _gameContext.GetEntities(GameMatcher.LocalId);
            var backupEntities  = _gameContext.GetEntities(GameMatcher.Backup).Where(e => e.backup.tick == resultTick)
                                  .ToList();
            var backupEntityIds = backupEntities.Select(entity => entity.backup.localEntityId);

            //Entities that were created in the prediction have to be destroyed
            var invalidEntities = currentEntities.Where(entity => !backupEntityIds.Contains(entity.localId.value))
                                  .ToList();

            foreach (var invalidEntity in invalidEntities)
            {
                invalidEntity.isDestroyed = true;
            }

            //将太后 和太前的snapshot 删除掉
            if (isNeedClear)
            {
                foreach (var invalidBackupEntity in _actorContext.GetEntities(ActorMatcher.Backup)
                         .Where(e => e.backup.tick != resultTick))
                {
                    invalidBackupEntity.Destroy();
                }

                foreach (var invalidBackupEntity in _gameContext.GetEntities(GameMatcher.Backup)
                         .Where(e => e.backup.tick != resultTick))
                {
                    invalidBackupEntity.Destroy();
                }

                foreach (var snapshotEntity in _snapshotContext.GetEntities(SnapshotMatcher.Tick)
                         .Where(e => e.tick.value != resultTick))
                {
                    snapshotEntity.Destroy();
                }
            }


            //Copy old state to the entity
            foreach (var backupEntity in backupEntities)
            {
                var target = _gameContext.GetEntityWithLocalId(backupEntity.backup.localEntityId);
                if (target == null)
                {
                    target = _gameContext.CreateEntity();
                    target.AddLocalId(backupEntity.backup.localEntityId);
                }

                //CopyTo does NOT remove additional existing components, so remove them first
                var additionalComponentIndices = target.GetComponentIndices().Except(
                    backupEntity.GetComponentIndices()
                    .Except(new[] { GameComponentsLookup.Backup })
                    .Concat(new[] { GameComponentsLookup.LocalId }));

                foreach (var index in additionalComponentIndices)
                {
                    target.RemoveComponent(index);
                }

                backupEntity.CopyTo(target, true,
                                    backupEntity.GetComponentIndices().Except(new[] { GameComponentsLookup.Backup }).ToArray());
            }

            //TODO: restore locally destroyed entities

            //Cleanup game-entities that are marked as destroyed
            _systems.Cleanup();
            _gameStateContext.ReplaceTick(resultTick);
            _timeMachineService.RollbackTo(resultTick);
            _timeMachineService.CurTick = resultTick;
        }