/
etc/
lib/
src/Abilities/
src/Abilities/Skills/
src/Abilities/Spells/
src/Abilities/Spells/Enums/
src/Affects/
src/ArtheaConsole/
src/ArtheaConsole/Properties/
src/ArtheaGUI/Properties/
src/Clans/Enums/
src/Commands/Communication/
src/Commands/ItemCommands/
src/Connections/
src/Connections/Colors/
src/Connections/Enums/
src/Connections/Players/
src/Connections/Players/Enums/
src/Continents/
src/Continents/Areas/
src/Continents/Areas/Characters/
src/Continents/Areas/Characters/Enums/
src/Continents/Areas/Items/
src/Continents/Areas/Items/Enums/
src/Continents/Areas/Rooms/
src/Continents/Areas/Rooms/Enums/
src/Continents/Areas/Rooms/Exits/
src/Creation/
src/Creation/Attributes/
src/Creation/Interfaces/
src/Database/
src/Database/Interfaces/
src/Environment/
src/Properties/
src/Scripts/Enums/
src/Scripts/Interfaces/
#region Arthea License

/***********************************************************************
*  Arthea MUD by R. Jennings (2007)      http://arthea.googlecode.com/ *
*  By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/

#endregion

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
#if !MONO
using System.Runtime.Remoting.Channels.Tcp;
#endif
using Arthea.Connections;
using Arthea.Connections.Enums;
using Arthea.Connections.Players;
using Arthea.Environment;

namespace Arthea.Commands.Admin
{
    /// <summary>
    /// Implementation of a reboot command.
    /// </summary>
    public class RebootCommand : Command
    {
        #region [rgn] Constructors (1)

        /// <summary>
        /// Initializes a new instance of the <see cref="RebootCommand"/> class.
        /// </summary>
        public RebootCommand() : base("reboot", "reboots the game, keeping connections", Levels.Admin)
        {
        }

        #endregion [rgn]

        #region [rgn] Methods (1)

        // [rgn] Public Methods (1)

        /// <summary>
        /// Processes the command for a player.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="argument">The argument.</param>
        public override void Process(Player player, String argument)
        {
#if MONO
	        player.WriteLine("Reboot not available on this server.");
#else
            Log.Info("Reboot by {0}...", player.Name);
            player.Act(null, null, Act.ToWorld, "$n has initiated a reboot.");
            player.WriteLine("Reboot activated...");

            TcpChannel channel = new TcpChannel(RebootRecovery.Port);

            ChannelServices.RegisterChannel(channel, false); //register channel

            //register remote object
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof (RebootRecovery),
                "RebootRecovery",
                WellKnownObjectMode.SingleCall);

            System.Diagnostics.Process.Start(
                System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, "-reboot");

            while (!RebootRecovery.Done)
            {
            }

            ChannelServices.UnregisterChannel(channel);

            Server.Instance.State = ServerState.Stopping;
#endif
        }

        #endregion [rgn]
    }

    /// <summary>
    /// Implementation of a reboot recovery.
    /// </summary>
    public class RebootRecovery : MarshalByRefObject
    {
        #region [rgn] Fields (2)

        /// <summary>
        /// Signals this recovery is done
        /// </summary>
        public static bool Done = false;

        /// <summary>
        /// The port to use.
        /// </summary>
        public static int Port = 4010;

        #endregion [rgn]

        #region [rgn] Methods (2)

        // [rgn] Public Methods (2)

        /// <summary>
        /// Signales the recovery is done.
        /// </summary>
        public void Finished()
        {
            Done = true;
        }

        /// <summary>
        /// Transfers the connections.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        public Dictionary<string, SocketInformation> TransferConnections(int processId)
        {
            Log.Info("Transferring connections...");

            Dictionary<string, SocketInformation> connections =
                new Dictionary<string, SocketInformation>();

            foreach (Connection con in Lists.Connections)
            {
                if (con.State != ConnectionState.Playing)
                {
                    continue;
                }
                connections.Add(con.Player.Name, con.Socket.DuplicateAndClose(processId));
            }

            return connections;
        }

        #endregion [rgn]
    }
}