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(); }
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; } }