RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[RunUO 2.0 RC1] [QuickRestart

milt

Knight
[RunUO 2.0 RC1] [QuickRestart

Ladies and gentleman, boys and girls -- JB & MilkBoy Inc. Presents...

[QUICKRESTART

So WTF does it do?
The quick restart command will compile the scripts in game, and then restart the server. This makes it so that the scripts are cached, thus making your server start a lot quicker. You only need to use quick restart if you have made changes to your scripts, or else it will just restart normally.

Quick restart will not lock up your server while compiling, because it runs on a separate thread. After it is done compiling the scripts, it makes the new hash and dll file, and puts a *.new extension on them. The server then calls Launcher.exe and shuts down.

Launcher.exe
This sexy launcher program was made by Jeff. What it does is rename and replace the hash and dll files, in order for the server to cache correctly. After that, it just launches RunUO.

Features
The [QuickRestart command supports command line arguments for RunUO. However, if you pass debug to it, the server will still recompile the scripts because of debug mode.
Example - "[QuickRestart -profile -service" will send the -profile and -service switch to runuo when it restarts.

Installation
All you need to do is extract and drop QuickRestart.cs somewhere into your Scripts folder, and put Launcher.exe into your main RunUO directory (the same folder as RunUO.exe is in).

For those of you interested, here is the sexy Launcher.exe source code:
Code:
/***********************************************
*					       *
* This script was made by Jeff Boulanger.      *
*					       *
* Email: [email protected]			       *
*					       *
************************************************
*
* Original Idea By: milt, AKA Pokey
*
* Email: [email protected]
*
* AIM: TrueBornStunna
*
* Website: www.pokey.f13nd.net
*
* Version: 1.0.0
*
* Release Date: June 30, 2006
*
************************************************/
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Diagnostics;

public class Launcher
{
    static bool _debug = false;
    static bool _service = false;
    static bool _profile = false;
    static bool _haltonwarning = false;

    public static void Main( string[] args )
    {
        for( int i = 0; i < args.Length; ++i )
        {
            if( args[i].ToLower() == "-debug" )
                _debug = true;
            else if( args[i].ToLower() == "-service" )
                _service = true;
            else if( args[i].ToLower() == "-profile" )
                _profile = true;
            else if( args[i].ToLower() == "-haltonwarning" )
                _haltonwarning = true;
        }

        string dllpath = "Scripts\\Output\\Scripts.CS.dll";
        string newpath = "Scripts\\Output\\Scripts.CS.dll.new";
        string hashpath = "Scripts\\Output\\Scripts.CS.hash";
        string newhashpath = "Scripts\\Output\\Scripts.CS.hash.new";

        Console.Write( "Waiting for RunUO.exe to exit..." );
        Process[] processes = Process.GetProcessesByName( "RunUO.exe" );

        while( processes.Length > 0 )
        {
            Thread.Sleep( 50 );
            processes = Process.GetProcessesByName( "RunUO.exe" );
        }

        Thread.Sleep( 1000 );

        Console.WriteLine( "done." );

        Console.Write( "Checking for {0}...", newpath );
        if( File.Exists( Path.Combine( Directory.GetCurrentDirectory(), newpath ) ) )
        {
            try
            {
                Console.Write( "Renaming the file..." );
                MoveFile( newpath, dllpath );
                Console.Write( "done." );
            }
            catch( Exception e )
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine( "an error occured while trying to move the file." );
                Console.WriteLine( "<Do you wish to log this exception?[Y/N]>" );
                if( Console.ReadKey().Key == ConsoleKey.Y )
                    LogError( e );
                
                Console.ForegroundColor = ConsoleColor.Gray;
            }
        }
        else
            Console.WriteLine( "not found." );

        Console.Write( "Checking for {0}...", newhashpath );
        if( File.Exists( Path.Combine( Directory.GetCurrentDirectory(), newhashpath ) ) )
        {
            try
            {
                Console.Write( "Renaming the file..." );
                MoveFile( newhashpath, hashpath );
                Console.Write( "done." );
            }
            catch( Exception e )
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine( "an error occured while trying to move the file." );
                Console.WriteLine( "<Do you wish to log this exception?[Y/N]>" );
                if( Console.ReadKey().Key == ConsoleKey.Y )
                    LogError( e );
                Console.ForegroundColor = ConsoleColor.White;
            }
        }
        else
            Console.WriteLine( "not found." );

        if( File.Exists( "RunUO.exe" ) )
            Process.Start( "RunUO.exe", Arguments() );

        Process.GetCurrentProcess().Kill();
    }

    private static string Arguments()
    {
        StringBuilder sb = new StringBuilder();

        if( _debug )
            sb.Append( " -debug" );
        if( _service )
            sb.Append( " -service" );
        if( _profile )
            sb.Append( " -profile" );
        if( _haltonwarning )
            sb.Append( " -haltonwarning" );

        return sb.ToString();
    }

    private static void MoveFile( string source, string destination )
    {
        if( !File.Exists( Path.Combine( Directory.GetCurrentDirectory(), source ) ) )
            throw new System.IO.FileNotFoundException( "File not found",
                Path.Combine( Directory.GetCurrentDirectory(), source ) );

        DateTime writeTime = File.GetLastWriteTime( source );

        if( File.Exists( destination ) )
            File.Delete( destination );

        FileStream reader = null;
        FileStream writer = null;

        try
        {
            reader = new FileStream( source, FileMode.Open );
            writer = new FileStream( destination, FileMode.OpenOrCreate );

            byte[] buffer = new byte[512];
            int totalSent = 0;
            int percent = 0;

            while( totalSent < reader.Length )
            {
                int chunkSize = ( int )Math.Min( ( long )buffer.Length, reader.Length - reader.Position );

                reader.Read( buffer, 0, chunkSize );
                writer.Write( buffer, 0, chunkSize );

                totalSent += chunkSize;

                int newpercent = GetPercent( totalSent, reader.Length );

                if( newpercent > percent )
                {
                    UpdatePercent( newpercent );
                    percent = newpercent;
                }
            }
        }
        catch( Exception e )
        {
            throw e;
        }
        finally
        {
            reader.Close();
            writer.Close();
        }        

        File.SetLastWriteTime( destination, writeTime );

        File.Delete( source );
    }

    private static void UpdatePercent( int percent )
    {
        int oldX = Console.CursorLeft;
        int oldY = Console.CursorTop;
        int totalblocks = 20;
        int blocks = percent / 5;
        int remainingblocks = totalblocks - blocks;

        Console.SetCursorPosition( 0, oldY + 1 );

        Console.Write( "[" );

        for( int i = 0; i < blocks; i++ )
            DrawBlock( percent );

        for( int i = 0; i < remainingblocks; i++ )
            Console.Write( "=" );

        Console.Write( "]{0}%", percent );
        Console.SetCursorPosition( oldX, oldY );
    }


    private static void DrawBlock( int percent )
    {
        ConsoleColor oldColor = Console.BackgroundColor;
        Console.BackgroundColor = GetColor( percent );
        Console.Write( " " );
        Console.BackgroundColor = oldColor;
    }

    private static ConsoleColor GetColor( int percent )
    {
        if( percent < 20 )
            return ConsoleColor.DarkRed;
        else if( percent < 40 )
            return ConsoleColor.Red;
        else if( percent < 60 )
            return ConsoleColor.Yellow;
        else if( percent < 80 )
            return ConsoleColor.Green;
        else
            return ConsoleColor.Blue;
    }

    private static int GetPercent( int totalSent, long p )
    {
        return ( int )( ( ( long )totalSent * 100 ) / p );
    }

    private static void LogError( Exception e )
    {
        Logger.Add( "[" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) + "] " + e.ToString() );
    }
    public class Logger
    {
        private static string m_Path = Directory.GetCurrentDirectory();

        private static bool m_Virgin = true;

        private static FileStream m_File;
        public static FileStream File
        {
            get
            {
                if( m_File == null )
                    m_File = new FileStream( Path.Combine( m_Path, ( "QuickStartLog" + GetTimeStamp() + ".log" ) ), FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite );

                return m_File;
            }
        }

        private static string GetTimeStamp()
        {
            DateTime now = DateTime.Now;

            return String.Format( "{0}-{1}-{2}-{3}-{4}-{5}",
                            now.Day,
                            now.Month,
                            now.Year,
                            now.Hour,
                            now.Minute,
                            now.Second
                    );
        }

        public static void Close()
        {
            m_Writer.Close();
            m_File.Close();
            m_File = null;
            m_Writer = null;
        }

        private static StreamWriter m_Writer;
        public static StreamWriter Writer
        {
            get
            {
                if( m_Writer == null )
                    m_Writer = new StreamWriter( File );
                return m_Writer;
            }
        }

        public static void Add( string text )
        {
            if( m_Virgin )
            {
                m_Virgin = false;
                string str = String.Format( "[{0}] Logging started.", DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) );
                Writer.WriteLine( str );
            }

            Writer.WriteLine( "" );
            Writer.WriteLine( text );

            Close();
        }
    }
}

Please enjoy.
 

Attachments

  • QuickRestart.zip
    9.8 KB · Views: 926

Pyro-Tech

Knight
i always run my server in debug mode.....do i just do [quickrestart -debug then?

and is there a way to automatically do debug on a normal restart?

but yes....this is great :)
 

milt

Knight
Pyro-Tech said:
i always run my server in debug mode.....do i just do [quickrestart -debug then?

and is there a way to automatically do debug on a normal restart?

but yes....this is great :)
I don't think you can do debug mode with a normal restart.

As for the debug mode with [QuickRestart... We are actually looking into starting the server with debug switch and still getting it cached. I think all we have to do is make the loader ignore the -debug switch, because QuickRestart will already compile the scripts with debug turned on. So technically, the server will not be started in debug mode, but the scripts will have been compiled in debug (which is what I think happens anyway). If we are right, then when the server crashes, you will still get a debug crashlog. This is a really easy mod, it just needs tested.

When Jeff gets the time I'm sure that he will post you a new Loader. I could make the change but I don't have Visual Studio on this computer :).
 

milt

Knight
Pyro,

I just tested it out, and it works! All I did was remove 2 lines of code from the Launcher and it worked fine. If you are willing to recompile the launcher, just delete these 2 lines of code from the Arguments() method:
Code:
        if( _debug )
            sb.Append( " -debug" );
If you don't want to recompile, just wait for Jeff to do it and we'll upload it here.

When you start the server with [QuickRestart -debug, next time the server starts it will not say that it is running in debug mode, but it will still generate the debug crashlog. :cool:
 

Jeff

Lord
advani said:
huh runuo 2.0 already have this
Basically this will compile the scripts if need be before your server restarts, thus saving you about 2-5 mins of downtime per restart.
 

Jeff

Lord
BeneathTheStars said:
And any errors during this quick restart, will go to the already opened console?
Not entirely sure I think they post in game to staff, Milt will need to comment on this :(
 

milt

Knight
BeneathTheStars said:
And any errors during this quick restart, will go to the already opened console?
As of now, the game will just tell you that you have errors, and that it cannot restart. I think that if we end up writing another version, I'll make an error pumper to the client :D
 

HomeDaddy

Wanderer
This is a great idea, I hate having to leave people hanging for a few min while it recompiles.

I am using BeneathTheStars ConsoleCommands Script so I can do restarts etc, from the console, instead of having to login to do it. I was wondering what it would take to convert this to work from the console.

Thnaks
 

Lubomir

Wanderer
A Suggestion for an Added Feature.

In a future release, would it be possible to have it do a save just before the restart. I have tried this on my shard and it doesn't seem to do a save before the restart. Thus, anything a player has done since the last save is lost.

otherwise, thank you for a script that works very well.

Lubomir :)
 

Jeff

Lord
Lubomir said:
In a future release, would it be possible to have it do a save just before the restart. I have tried this on my shard and it doesn't seem to do a save before the restart. Thus, anything a player has done since the last save is lost.

otherwise, thank you for a script that works very well.

Lubomir :)
It does do that.....


Code:
		public static void DoRestart(bool normal)
		{
			[COLOR="Red"]AutoSave.Save();[/COLOR]

			if(normal)
			{
				if( File.Exists("Launcher.exe") )
				{
					m_Mobile.SendMessage("Launcher found, restarting...");
					Process.Start("Launcher.exe", Arguments());
					Core.Process.Kill();
				}
			}

			Process.Start( Core.ExePath, Arguments() );
			Core.Process.Kill();
		}
 
Top