示例#1
0
        /// <summary>
        /// Executes the specified command and adds it to the command history.</summary>
        /// <param name="worldState">
        /// The <see cref="WorldState"/> on which the specified <paramref name="command"/> is
        /// executed.</param>
        /// <param name="command">
        /// The <see cref="Command"/> to execute.</param>
        /// <param name="queued">
        /// <c>true</c> if <paramref name="command"/> was enqueued by the <see
        /// cref="CommandExecutor.QueueCommand"/> method; <c>false</c> if <paramref name="command"/>
        /// was directly supplied to the <see cref="ProcessCommand"/> method.</param>
        /// <exception cref="ArgumentException">
        /// <paramref name="worldState"/> does not equal the <see cref="Session.WorldState"/> of the
        /// current <see cref="Session"/>.</exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="worldState"/> or <paramref name="command"/> is a null reference.
        /// </exception>
        /// <exception cref="InvalidCommandException">
        /// The specified <paramref name="command"/> contains data that is invalid with respect to
        /// the specified <paramref name="worldState"/>.</exception>
        /// <remarks><para>
        /// <b>ExecuteCommand</b> attempts to execute the specified <paramref name="command"/> by
        /// calling the base class implementation of <see cref="CommandExecutor.ExecuteCommand"/>.
        /// </para><para>
        /// On success, <b>ExecuteCommand</b> shows any events that were generated and sets the <see
        /// cref="Session.WorldChanged"/> flag of the current <see cref="Session"/>.
        /// </para><para>
        /// If <paramref name="queued"/> is <c>true</c>, <b>ExecuteCommand</b> inserts additional
        /// delays before and during command execution, and scrolls the default <see
        /// cref="Session.MapView"/> to bring the affected sites into view. These additional actions
        /// are skipped if the <see cref="AbortSignal"/> is set, however.</para></remarks>

        protected override void ExecuteCommand(
            WorldState worldState, Command command, bool queued)
        {
            if (worldState == null)
            {
                ThrowHelper.ThrowArgumentNullException("worldState");
            }
            if (command == null)
            {
                ThrowHelper.ThrowArgumentNullException("command");
            }

            if (worldState != Session.Instance.WorldState)
            {
                ThrowHelper.ThrowArgumentExceptionWithFormat("worldState",
                                                             Tektosyne.Strings.ArgumentNotEquals, "Session.Instance.WorldState");
            }

            // get current delay for interactive replay
            int delay = ApplicationOptions.Instance.Game.Replay.Delay;

            // add delay between queued commands
            if (queued)
            {
                AbortSignal.WaitOne(2 * delay, false);
            }

            // validate & show command
            command.Validate(worldState);
            ShowCommand(command);

            PointI  source  = command.Source.Location;
            PointI  target  = command.Target.Location;
            MapView mapView = Session.MapView;

            if (queued && !AbortSignal.WaitOne(0, false))
            {
                bool sourceValid = Finder.MapGrid.Contains(source);

                AsyncAction.Invoke(delegate {
                    // scroll command sites into view
                    mapView.ScrollIntoView(source, target);

                    // highlight source site if valid
                    if (sourceValid)
                    {
                        mapView.SelectedSite = source;

                        // select first entity if specified
                        EntityReference[] entities = command.Entities;
                        if (entities != null && entities.Length > 0)
                        {
                            MainWindow.Instance.SelectedEntity = entities[0].Id;
                        }
                    }
                });

                // show valid source site for a while
                if (sourceValid)
                {
                    AbortSignal.WaitOne(delay, false);
                }
            }

            // execute command and add to history
            command.Execute(new ExecutionContext(worldState, QueueCommand, ShowCommandEvent));
            worldState.History.AddCommand(command, worldState.CurrentTurn);

            AsyncAction.Invoke(delegate {
                // move to target if valid, else update source
                if (Finder.MapGrid.Contains(target))
                {
                    mapView.SelectedSite = target;
                }
                else
                {
                    MainWindow.Instance.UpdateSelection();
                }

                // ensure command effects are shown
                mapView.Redraw();
            });

            // world state has changed
            Session.Instance.SetWorldChanged();
        }