skillcaps and things that exceed it Possible threading issue Addition of Generic FindItemsByType - List<T> findItemsByType<T>() Change to make polymorph not have a timer and instead a toggle skill KiAttack no longer works with ranged weapons Poison strike speed and damage changed Necro spells now affected by FC Must have atleast 50 weapon skill if no shield equipped to use Evasion Stalking bonus capped at 10 + skill/10 Stalking bonus now Clears Bugfix w/Guilds Crashguard Exception message moved closer to the top of the file. Character creation of Pallys and necros using advanced skills now gives skill items Honor no longer works on Players Pre-ML area HitArea attacks nolonger require LoS Serialization fix for BladeOfTheRighteous RidingSwipe now has paralyzation immunity as with NerveStrike and ParaBlow AnkhEast renamed to AnkhNorth LeggingsOfBane no longer have 510 HP ElvenWashBasinEastAddon Fixed AnsellaGryen won't be renamed each time the server Restarts DiseasedCats are properly named Localization fixes in DefBlacksmithy BearMasks/DearMAsks and things that extend from them now can be repaired
260 lines
No EOL
6.2 KiB
C#
260 lines
No EOL
6.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Net.Mail;
|
|
using Server;
|
|
using Server.Accounting;
|
|
using Server.Network;
|
|
|
|
namespace Server.Misc
|
|
{
|
|
public class CrashGuard
|
|
{
|
|
private static bool Enabled = true;
|
|
private static bool SaveBackup = true;
|
|
private static bool RestartServer = true;
|
|
private static bool GenerateReport = true;
|
|
|
|
public static void Initialize()
|
|
{
|
|
if ( Enabled ) // If enabled, register our crash event handler
|
|
EventSink.Crashed += new CrashedEventHandler( CrashGuard_OnCrash );
|
|
}
|
|
|
|
public static void CrashGuard_OnCrash( CrashedEventArgs e )
|
|
{
|
|
if ( SaveBackup )
|
|
Backup();
|
|
|
|
if ( GenerateReport )
|
|
GenerateCrashReport( e );
|
|
|
|
if ( Core.Service )
|
|
e.Close = true;
|
|
else if ( RestartServer )
|
|
Restart( e );
|
|
}
|
|
|
|
private static void SendEmail( string filePath )
|
|
{
|
|
Console.Write( "Crash: Sending email..." );
|
|
|
|
MailMessage message = new MailMessage( "RunUO", Email.CrashAddresses );
|
|
|
|
message.Subject = "Automated RunUO Crash Report";
|
|
|
|
message.Body = "Automated RunUO Crash Report. See attachment for details.";
|
|
|
|
message.Attachments.Add( new Attachment( filePath ) );
|
|
|
|
if ( Email.Send( message ) )
|
|
Console.WriteLine( "done" );
|
|
else
|
|
Console.WriteLine( "failed" );
|
|
}
|
|
|
|
private static string GetRoot()
|
|
{
|
|
try
|
|
{
|
|
return Path.GetDirectoryName( Environment.GetCommandLineArgs()[0] );
|
|
}
|
|
catch
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
private static string Combine( string path1, string path2 )
|
|
{
|
|
if ( path1 == "" )
|
|
return path2;
|
|
|
|
return Path.Combine( path1, path2 );
|
|
}
|
|
|
|
private static void Restart( CrashedEventArgs e )
|
|
{
|
|
string root = GetRoot();
|
|
|
|
Console.Write( "Crash: Restarting..." );
|
|
|
|
try
|
|
{
|
|
Process.Start( Core.ExePath, Core.Arguments );
|
|
Console.WriteLine( "done" );
|
|
|
|
e.Close = true;
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine( "failed" );
|
|
}
|
|
}
|
|
|
|
private static void CreateDirectory( string path )
|
|
{
|
|
if ( !Directory.Exists( path ) )
|
|
Directory.CreateDirectory( path );
|
|
}
|
|
|
|
private static void CreateDirectory( string path1, string path2 )
|
|
{
|
|
CreateDirectory( Combine( path1, path2 ) );
|
|
}
|
|
|
|
private static void CopyFile( string rootOrigin, string rootBackup, string path )
|
|
{
|
|
string originPath = Combine( rootOrigin, path );
|
|
string backupPath = Combine( rootBackup, path );
|
|
|
|
try
|
|
{
|
|
if ( File.Exists( originPath ) )
|
|
File.Copy( originPath, backupPath );
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
private static void Backup()
|
|
{
|
|
Console.Write( "Crash: Backing up..." );
|
|
|
|
try
|
|
{
|
|
string timeStamp = GetTimeStamp();
|
|
|
|
string root = GetRoot();
|
|
string rootBackup = Combine( root, String.Format( "Backups/Crashed/{0}/", timeStamp ) );
|
|
string rootOrigin = Combine( root, String.Format( "Saves/" ) );
|
|
|
|
// Create new directories
|
|
CreateDirectory( rootBackup );
|
|
CreateDirectory( rootBackup, "Accounts/" );
|
|
CreateDirectory( rootBackup, "Items/" );
|
|
CreateDirectory( rootBackup, "Mobiles/" );
|
|
CreateDirectory( rootBackup, "Guilds/" );
|
|
CreateDirectory( rootBackup, "Regions/" );
|
|
|
|
// Copy files
|
|
CopyFile( rootOrigin, rootBackup, "Accounts/Accounts.xml" );
|
|
|
|
CopyFile( rootOrigin, rootBackup, "Items/Items.bin" );
|
|
CopyFile( rootOrigin, rootBackup, "Items/Items.idx" );
|
|
CopyFile( rootOrigin, rootBackup, "Items/Items.tdb" );
|
|
|
|
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.bin" );
|
|
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.idx" );
|
|
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.tdb" );
|
|
|
|
CopyFile( rootOrigin, rootBackup, "Guilds/Guilds.bin" );
|
|
CopyFile( rootOrigin, rootBackup, "Guilds/Guilds.idx" );
|
|
|
|
CopyFile( rootOrigin, rootBackup, "Regions/Regions.bin" );
|
|
CopyFile( rootOrigin, rootBackup, "Regions/Regions.idx" );
|
|
|
|
Console.WriteLine( "done" );
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine( "failed" );
|
|
}
|
|
}
|
|
|
|
private static void GenerateCrashReport( CrashedEventArgs e )
|
|
{
|
|
Console.Write( "Crash: Generating report..." );
|
|
|
|
try
|
|
{
|
|
string timeStamp = GetTimeStamp();
|
|
string fileName = String.Format( "Crash {0}.log", timeStamp );
|
|
|
|
string root = GetRoot();
|
|
string filePath = Combine( root, fileName );
|
|
|
|
using ( StreamWriter op = new StreamWriter( filePath ) )
|
|
{
|
|
Version ver = Core.Assembly.GetName().Version;
|
|
|
|
op.WriteLine( "Server Crash Report" );
|
|
op.WriteLine( "===================" );
|
|
op.WriteLine();
|
|
op.WriteLine( "RunUO Version {0}.{1}, Build {2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision );
|
|
op.WriteLine( "Operating System: {0}", Environment.OSVersion );
|
|
op.WriteLine( ".NET Framework: {0}", Environment.Version );
|
|
op.WriteLine( "Time: {0}", DateTime.Now );
|
|
|
|
try { op.WriteLine( "Mobiles: {0}", World.Mobiles.Count ); }
|
|
catch {}
|
|
|
|
try { op.WriteLine( "Items: {0}", World.Items.Count ); }
|
|
catch {}
|
|
|
|
op.WriteLine( "Exception:" );
|
|
op.WriteLine( e.Exception );
|
|
op.WriteLine();
|
|
|
|
op.WriteLine( "Clients:" );
|
|
|
|
try
|
|
{
|
|
List<NetState> states = NetState.Instances;
|
|
|
|
op.WriteLine( "- Count: {0}", states.Count );
|
|
|
|
for ( int i = 0; i < states.Count; ++i )
|
|
{
|
|
NetState state = states[i];
|
|
|
|
op.Write( "+ {0}:", state );
|
|
|
|
Account a = state.Account as Account;
|
|
|
|
if ( a != null )
|
|
op.Write( " (account = {0})", a.Username );
|
|
|
|
Mobile m = state.Mobile;
|
|
|
|
if ( m != null )
|
|
op.Write( " (mobile = 0x{0:X} '{1}')", m.Serial.Value, m.Name );
|
|
|
|
op.WriteLine();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
op.WriteLine( "- Failed" );
|
|
}
|
|
}
|
|
|
|
Console.WriteLine( "done" );
|
|
|
|
if ( Email.CrashAddresses != null )
|
|
SendEmail( filePath );
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine( "failed" );
|
|
}
|
|
}
|
|
|
|
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
|
|
);
|
|
}
|
|
}
|
|
} |