Ejemplo n.º 1
0
        public ContiMove(
            GameStage gameStage,
            ContiMoveTemplate template,
            IFieldRepository fieldRepository
            )
        {
            _gameStage    = gameStage;
            _template     = template;
            _stateMachine = new StateMachine <ContiMoveState, ContiMoveStateTrigger>(ContiMoveState.Dormant);

            _stateMachine
            .Configure(ContiMoveState.Dormant)
            .Permit(ContiMoveStateTrigger.Board, ContiMoveState.Wait);
            _stateMachine
            .Configure(ContiMoveState.Wait)
            .Permit(ContiMoveStateTrigger.Start, ContiMoveState.Move);
            _stateMachine
            .Configure(ContiMoveState.Move)
            .OnEntryFromAsync(ContiMoveStateTrigger.Start, async() =>
            {
                await Move(WaitField, MoveField);
                await StartShipMoveField.Dispatch(
                    new UnstructuredOutgoingPacket(PacketSendOperations.CONTIMOVE)
                    .WriteByte((byte)ContiMoveTarget.TargetStartShipMoveField)
                    .WriteByte((byte)ContiMoveStateTrigger.Start)
                    );
            })
            .OnExitAsync(async() =>
            {
                await Move(MoveField, EndField);
                if (CabinField != null)
                {
                    await Move(CabinField, EndField);
                }

                await EndShipMoveField.Dispatch(
                    new UnstructuredOutgoingPacket(PacketSendOperations.CONTIMOVE)
                    .WriteByte((byte)ContiMoveTarget.TargetEndShipMoveField)
                    .WriteByte((byte)ContiMoveStateTrigger.End)
                    );

                _nextBoarding = _nextBoarding.AddMinutes(_template.Term);
                ResetEvent();
            })
            .Permit(ContiMoveStateTrigger.MobGen, ContiMoveState.Event)
            .Permit(ContiMoveStateTrigger.End, ContiMoveState.Dormant);
            _stateMachine
            .Configure(ContiMoveState.Event)
            .SubstateOf(ContiMoveState.Move)
            .OnEntryAsync(async() =>
            {
                _nextEvent = null;
                _gameStage.Logger.LogDebug($"{_template.Name} started the event");

                // TODO: Mobspawns

                await MoveField.Dispatch(
                    new UnstructuredOutgoingPacket(PacketSendOperations.CONTIMOVE)
                    .WriteByte((byte)ContiMoveTarget.TargetMoveField)
                    .WriteByte((byte)ContiMoveStateTrigger.MobGen)
                    );
            })
            .OnExitAsync(async() =>
            {
                _gameStage.Logger.LogDebug($"{_template.Name} ended the event");

                // TODO: Mobspawns

                await MoveField.Dispatch(
                    new UnstructuredOutgoingPacket(PacketSendOperations.CONTIMOVE)
                    .WriteByte((byte)ContiMoveTarget.TargetMoveField)
                    .WriteByte((byte)ContiMoveStateTrigger.MobDestroy)
                    );
            })
            .Permit(ContiMoveStateTrigger.MobDestroy, ContiMoveState.Move);

            _stateMachine.OnTransitioned(t => _gameStage.Logger.LogDebug(
                                             $"{_template.Name} contimove state transitioned to {t.Destination}")
                                         );

            StartShipMoveField = fieldRepository.Retrieve(_template.StartShipMoveFieldID).Result;
            WaitField          = fieldRepository.Retrieve(_template.WaitFieldID).Result;
            MoveField          = fieldRepository.Retrieve(_template.MoveFieldID).Result;
            if (_template.CabinFieldID.HasValue)
            {
                CabinField = fieldRepository.Retrieve(_template.CabinFieldID.Value).Result;
            }
            EndField         = fieldRepository.Retrieve(_template.EndFieldID).Result;
            EndShipMoveField = fieldRepository.Retrieve(_template.EndShipMoveFieldID).Result;

            var now = DateTime.UtcNow;

            _nextBoarding = now
                            .AddMinutes(now.Minute % _template.Term == 0
                    ? 0
                    : _template.Term - now.Minute % _template.Term)
                            .AddMinutes(_template.Delay)
                            .AddSeconds(-now.Second);
            _gameStage.Logger.LogDebug($"{_template.Name} contimove is scheduled to board at {_nextBoarding}");

            ResetEvent();
        }
Ejemplo n.º 2
0
        public async Task OnTick(DateTime now)
        {
            var eventState = State;
            var nextState  = State;

            switch (State)
            {
            case ContinentState.Dormant:
                if (now > NextBoarding)
                {
                    eventState = ContinentState.Wait;
                    nextState  = ContinentState.Wait;
                }

                break;

            case ContinentState.Wait:
                if (now > NextBoarding.AddMinutes(Template.Wait))
                {
                    eventState = ContinentState.Start;
                    nextState  = ContinentState.Move;
                }

                break;

            case ContinentState.Move:
                if (NextEvent.HasValue &&
                    !EventDoing &&
                    now > NextEvent.Value)
                {
                    eventState = ContinentState.MobGen;
                }
                if (EventDoing &&
                    (now > NextBoarding
                     .AddMinutes(Template.Wait)
                     .AddMinutes(Template.EventEnd) ||
                     MoveField.GetObjects <FieldMob>().Any()))
                {
                    eventState = ContinentState.MobDestroy;
                }
                if (now > NextBoarding
                    .AddMinutes(Template.Wait)
                    .AddMinutes(Template.Required))
                {
                    eventState = ContinentState.End;
                    nextState  = ContinentState.Dormant;
                }

                break;
            }

            if (State != nextState)
            {
                State = nextState;
                Logger.Debug($"{Template.Info} continent state has been updated to {State}");
            }

            switch (eventState)
            {
            case ContinentState.Start:
                using (var p = new Packet(SendPacketOperations.CONTIMOVE))
                {
                    p.Encode <byte>((byte)ContinentState.TargetStartShipMoveField);
                    p.Encode <byte>((byte)ContinentState.Start);
                    await StartShipMoveField.BroadcastPacket(p);
                }

                await Move(WaitField, MoveField);

                break;

            case ContinentState.MobGen:
                NextEvent  = null;
                EventDoing = true;
                Logger.Debug($"{Template.Info} started the {eventState} event");

                await Task.WhenAll(((MobSummonItemTemplate)_templateManager
                                    .Get <ItemTemplate>(Template.GenMob.TemplateID)).Mobs
                                   .Select(m => _templateManager.Get <MobTemplate>(m.TemplateID))
                                   .Select(m => MoveField.Enter(new FieldMob(m)
                {
                    Position = Template.GenMob.Position
                })));

                using (var p = new Packet(SendPacketOperations.CONTIMOVE))
                {
                    p.Encode <byte>((byte)ContinentState.TargetMoveField);
                    p.Encode <byte>((byte)ContinentState.MobGen);
                    await MoveField.BroadcastPacket(p);
                }

                break;

            case ContinentState.MobDestroy:
                EventDoing = false;
                Logger.Debug($"{Template.Info} started the {eventState} event");

                await Task.WhenAll(MoveField
                                   .GetObjects <FieldMob>()
                                   .Select(m => MoveField.Leave(m)));

                using (var p = new Packet(SendPacketOperations.CONTIMOVE))
                {
                    p.Encode <byte>((byte)ContinentState.TargetMoveField);
                    p.Encode <byte>((byte)ContinentState.MobDestroy);
                    await MoveField.BroadcastPacket(p);
                }

                break;

            case ContinentState.End:
                using (var p = new Packet(SendPacketOperations.CONTIMOVE))
                {
                    p.Encode <byte>((byte)ContinentState.TargetEndShipMoveField);
                    p.Encode <byte>((byte)ContinentState.End);
                    await EndShipMoveField.BroadcastPacket(p);
                }

                await Move(MoveField, EndField);

                if (CabinField != null)
                {
                    await Move(CabinField, EndField);
                }

                NextBoarding = NextBoarding.AddMinutes(Template.Term);
                ResetEvent();
                break;
            }
        }