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!

Auto Save + gump

kokosbytow

Sorceror
Auto Save + gump

I use this script:

Code:
using System;
using System.IO;
using Server;
using Server.Commands;

namespace Server.Misc
{
	public class AutoSave : Timer
	{
		private static TimeSpan m_Delay = TimeSpan.FromMinutes( 20.0 );
		private static TimeSpan m_Warning = TimeSpan.Zero;
		//private static TimeSpan m_Warning = TimeSpan.FromSeconds( 15.0 );

		public static void Initialize()
		{
			new AutoSave().Start();
			CommandSystem.Register( "SetSaves", AccessLevel.Administrator, new CommandEventHandler( SetSaves_OnCommand ) );
		}

		private static bool m_SavesEnabled = true;

		public static bool SavesEnabled
		{
			get{ return m_SavesEnabled; }
			set{ m_SavesEnabled = value; }
		}

		[Usage( "SetSaves <true | false>" )]
		[Description( "Enables or disables automatic shard saving." )]
		public static void SetSaves_OnCommand( CommandEventArgs e )
		{
			if ( e.Length == 1 )
			{
				m_SavesEnabled = e.GetBoolean( 0 );
				e.Mobile.SendMessage( "Saves have been {0}.", m_SavesEnabled ? "enabled" : "disabled" );
			}
			else
			{
				e.Mobile.SendMessage( "Format: SetSaves <true | false>" );
			}
		}

		public AutoSave() : base( m_Delay - m_Warning, m_Delay )
		{
			Priority = TimerPriority.OneMinute;
		}

		protected override void OnTick()
		{
			if ( !m_SavesEnabled || AutoRestart.Restarting )
				return;

			if ( m_Warning == TimeSpan.Zero )
			{
				Save();
			}
			else
			{
				int s = (int)m_Warning.TotalSeconds;
				int m = s / 60;
				s %= 60;

				if ( m > 0 && s > 0 )
					World.Broadcast( 0x35, true, "The world will save in {0} minute{1} and {2} second{3}.", m, m != 1 ? "s" : "", s, s != 1 ? "s" : "" );
				else if ( m > 0 )
					World.Broadcast( 0x35, true, "The world will save in {0} minute{1}.", m, m != 1 ? "s" : "" );
				else
					World.Broadcast( 0x35, true, "The world will save in {0} second{1}.", s, s != 1 ? "s" : "" );

				Timer.DelayCall( m_Warning, new TimerCallback( Save ) );
			}
		}

		public static void Save()
		{
			if ( AutoRestart.Restarting )
				return;

			try{ Backup(); }
            catch (Exception e) { Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); }

			World.Save();
		}

		private static string[] m_Backups = new string[]
			{
				"Third Backup",
				"Second Backup",
				"Most Recent"
			};

		private static void Backup()
		{
			if ( m_Backups.Length == 0 )
				return;

			string root = Path.Combine( Core.BaseDirectory, "Backups/Automatic" );

			if ( !Directory.Exists( root ) )
				Directory.CreateDirectory( root );

			string[] existing = Directory.GetDirectories( root );

			for ( int i = 0; i < m_Backups.Length; ++i )
			{
				DirectoryInfo dir = Match( existing, m_Backups[i] );

				if ( dir == null )
					continue;

				if ( i > 0 )
				{
					string timeStamp = FindTimeStamp( dir.Name );

					if ( timeStamp != null )
					{
						try{ dir.MoveTo( FormatDirectory( root, m_Backups[i - 1], timeStamp ) ); }
						catch{}
					}
				}
				else
				{
					try{ dir.Delete( true ); }
					catch{}
				}
			}

			string saves = Path.Combine( Core.BaseDirectory, "Saves" );

			if ( Directory.Exists( saves ) )
				Directory.Move( saves, FormatDirectory( root, m_Backups[m_Backups.Length - 1], GetTimeStamp() ) );
		}

		private static DirectoryInfo Match( string[] paths, string match )
		{
			for ( int i = 0; i < paths.Length; ++i )
			{
				DirectoryInfo info = new DirectoryInfo( paths[i] );

				if ( info.Name.StartsWith( match ) )
					return info;
			}

			return null;
		}

		private static string FormatDirectory( string root, string name, string timeStamp )
		{
			return Path.Combine( root, String.Format( "{0} ({1})", name, timeStamp ) );
		}

		private static string FindTimeStamp( string input )
		{
			int start = input.IndexOf( '(' );

			if ( start >= 0 )
			{
				int end = input.IndexOf( ')', ++start );

				if ( end >= start )
					return input.Substring( start, end-start );
			}

			return null;
		}

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

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

and i try add this:
Code:
			foreach ( Mobile m in mobs ) 
			{
				m.SendGump ( new SaveGump() );
			}
			World.Save(false);
			foreach ( Mobile m in mobs ) 
			{
				m.CloseGump( typeof(SaveGump) );
			}

And i have error... someone tells me why this not work ?
 

kokosbytow

Sorceror
Code:
Errors:
 + Misc/AutoSave.cs:
    CS0246: Line 76: The type or namespace name `ArrayList' could not be found. Are you missing a using directive or an assembly reference?

if i not use ArrayList i have this error:
Code:
Errors:
 + Misc/AutoSave.cs:
    CS0103: Line 84: The name `mobs' does not exist in the current context
    CS0103: Line 89: The name `mobs' does not exist in the current context

this is CODE:

Code:
		public static void Save()
		{
			ArrayList mobs = new ArrayList( World.Mobiles.Values ); 		
		
			if ( AutoRestart.Restarting )
				return;

			try{ Backup(); }
            catch (Exception e) { Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); }

			World.Save();
			
			foreach ( Mobile m in mobs ) 
			{
				m.SendGump ( new SaveGump() );
			}
			World.Save(false);
			foreach ( Mobile m in mobs ) 
			{
				m.CloseGump( typeof(SaveGump) );
			}
			
		}

I know what i make bad i not add
using System;
using System.Reflection;
using System.Collections;
using System.IO;
using Server;
using Server.Commands;
using Server.Network;
using Server.Items;
using Server.Mobiles;
using Server.Misc;
using Server.Accounting;
using Server.Gumps;
and now compile without error but i login and wanna make [save serwer is crashed . This is crash error:

Exception:
System.InvalidCastException: Cannot cast from source type to destination type.
at System.Collections.Generic.Dictionary`2+ValueCollection[Server.Serial,Server.Mobile].System.Collections.ICollection.CopyTo (System.Array , Int32 ) [0x00000]
at System.Collections.ArrayList.InsertRange (Int32 index, ICollection c) [0x00000]
at System.Collections.ArrayList.AddRange (ICollection c) [0x00000]
at System.Collections.ArrayList..ctor (ICollection c) [0x00000]
at Server.Misc.AutoSave.Save () [0x00000]
at Server.Commands.CommandHandlers.Save_OnCommand (Server.Commands.CommandEventArgs e) [0x00000]
at Server.Commands.CommandSystem.Handle (Server.Mobile from, System.String text, MessageType type) [0x00000]
at Server.Mobile.DoSpeech (System.String text, System.Int32[] keywords, MessageType type, Int32 hue) [0x00000]
at Server.Mobiles.PlayerMobile.DoSpeech (System.String text, System.Int32[] keywords, MessageType type, Int32 hue) [0x00000]
at Server.Network.PacketHandlers.UnicodeSpeech (Server.Network.NetState state, Server.Network.PacketReader pvSrc) [0x00000]
at Server.Network.MessagePump.HandleReceive (Server.Network.NetState ns) [0x00000]
at Server.Network.MessagePump.Slice () [0x00000]
at Server.Core.Main (System.String[] args) [0x00000]
 
Try this and see if it works for you. I placed everything in red where your edits will need to be done....


Code:
using System;
using System.IO;
using Server;
using Server.Commands;
[COLOR=Red]using Server.Gumps;
using System.Reflection;
using System.Collections;
using Server.Network;
using Server.Items;
using Server.Mobiles;
using Server.Misc;
using Server.Accounting;[/COLOR]

namespace Server.Misc
{
    public class AutoSave : Timer
    {
        private static TimeSpan m_Delay = TimeSpan.FromMinutes(5.0);
        private static TimeSpan m_Warning = TimeSpan.Zero;
        //private static TimeSpan m_Warning = TimeSpan.FromSeconds( 15.0 );

        public static void Initialize()
        {
            new AutoSave().Start();
            CommandSystem.Register("SetSaves", AccessLevel.Administrator, new CommandEventHandler(SetSaves_OnCommand));
        }

        private static bool m_SavesEnabled = true;

        public static bool SavesEnabled
        {
            get { return m_SavesEnabled; }
            set { m_SavesEnabled = value; }
        }

        [Usage("SetSaves <true | false>")]
        [Description("Enables or disables automatic shard saving.")]
        public static void SetSaves_OnCommand(CommandEventArgs e)
        {
            if (e.Length == 1)
            {
                m_SavesEnabled = e.GetBoolean(0);
                e.Mobile.SendMessage("Saves have been {0}.", m_SavesEnabled ? "enabled" : "disabled");
            }
            else
            {
                e.Mobile.SendMessage("Format: SetSaves <true | false>");
            }
        }

        public AutoSave()
            : base(m_Delay - m_Warning, m_Delay)
        {
            Priority = TimerPriority.OneMinute;
        }

        protected override void OnTick()
        {
            if (!m_SavesEnabled || AutoRestart.Restarting)
                return;

            if (m_Warning == TimeSpan.Zero)
            {
                Save();
            }
            else
            {
                int s = (int)m_Warning.TotalSeconds;
                int m = s / 60;
                s %= 60;

                if (m > 0 && s > 0)
                    World.Broadcast(0x35, true, "The world will save in {0} minute{1} and {2} second{3}.", m, m != 1 ? "s" : "", s, s != 1 ? "s" : "");
                else if (m > 0)
                    World.Broadcast(0x35, true, "The world will save in {0} minute{1}.", m, m != 1 ? "s" : "");
                else
                    World.Broadcast(0x35, true, "The world will save in {0} second{1}.", s, s != 1 ? "s" : "");

                Timer.DelayCall(m_Warning, new TimerCallback(Save));
            }
        }

        public static void Save()
        {
            if (AutoRestart.Restarting)
                return;

[COLOR=Red]            ArrayList mobs = new ArrayList(World.Mobiles.Values);
            foreach (Mobile m in mobs)
            {
                if (m != null && m is PlayerMobile)
                    m.SendGump(new SaveGump());   // change to the name of your custom save gump
            }[/COLOR]

            try { Backup(); }
            catch (Exception e) { Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); }

            World.Save();

[COLOR=Red]            // Comment these lines out to keep your save gump open after the save has completed.
            foreach (Mobile m in mobs)
            {
                if (m != null && m is PlayerMobile)
                    m.CloseGump(typeof(SaveGump));
            }[/COLOR]
        }

        private static string[] m_Backups = new string[]
            {
                "Third Backup",
                "Second Backup",
                "Most Recent"
            };

        private static void Backup()
        {
            if (m_Backups.Length == 0)
                return;

            string root = Path.Combine(Core.BaseDirectory, "Backups/Automatic");

            if (!Directory.Exists(root))
                Directory.CreateDirectory(root);

            string[] existing = Directory.GetDirectories(root);

            for (int i = 0; i < m_Backups.Length; ++i)
            {
                DirectoryInfo dir = Match(existing, m_Backups[i]);

                if (dir == null)
                    continue;

                if (i > 0)
                {
                    string timeStamp = FindTimeStamp(dir.Name);

                    if (timeStamp != null)
                    {
                        try { dir.MoveTo(FormatDirectory(root, m_Backups[i - 1], timeStamp)); }
                        catch { }
                    }
                }
                else
                {
                    try { dir.Delete(true); }
                    catch { }
                }
            }

            string saves = Path.Combine(Core.BaseDirectory, "Saves");

            if (Directory.Exists(saves))
                Directory.Move(saves, FormatDirectory(root, m_Backups[m_Backups.Length - 1], GetTimeStamp()));
        }

        private static DirectoryInfo Match(string[] paths, string match)
        {
            for (int i = 0; i < paths.Length; ++i)
            {
                DirectoryInfo info = new DirectoryInfo(paths[i]);

                if (info.Name.StartsWith(match))
                    return info;
            }

            return null;
        }

        private static string FormatDirectory(string root, string name, string timeStamp)
        {
            return Path.Combine(root, String.Format("{0} ({1})", name, timeStamp));
        }

        private static string FindTimeStamp(string input)
        {
            int start = input.IndexOf('(');

            if (start >= 0)
            {
                int end = input.IndexOf(')', ++start);

                if (end >= start)
                    return input.Substring(start, end - start);
            }

            return null;
        }

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

            return String.Format("{0}-{1}-{2} {3}-{4:D2}-{5:D2}",
                    now.Day,
                    now.Month,
                    now.Year,
                    now.Hour,
                    now.Minute,
                    now.Second
                );
        }
    }
}
 
kokosbytow;799121 said:
i try this ... this same crash


I have tried that file in an SVN release system and it works just fine. The file has not changed much since 2.0RC1. Maybe it's your save gump file causing the crash and not autosave.cs
 

Soteric

Knight
Or even better variant
Code:
foreach ( NetState state in NetState.Instances )
	state.Mobile.SendGump ( new SaveGump() );
"using Server.Network;" should be added to the top of the script also
 

kokosbytow

Sorceror
Soteric;799191 said:
Or even better variant
Code:
foreach ( NetState state in NetState.Instances )
	state.Mobile.SendGump ( new SaveGump() );
"using Server.Network;" should be added to the top of the script also


This not work too .... not the crash of the server but gump does not send.
 

Soteric

Knight
Works fine with me. I guess you've made something wrong. Post SaveGump and AutoSave.cs with your changes
 

kokosbytow

Sorceror
Soteric;800068 said:
Works fine with me. I guess you've made something wrong. Post SaveGump and AutoSave.cs with your changes

Yes i make bad this but i repair this now send gump , but if is save now send gump but after save not automatically closes ... maybe i must make this:
Code:
			foreach ( NetState state in NetState.Instances )
	             state.Mobile.CloseGump ( new SaveGump() );
 

Soteric

Knight
Yes, if you need to close gumps.
P.S. World save usually lasts less than a second... what a point of sending any gumps and immidiate closing them?
 

kokosbytow

Sorceror
I add this
Code:
			foreach ( NetState state in NetState.Instances )
	             state.Mobile.CloseGump ( new SaveGump() );

but i cant compile my scrpits 0 errors but i see only this:

Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.
Scripts: Compiling C# scripts...ScriptCompiler: : /home/admin/Desktop/UO/runuo.exe (Location of the symbol related to previous error)
 
Top