using System; using System.IO; using System.Text; using System.Reflection; using System.Collections; using Server; using Server.Items; using Server.Engines.BulkOrders; using Server.Commands.Generic; using System.Collections.Generic; namespace Server.Commands { public class Docs { public static void Initialize() { CommandSystem.Register( "DocGen", AccessLevel.Administrator, new CommandEventHandler( DocGen_OnCommand ) ); } [Usage( "DocGen" )] [Description( "Generates RunUO documentation." )] private static void DocGen_OnCommand( CommandEventArgs e ) { World.Broadcast( 0x35, true, "Documentation is being generated, please wait." ); Network.NetState.FlushAll(); Network.NetState.Pause(); DateTime startTime = DateTime.Now; Document(); DateTime endTime = DateTime.Now; Network.NetState.Resume(); World.Broadcast( 0x35, true, "Documentation has been completed. The entire process took {0:F1} seconds.", (endTime - startTime).TotalSeconds ); } private class MemberComparer : IComparer { public int Compare( object x, object y ) { if( x == y ) return 0; ConstructorInfo aCtor = x as ConstructorInfo; ConstructorInfo bCtor = y as ConstructorInfo; PropertyInfo aProp = x as PropertyInfo; PropertyInfo bProp = y as PropertyInfo; MethodInfo aMethod = x as MethodInfo; MethodInfo bMethod = y as MethodInfo; bool aStatic = GetStaticFor( aCtor, aProp, aMethod ); bool bStatic = GetStaticFor( bCtor, bProp, bMethod ); if( aStatic && !bStatic ) return -1; else if( !aStatic && bStatic ) return 1; int v = 0; if( aCtor != null ) { if( bCtor == null ) v = -1; } else if( bCtor != null ) { if( aCtor == null ) v = 1; } else if( aProp != null ) { if( bProp == null ) v = -1; } else if( bProp != null ) { if( aProp == null ) v = 1; } if( v == 0 ) { v = GetNameFrom( aCtor, aProp, aMethod ).CompareTo( GetNameFrom( bCtor, bProp, bMethod ) ); } if( v == 0 && aCtor != null && bCtor != null ) { v = aCtor.GetParameters().Length.CompareTo( bCtor.GetParameters().Length ); } else if( v == 0 && aMethod != null && bMethod != null ) { v = aMethod.GetParameters().Length.CompareTo( bMethod.GetParameters().Length ); } return v; } private bool GetStaticFor( ConstructorInfo ctor, PropertyInfo prop, MethodInfo method ) { if( ctor != null ) return ctor.IsStatic; else if( method != null ) return method.IsStatic; if( prop != null ) { MethodInfo getMethod = prop.GetGetMethod(); MethodInfo setMethod = prop.GetGetMethod(); return (getMethod != null && getMethod.IsStatic) || (setMethod != null && setMethod.IsStatic); } return false; } private string GetNameFrom( ConstructorInfo ctor, PropertyInfo prop, MethodInfo method ) { if( ctor != null ) return ctor.DeclaringType.Name; else if( prop != null ) return prop.Name; else if( method != null ) return method.Name; else return ""; } } private class TypeComparer : IComparer { public int Compare( TypeInfo x, TypeInfo y ) { if( x == null && y == null ) return 0; else if( x == null ) return -1; else if( y == null ) return 1; return x.m_TypeName.CompareTo( y.m_TypeName ); } } private class TypeInfo { public Type m_Type, m_BaseType, m_Declaring; public string m_FileName, m_TypeName; public List m_Derived, m_Nested; public Type[] m_Interfaces; public StreamWriter m_Writer; public TypeInfo( Type type ) { m_Type = type; m_BaseType = type.BaseType; m_Declaring = type.DeclaringType; m_Interfaces = type.GetInterfaces(); m_TypeName = GetGenericTypeName( m_Type ); m_FileName = Docs.GetFileName( "docs/types/", GetGenericTypeName( m_Type, "-", "-" ), ".html" ); m_Writer = Docs.GetWriter( "docs/types/", m_FileName ); } } #region FileSystem private static readonly char[] ReplaceChars = "<>".ToCharArray(); public static string GetFileName( string root, string name, string ext ) { if( name.IndexOfAny( ReplaceChars ) >= 0 ) { StringBuilder sb = new StringBuilder( name ); for( int i = 0; i < ReplaceChars.Length; ++i ) { sb.Replace( ReplaceChars[i], '-' ); } name = sb.ToString(); } int index = 0; string file = String.Concat( name, ext ); while( File.Exists( Path.Combine( root, file ) ) ) { file = String.Concat( name, ++index, ext ); } return file; } private static string m_RootDirectory = Path.GetDirectoryName( Environment.GetCommandLineArgs()[0] ); private static void EnsureDirectory( string path ) { path = Path.Combine( m_RootDirectory, path ); if( !Directory.Exists( path ) ) Directory.CreateDirectory( path ); } private static void DeleteDirectory( string path ) { path = Path.Combine( m_RootDirectory, path ); if( Directory.Exists( path ) ) Directory.Delete( path, true ); } private static StreamWriter GetWriter( string root, string name ) { return new StreamWriter( Path.Combine( Path.Combine( m_RootDirectory, root ), name ) ); } private static StreamWriter GetWriter( string path ) { return new StreamWriter( Path.Combine( m_RootDirectory, path ) ); } #endregion #region GetPair private static string[,] m_Aliases = new string[,] { { "System.Object", "object" }, { "System.String", "string" }, { "System.Boolean", "bool" }, { "System.Byte", "byte" }, { "System.SByte", "sbyte" }, { "System.Int16", "short" }, { "System.UInt16", "ushort" }, { "System.Int32", "int" }, { "System.UInt32", "uint" }, { "System.Int64", "long" }, { "System.UInt64", "ulong" }, { "System.Single", "float" }, { "System.Double", "double" }, { "System.Decimal", "decimal" }, { "System.Char", "char" }, { "System.Void", "void" } }; private static int m_AliasLength = m_Aliases.GetLength( 0 ); public static string GetPair( Type varType, string name, bool ignoreRef ) { string prepend = ""; StringBuilder append = new StringBuilder(); Type realType = varType; if( varType.IsByRef ) { if( !ignoreRef ) prepend = RefString; realType = varType.GetElementType(); } if( realType.IsPointer ) { if( realType.IsArray ) { append.Append( '*' ); do { append.Append( '[' ); for( int i = 1; i < realType.GetArrayRank(); ++i ) append.Append( ',' ); append.Append( ']' ); realType = realType.GetElementType(); } while( realType.IsArray ); append.Append( ' ' ); } else { realType = realType.GetElementType(); append.Append( " *" ); } } else if( realType.IsArray ) { do { append.Append( '[' ); for( int i = 1; i < realType.GetArrayRank(); ++i ) append.Append( ',' ); append.Append( ']' ); realType = realType.GetElementType(); } while( realType.IsArray ); append.Append( ' ' ); } else { append.Append( ' ' ); } string fullName = realType.FullName; string aliased = null;// = realType.Name; TypeInfo info = null; m_Types.TryGetValue( realType, out info ); if( info != null ) { aliased = String.Format( "{1}", info.m_FileName, info.m_TypeName ); } else { for( int i = 0; i < m_AliasLength; ++i ) { if( m_Aliases[i, 0] == fullName ) { aliased = m_Aliases[i, 1]; break; } } if( aliased == null ) aliased = realType.Name; } return String.Concat( prepend, aliased, append, name ); } #endregion private static Dictionary m_Types; private static Dictionary> m_Namespaces; #region Root documentation private static void Document() { DeleteDirectory( "docs/" ); EnsureDirectory( "docs/" ); EnsureDirectory( "docs/namespaces/" ); EnsureDirectory( "docs/types/" ); EnsureDirectory( "docs/bods/" ); GenerateStyles(); GenerateIndex(); DocumentCommands(); DocumentKeywords(); DocumentBodies(); DocumentBulkOrders(); m_Types = new Dictionary(); m_Namespaces = new Dictionary>(); List assemblies = new List(); assemblies.Add( Core.Assembly ); foreach( Assembly asm in ScriptCompiler.Assemblies ) assemblies.Add( asm ); Assembly[] asms = assemblies.ToArray(); for( int i = 0; i < asms.Length; ++i ) LoadTypes( asms[i], asms ); DocumentLoadedTypes(); DocumentConstructableObjects(); } private static void AddIndexLink( StreamWriter html, string filePath, string label, string desc ) { html.WriteLine( "

{2}

", filePath, desc, label ); } private static void GenerateStyles() { using( StreamWriter css = GetWriter( "docs/", "styles.css" ) ) { css.WriteLine( "body { background-color: #FFFFFF; font-family: verdana, arial; font-size: 11px; }" ); css.WriteLine( "a { color: #28435E; }" ); css.WriteLine( "a:hover { color: #4878A9; }" ); css.WriteLine( "td.header { background-color: #9696AA; font-weight: bold; font-size: 12px; }" ); css.WriteLine( "td.lentry { background-color: #D7D7EB; width: 10%; }" ); css.WriteLine( "td.rentry { background-color: #FFFFFF; width: 90%; }" ); css.WriteLine( "td.entry { background-color: #FFFFFF; }" ); css.WriteLine( "td { font-size: 11px; }" ); css.WriteLine( ".tbl-border { background-color: #46465A; }" ); css.WriteLine( "td.ir {{ background-color: #{0:X6}; }}", Iron ); css.WriteLine( "td.du {{ background-color: #{0:X6}; }}", DullCopper ); css.WriteLine( "td.sh {{ background-color: #{0:X6}; }}", ShadowIron ); css.WriteLine( "td.co {{ background-color: #{0:X6}; }}", Copper ); css.WriteLine( "td.br {{ background-color: #{0:X6}; }}", Bronze ); css.WriteLine( "td.go {{ background-color: #{0:X6}; }}", Gold ); css.WriteLine( "td.ag {{ background-color: #{0:X6}; }}", Agapite ); css.WriteLine( "td.ve {{ background-color: #{0:X6}; }}", Verite ); css.WriteLine( "td.va {{ background-color: #{0:X6}; }}", Valorite ); css.WriteLine( "td.cl {{ background-color: #{0:X6}; }}", Cloth ); css.WriteLine( "td.pl {{ background-color: #{0:X6}; }}", Plain ); css.WriteLine( "td.sp {{ background-color: #{0:X6}; }}", Core.AOS ? SpinedAOS : SpinedLBR ); css.WriteLine( "td.ho {{ background-color: #{0:X6}; }}", Core.AOS ? HornedAOS : HornedLBR ); css.WriteLine( "td.ba {{ background-color: #{0:X6}; }}", Core.AOS ? BarbedAOS : BarbedLBR ); } } private static void GenerateIndex() { using( StreamWriter html = GetWriter( "docs/", "index.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Index" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); AddIndexLink( html, "commands.html", "Commands", "Every available command. This contains command name, usage, aliases, and description." ); AddIndexLink( html, "objects.html", "Constructable Objects", "Every constructable item or npc. This contains object name and usage. Hover mouse over parameters to see type description." ); AddIndexLink( html, "keywords.html", "Speech Keywords", "Lists speech keyword numbers and associated match patterns. These are used in some scripts for multi-language matching of client speech." ); AddIndexLink( html, "bodies.html", "Body List", "Every usable body number and name. Table is generated from a UO:3D client datafile. If you do not have UO:3D installed, this may be blank." ); AddIndexLink( html, "overview.html", "Class Overview", "Scripting reference. Contains every class type and contained methods in the core and scripts." ); AddIndexLink( html, "bods/bod_smith_rewards.html", "Bulk Order Rewards: Smithing", "Reference table for large and small smithing bulk order deed rewards." ); AddIndexLink( html, "bods/bod_tailor_rewards.html", "Bulk Order Rewards: Tailoring", "Reference table for large and small tailoring bulk order deed rewards." ); html.WriteLine( " " ); html.WriteLine( "" ); } } #endregion #region BODs private const int Iron = 0xCCCCDD; private const int DullCopper = 0xAAAAAA; private const int ShadowIron = 0x777799; private const int Copper = 0xDDCC99; private const int Bronze = 0xAA8866; private const int Gold = 0xDDCC55; private const int Agapite = 0xDDAAAA; private const int Verite = 0x99CC77; private const int Valorite = 0x88AABB; private const int Cloth = 0xDDDDDD; private const int Plain = 0xCCAA88; private const int SpinedAOS = 0x99BBBB; private const int HornedAOS = 0xCC8888; private const int BarbedAOS = 0xAABBAA; private const int SpinedLBR = 0xAA8833; private const int HornedLBR = 0xBBBBAA; private const int BarbedLBR = 0xCCAA88; private static void DocumentBulkOrders() { using( StreamWriter html = GetWriter( "docs/bods/", "bod_smith_rewards.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Bulk Orders - Smith Rewards" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); SmallBOD sbod = new SmallSmithBOD(); sbod.Type = typeof( Katana ); sbod.Material = BulkMaterialType.None; sbod.AmountMax = 10; WriteSmithBODHeader( html, "(Small) Weapons" ); sbod.RequireExceptional = false; DocumentSmithBOD( html, sbod.ComputeRewards( true ), "10, 15, 20: Normal", sbod.Material ); sbod.RequireExceptional = true; DocumentSmithBOD( html, sbod.ComputeRewards( true ), "10, 15, 20: Exceptional", sbod.Material ); WriteSmithBODFooter( html ); html.WriteLine( "

" ); html.WriteLine( "

" ); sbod.Type = typeof( PlateArms ); WriteSmithBODHeader( html, "(Small) Armor: Normal" ); sbod.RequireExceptional = false; for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat ) { sbod.Material = mat; sbod.AmountMax = 10; DocumentSmithBOD( html, sbod.ComputeRewards( true ), "10, 15, 20", sbod.Material ); } WriteSmithBODFooter( html ); html.WriteLine( "

" ); WriteSmithBODHeader( html, "(Small) Armor: Exceptional" ); sbod.RequireExceptional = true; for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat ) { sbod.Material = mat; for( int amt = 15; amt <= 20; amt += 5 ) { sbod.AmountMax = amt; DocumentSmithBOD( html, sbod.ComputeRewards( true ), amt == 20 ? "20" : "10, 15", sbod.Material ); } } WriteSmithBODFooter( html ); html.WriteLine( "

" ); html.WriteLine( "

" ); sbod.Delete(); WriteSmithLBOD( html, "Ringmail", LargeBulkEntry.LargeRing ); WriteSmithLBOD( html, "Chainmail", LargeBulkEntry.LargeChain ); WriteSmithLBOD( html, "Platemail", LargeBulkEntry.LargePlate ); html.WriteLine( " " ); html.WriteLine( "" ); } using( StreamWriter html = GetWriter( "docs/bods/", "bod_tailor_rewards.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Bulk Orders - Tailor Rewards" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); SmallBOD sbod = new SmallTailorBOD(); WriteTailorBODHeader( html, "Small Bulk Order" ); html.WriteLine( " " ); html.WriteLine( " Regular: 10, 15" ); html.WriteLine( " " ); sbod.AmountMax = 10; sbod.RequireExceptional = false; sbod.Type = typeof( SkullCap ); sbod.Material = BulkMaterialType.None; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "10, 15", sbod.Material, sbod.Type ); sbod.Type = typeof( LeatherCap ); for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat ) { if( mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite ) continue; sbod.Material = mat; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "10, 15", sbod.Material, sbod.Type ); } html.WriteLine( " " ); html.WriteLine( " Regular: 20" ); html.WriteLine( " " ); sbod.AmountMax = 20; sbod.RequireExceptional = false; sbod.Type = typeof( SkullCap ); sbod.Material = BulkMaterialType.None; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "20", sbod.Material, sbod.Type ); sbod.Type = typeof( LeatherCap ); for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat ) { if( mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite ) continue; sbod.Material = mat; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "20", sbod.Material, sbod.Type ); } html.WriteLine( " " ); html.WriteLine( " Exceptional: 10, 15" ); html.WriteLine( " " ); sbod.AmountMax = 10; sbod.RequireExceptional = true; sbod.Type = typeof( SkullCap ); sbod.Material = BulkMaterialType.None; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "10, 15", sbod.Material, sbod.Type ); sbod.Type = typeof( LeatherCap ); for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat ) { if( mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite ) continue; sbod.Material = mat; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "10, 15", sbod.Material, sbod.Type ); } html.WriteLine( " " ); html.WriteLine( " Exceptional: 20" ); html.WriteLine( " " ); sbod.AmountMax = 20; sbod.RequireExceptional = true; sbod.Type = typeof( SkullCap ); sbod.Material = BulkMaterialType.None; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "20", sbod.Material, sbod.Type ); sbod.Type = typeof( LeatherCap ); for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat ) { if( mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite ) continue; sbod.Material = mat; DocumentTailorBOD( html, sbod.ComputeRewards( true ), "20", sbod.Material, sbod.Type ); } WriteTailorBODFooter( html ); html.WriteLine( "

" ); html.WriteLine( "

" ); sbod.Delete(); WriteTailorLBOD( html, "Large Bulk Order: 4-part", LargeBulkEntry.Gypsy, true, true ); WriteTailorLBOD( html, "Large Bulk Order: 5-part", LargeBulkEntry.TownCrier, true, true ); WriteTailorLBOD( html, "Large Bulk Order: 6-part", LargeBulkEntry.MaleLeatherSet, false, true ); html.WriteLine( " " ); html.WriteLine( "" ); } } #region Tailor Bods private static void WriteTailorLBOD( StreamWriter html, string name, SmallBulkEntry[] entries, bool expandCloth, bool expandPlain ) { WriteTailorBODHeader( html, name ); LargeBOD lbod = new LargeTailorBOD(); lbod.Entries = LargeBulkEntry.ConvertEntries( lbod, entries ); Type type = entries[0].Type; bool showCloth = !(type.IsSubclassOf( typeof( BaseArmor ) ) || type.IsSubclassOf( typeof( BaseShoes ) )); html.WriteLine( " " ); html.WriteLine( " Regular" ); html.WriteLine( " " ); lbod.RequireExceptional = false; lbod.AmountMax = 10; if( showCloth ) { lbod.Material = BulkMaterialType.None; if( expandCloth ) { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15", lbod.Material, type ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, type ); } else { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, type ); } } lbod.Material = BulkMaterialType.None; if( expandPlain ) { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, typeof( LeatherCap ) ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, typeof( LeatherCap ) ); } else { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, typeof( LeatherCap ) ); } for( BulkMaterialType mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat ) { lbod.Material = mat; lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15", lbod.Material, type ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, type ); } html.WriteLine( " " ); html.WriteLine( " Exceptional" ); html.WriteLine( " " ); lbod.RequireExceptional = true; lbod.AmountMax = 10; if( showCloth ) { lbod.Material = BulkMaterialType.None; if( expandCloth ) { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15", lbod.Material, type ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, type ); } else { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, type ); } } lbod.Material = BulkMaterialType.None; if( expandPlain ) { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, typeof( LeatherCap ) ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, typeof( LeatherCap ) ); } else { lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material, typeof( LeatherCap ) ); } for( BulkMaterialType mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat ) { lbod.Material = mat; lbod.AmountMax = 10; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "10, 15", lbod.Material, type ); lbod.AmountMax = 20; DocumentTailorBOD( html, lbod.ComputeRewards( true ), "20", lbod.Material, type ); } WriteTailorBODFooter( html ); html.WriteLine( "

" ); html.WriteLine( "

" ); } private static void WriteTailorBODHeader( StreamWriter html, string title ) { html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " ", title ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); } private static void WriteTailorBODFooter( StreamWriter html ) { html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "
{0}
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
Power Scrolls
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
Runic Kits
+5
+10
+15
+20
\"Runic
\"Runic
\"Runic
 
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
+5
+10
+15
+20
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
\"Runic
\"Runic
\"Runic
Power Scrolls
Runic Kits
" ); } private static void DocumentTailorBOD( StreamWriter html, List items, string amt, BulkMaterialType material, Type type ) { bool[] rewards = new bool[20]; for( int i = 0; i < items.Count; ++i ) { Item item = (Item)items[i]; if( item is Sandals ) rewards[5] = true; else if( item is SmallStretchedHideEastDeed || item is SmallStretchedHideSouthDeed ) rewards[10] = rewards[11] = true; else if( item is MediumStretchedHideEastDeed || item is MediumStretchedHideSouthDeed ) rewards[10] = rewards[11] = true; else if( item is LightFlowerTapestryEastDeed || item is LightFlowerTapestrySouthDeed ) rewards[12] = rewards[13] = true; else if( item is DarkFlowerTapestryEastDeed || item is DarkFlowerTapestrySouthDeed ) rewards[12] = rewards[13] = true; else if( item is BrownBearRugEastDeed || item is BrownBearRugSouthDeed ) rewards[14] = rewards[15] = true; else if( item is PolarBearRugEastDeed || item is PolarBearRugSouthDeed ) rewards[14] = rewards[15] = true; else if( item is ClothingBlessDeed ) rewards[16] = true; else if( item is PowerScroll ) { PowerScroll ps = (PowerScroll)item; if( ps.Value == 105.0 ) rewards[6] = true; else if( ps.Value == 110.0 ) rewards[7] = true; else if( ps.Value == 115.0 ) rewards[8] = true; else if( ps.Value == 120.0 ) rewards[9] = true; } else if( item is UncutCloth ) { if( item.Hue == 0x483 || item.Hue == 0x48C || item.Hue == 0x488 || item.Hue == 0x48A ) rewards[0] = true; else if( item.Hue == 0x495 || item.Hue == 0x48B || item.Hue == 0x486 || item.Hue == 0x485 ) rewards[1] = true; else if( item.Hue == 0x48D || item.Hue == 0x490 || item.Hue == 0x48E || item.Hue == 0x491 ) rewards[2] = true; else if( item.Hue == 0x48F || item.Hue == 0x494 || item.Hue == 0x484 || item.Hue == 0x497 ) rewards[3] = true; else rewards[4] = true; } else if( item is RunicSewingKit ) { RunicSewingKit rkit = (RunicSewingKit)item; rewards[16 + CraftResources.GetIndex( rkit.Resource )] = true; } item.Delete(); } string style = null; string name = null; switch( material ) { case BulkMaterialType.None: { if( type.IsSubclassOf( typeof( BaseArmor ) ) || type.IsSubclassOf( typeof( BaseShoes ) ) ) { style = "pl"; name = "Plain"; } else { style = "cl"; name = "Cloth"; } break; } case BulkMaterialType.Spined: style = "sp"; name = "Spined"; break; case BulkMaterialType.Horned: style = "ho"; name = "Horned"; break; case BulkMaterialType.Barbed: style = "ba"; name = "Barbed"; break; } html.WriteLine( " " ); html.WriteLine( "  - {0} {1}", name, amt ); int index = 0; while( index < 20 ) { if( rewards[index] ) { html.WriteLine( "
X
", style ); ++index; } else { int count = 0; while( index < 20 && !rewards[index] ) { ++count; ++index; if( index == 5 || index == 6 || index == 10 || index == 17 ) break; } html.WriteLine( "  ", count*25, count==1?"":String.Format( " colspan=\"{0}\"", count ) ); } } html.WriteLine( " " ); } #endregion #region Smith Bods private static void WriteSmithLBOD( StreamWriter html, string name, SmallBulkEntry[] entries ) { LargeBOD lbod = new LargeSmithBOD(); lbod.Entries = LargeBulkEntry.ConvertEntries( lbod, entries ); WriteSmithBODHeader( html, String.Format( "(Large) {0}: Normal", name ) ); lbod.RequireExceptional = false; for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat ) { lbod.Material = mat; lbod.AmountMax = 10; DocumentSmithBOD( html, lbod.ComputeRewards( true ), "10, 15, 20", lbod.Material ); } WriteSmithBODFooter( html ); html.WriteLine( "

" ); WriteSmithBODHeader( html, String.Format( "(Large) {0}: Exceptional", name ) ); lbod.RequireExceptional = true; for( BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat ) { lbod.Material = mat; for( int amt = 15; amt <= 20; amt += 5 ) { lbod.AmountMax = amt; DocumentSmithBOD( html, lbod.ComputeRewards( true ), amt == 20 ? "20" : "10, 15", lbod.Material ); } } WriteSmithBODFooter( html ); html.WriteLine( "

" ); html.WriteLine( "

" ); } private static void WriteSmithBODHeader( StreamWriter html, string title ) { html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " ", title ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); } private static void WriteSmithBODFooter( StreamWriter html ) { html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "
{0}
\"Sturdy
Gloves
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
Power Scrolls
Runic Hammers
Ancient Hammers
+1
+3
+5
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
 
\"Sturdy
+1
 
+3
 
+5
 
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
Gloves
Power Scrolls
Runic Hammers
Ancient Hammers
" ); } private static void DocumentSmithBOD( StreamWriter html, List items, string amt, BulkMaterialType material ) { bool[] rewards = new bool[24]; for( int i = 0; i < items.Count; ++i ) { Item item = (Item)items[i]; if( item is SturdyPickaxe || item is SturdyShovel ) rewards[0] = true; else if( item is LeatherGlovesOfMining ) rewards[1] = true; else if( item is StuddedGlovesOfMining ) rewards[2] = true; else if( item is RingmailGlovesOfMining ) rewards[3] = true; else if( item is GargoylesPickaxe ) rewards[4] = true; else if( item is ProspectorsTool ) rewards[5] = true; else if( item is PowderOfTemperament ) rewards[6] = true; else if( item is ColoredAnvil ) rewards[7] = true; else if( item is PowerScroll ) { PowerScroll ps = (PowerScroll)item; if( ps.Value == 105.0 ) rewards[8] = true; else if( ps.Value == 110.0 ) rewards[9] = true; else if( ps.Value == 115.0 ) rewards[10] = true; else if( ps.Value == 120.0 ) rewards[11] = true; } else if( item is RunicHammer ) { RunicHammer rh = (RunicHammer)item; rewards[11 + CraftResources.GetIndex( rh.Resource )] = true; } else if( item is AncientSmithyHammer ) { AncientSmithyHammer ash = (AncientSmithyHammer)item; if( ash.Bonus == 10 ) rewards[20] = true; else if( ash.Bonus == 15 ) rewards[21] = true; else if( ash.Bonus == 30 ) rewards[22] = true; else if( ash.Bonus == 60 ) rewards[23] = true; } item.Delete(); } string style = null; string name = null; switch( material ) { case BulkMaterialType.None: style = "ir"; name = "Iron"; break; case BulkMaterialType.DullCopper: style = "du"; name = "Dull Copper"; break; case BulkMaterialType.ShadowIron: style = "sh"; name = "Shadow Iron"; break; case BulkMaterialType.Copper: style = "co"; name = "Copper"; break; case BulkMaterialType.Bronze: style = "br"; name = "Bronze"; break; case BulkMaterialType.Gold: style = "go"; name = "Gold"; break; case BulkMaterialType.Agapite: style = "ag"; name = "Agapite"; break; case BulkMaterialType.Verite: style = "ve"; name = "Verite"; break; case BulkMaterialType.Valorite: style = "va"; name = "Valorite"; break; } html.WriteLine( " " ); html.WriteLine( " {0} {1}", name, amt ); int index = 0; while( index < 24 ) { if( rewards[index] ) { html.WriteLine( "
X
", style ); ++index; } else { int count = 0; while( index < 24 && !rewards[index] ) { ++count; ++index; if( index == 4 || index == 8 || index == 12 || index == 20 ) break; } html.WriteLine( "  ", count*25, count==1?"":String.Format( " colspan=\"{0}\"", count ) ); } } html.WriteLine( " " ); } #endregion #endregion #region Bodies public static List LoadBodies() { List list = new List(); string path = Core.FindDataFile( "models/models.txt" ); if( File.Exists( path ) ) { using( StreamReader ip = new StreamReader( path ) ) { string line; while( (line = ip.ReadLine()) != null ) { line = line.Trim(); if( line.Length == 0 || line.StartsWith( "#" ) ) continue; string[] split = line.Split( '\t' ); if( split.Length >= 9 ) { Body body = Utility.ToInt32( split[0] ); ModelBodyType type = (ModelBodyType)Utility.ToInt32( split[1] ); string name = split[8]; BodyEntry entry = new BodyEntry( body, type, name ); if( !list.Contains( entry ) ) list.Add( entry ); } } } } return list; } private static void DocumentBodies() { List list = LoadBodies(); using( StreamWriter html = GetWriter( "docs/", "bodies.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Body List" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "

Back to the index

" ); if( list.Count > 0 ) { html.WriteLine( "

Body List

" ); list.Sort( new BodyEntrySorter() ); ModelBodyType lastType = ModelBodyType.Invalid; for( int i = 0; i < list.Count; ++i ) { BodyEntry entry = list[i]; ModelBodyType type = entry.BodyType; if( type != lastType ) { if( lastType != ModelBodyType.Invalid ) html.WriteLine( "
" ); lastType = type; html.WriteLine( " ", type ); switch( type ) { case ModelBodyType.Monsters: html.WriteLine( " Monsters | Sea | Animals | Human | Equipment

" ); break; case ModelBodyType.Sea: html.WriteLine( " Monsters | Sea | Animals | Human | Equipment

" ); break; case ModelBodyType.Animals: html.WriteLine( " Monsters | Sea | Animals | Human | Equipment

" ); break; case ModelBodyType.Human: html.WriteLine( " Monsters | Sea | Animals | Human | Equipment

" ); break; case ModelBodyType.Equipment: html.WriteLine( " Monsters | Sea | Animals | Human | Equipment

" ); break; } html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " ", type ); } html.WriteLine( " ", entry.Body.BodyID, entry.Name ); } html.WriteLine( "
{0}
{0}{1}
" ); } else { html.WriteLine( " This feature requires a UO:3D installation." ); } html.WriteLine( " " ); html.WriteLine( "" ); } } #endregion #region Speech private static void DocumentKeywords() { List> tables = LoadSpeechFile(); using( StreamWriter html = GetWriter( "docs/", "keywords.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Speech Keywords" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "

Back to the index

" ); html.WriteLine( "

Speech Keywords

" ); for( int p = 0; p < 1 && p < tables.Count; ++p ) { Dictionary table = tables[p]; if( p > 0 ) html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " " ); List list = new List( table.Values ); list.Sort( new SpeechEntrySorter() ); for( int i = 0; i < list.Count; ++i ) { SpeechEntry entry = list[i]; html.Write( " " ); } html.WriteLine( "
NumberText
0x{0:X4}", entry.Index ); entry.Strings.Sort();//( new EnglishPrioStringSorter() ); for( int j = 0; j < entry.Strings.Count; ++j ) { if( j > 0 ) html.Write( "
" ); string v = entry.Strings[j]; for( int k = 0; k < v.Length; ++k ) { char c = v[k]; if( c == '<' ) html.Write( "<" ); else if( c == '>' ) html.Write( ">" ); else if( c == '&' ) html.Write( "&" ); else if( c == '"' ) html.Write( """ ); else if( c == '\'' ) html.Write( "'" ); else if( c >= 0x20 && c < 0x80 ) html.Write( c ); else html.Write( "&#{0};", (int)c ); } } html.WriteLine( "
" ); } html.WriteLine( " " ); html.WriteLine( "" ); } } private class SpeechEntry { private int m_Index; private List m_Strings; public int Index { get { return m_Index; } } public List Strings { get { return m_Strings; } } public SpeechEntry( int index ) { m_Index = index; m_Strings = new List(); } } private class SpeechEntrySorter : IComparer { public int Compare( SpeechEntry x, SpeechEntry y ) { return x.Index.CompareTo( y.Index ); } } private static List> LoadSpeechFile() { List> tables = new List>(); int lastIndex = -1; Dictionary table = null; string path = Core.FindDataFile( "speech.mul" ); if( File.Exists( path ) ) { using( FileStream ip = new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { BinaryReader bin = new BinaryReader( ip ); while( bin.PeekChar() >= 0 ) { int index = (bin.ReadByte() << 8) | bin.ReadByte(); int length = (bin.ReadByte() << 8) | bin.ReadByte(); string text = Encoding.UTF8.GetString( bin.ReadBytes( length ) ).Trim(); if( text.Length == 0 ) continue; if( table == null || lastIndex > index ) { if( index == 0 && text == "*withdraw*" ) tables.Insert( 0, table = new Dictionary() ); else tables.Add( table = new Dictionary() ); } lastIndex = index; SpeechEntry entry = null; table.TryGetValue( index, out entry ); if( entry == null ) table[index] = entry = new SpeechEntry( index ); entry.Strings.Add( text ); } } } return tables; } #endregion #region Commands private class DocCommandEntry { private AccessLevel m_AccessLevel; private string m_Name; private string[] m_Aliases; private string m_Usage; private string m_Description; public AccessLevel AccessLevel { get { return m_AccessLevel; } } public string Name { get { return m_Name; } } public string[] Aliases { get { return m_Aliases; } } public string Usage { get { return m_Usage; } } public string Description { get { return m_Description; } } public DocCommandEntry( AccessLevel accessLevel, string name, string[] aliases, string usage, string description ) { m_AccessLevel = accessLevel; m_Name = name; m_Aliases = aliases; m_Usage = usage; m_Description = description; } } private class CommandEntrySorter : IComparer { public int Compare( DocCommandEntry a, DocCommandEntry b ) { int v = b.AccessLevel.CompareTo( a.AccessLevel ); if( v == 0 ) v = a.Name.CompareTo( b.Name ); return v; } } private static void DocumentCommands() { using( StreamWriter html = GetWriter( "docs/", "commands.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Commands" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "

Back to the index

" ); html.WriteLine( "

Commands

" ); List commands = new List( CommandSystem.Entries.Values ); List list = new List(); commands.Sort(); commands.Reverse(); Clean( commands ); for( int i = 0; i < commands.Count; ++i ) { CommandEntry e = commands[i]; MethodInfo mi = e.Handler.Method; object[] attrs = mi.GetCustomAttributes( typeof( UsageAttribute ), false ); if( attrs.Length == 0 ) continue; UsageAttribute usage = attrs[0] as UsageAttribute; attrs = mi.GetCustomAttributes( typeof( DescriptionAttribute ), false ); if( attrs.Length == 0 ) continue; DescriptionAttribute desc = attrs[0] as DescriptionAttribute; if( usage == null || desc == null ) continue; attrs = mi.GetCustomAttributes( typeof( AliasesAttribute ), false ); AliasesAttribute aliases = (attrs.Length == 0 ? null : attrs[0] as AliasesAttribute); string descString = desc.Description.Replace( "<", "<" ).Replace( ">", ">" ); if( aliases == null ) list.Add( new DocCommandEntry( e.AccessLevel, e.Command, null, usage.Usage, descString ) ); else list.Add( new DocCommandEntry( e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString ) ); } for( int i = 0; i < TargetCommands.AllCommands.Count; ++i ) { BaseCommand command = TargetCommands.AllCommands[i]; string usage = command.Usage; string desc = command.Description; if( usage == null || desc == null ) continue; string[] cmds = command.Commands; string cmd = cmds[0]; string[] aliases = new string[cmds.Length - 1]; for( int j = 0; j < aliases.Length; ++j ) aliases[j] = cmds[j + 1]; desc = desc.Replace( "<", "<" ).Replace( ">", ">" ); if( command.Supports != CommandSupport.Single ) { StringBuilder sb = new StringBuilder( 50 + desc.Length ); sb.Append( "Modifiers: " ); if( (command.Supports & CommandSupport.Global) != 0 ) sb.Append( "Global, " ); if( (command.Supports & CommandSupport.Online) != 0 ) sb.Append( "Online, " ); if( (command.Supports & CommandSupport.Region) != 0 ) sb.Append( "Region, " ); if( (command.Supports & CommandSupport.Contained) != 0 ) sb.Append( "Contained, " ); if( (command.Supports & CommandSupport.Multi) != 0 ) sb.Append( "Multi, " ); if( (command.Supports & CommandSupport.Area) != 0 ) sb.Append( "Area, " ); if( (command.Supports & CommandSupport.Self) != 0 ) sb.Append( "Self, " ); sb.Remove( sb.Length - 2, 2 ); sb.Append( "
" ); sb.Append( desc ); desc = sb.ToString(); } list.Add( new DocCommandEntry( command.AccessLevel, cmd, aliases, usage, desc ) ); } List commandImpls = BaseCommandImplementor.Implementors; for( int i = 0; i < commandImpls.Count; ++i ) { BaseCommandImplementor command = commandImpls[i]; string usage = command.Usage; string desc = command.Description; if( usage == null || desc == null ) continue; string[] cmds = command.Accessors; string cmd = cmds[0]; string[] aliases = new string[cmds.Length - 1]; for( int j = 0; j < aliases.Length; ++j ) aliases[j] = cmds[j + 1]; desc = desc.Replace( "<", "<" ).Replace( ">", ">" ); list.Add( new DocCommandEntry( command.AccessLevel, cmd, aliases, usage, desc ) ); } list.Sort( new CommandEntrySorter() ); AccessLevel last = AccessLevel.Player; foreach( DocCommandEntry e in list ) { if( e.AccessLevel != last ) { if( last != AccessLevel.Player ) html.WriteLine( "

" ); last = e.AccessLevel; html.WriteLine( " ", last ); switch( last ) { case AccessLevel.Administrator: html.WriteLine( " Administrator | Game Master | Counselor | Player

" ); break; case AccessLevel.GameMaster: html.WriteLine( " Administrator | Game Master | Counselor | Player

" ); break; case AccessLevel.Seer: html.WriteLine( " Administrator | Game Master | Counselor | Player

" ); break; case AccessLevel.Counselor: html.WriteLine( " Administrator | Game Master | Counselor | Player

" ); break; case AccessLevel.Player: html.WriteLine( " Administrator | Game Master | Counselor | Player

" ); break; } html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " ", last == AccessLevel.GameMaster ? "Game Master" : last.ToString() ); } DocumentCommand( html, e ); } html.WriteLine( "
{0}
" ); html.WriteLine( " " ); html.WriteLine( "" ); } } private static void Clean( List list ) { for( int i = 0; i < list.Count; ++i ) { CommandEntry e = list[i]; for( int j = i + 1; j < list.Count; ++j ) { CommandEntry c = list[j]; if( e.Handler.Method == c.Handler.Method ) { list.RemoveAt( j ); --j; } } } } private static void DocumentCommand( StreamWriter html, DocCommandEntry e ) { string usage = e.Usage; string desc = e.Description; string[] aliases = e.Aliases; html.Write( " {0}", e.Name ); if( aliases == null || aliases.Length == 0 ) { html.Write( "Usage: {0}
{1}", usage.Replace( "<", "<" ).Replace( ">", ">" ), desc ); } else { html.Write( "Usage: {0}
Alias{1}: ", usage.Replace( "<", "<" ).Replace( ">", ">" ), aliases.Length == 1 ? "" : "es" ); for( int i = 0; i < aliases.Length; ++i ) { if( i != 0 ) html.Write( ", " ); html.Write( aliases[i] ); } html.Write( "
{0}", desc ); } html.WriteLine( "" ); } #endregion private static void LoadTypes( Assembly a, Assembly[] asms ) { Type[] types = a.GetTypes(); for( int i = 0; i < types.Length; ++i ) { Type type = types[i]; string nspace = type.Namespace; if( nspace == null || type.IsSpecialName ) continue; TypeInfo info = new TypeInfo( type ); m_Types[type] = info; List nspaces = null; m_Namespaces.TryGetValue( nspace, out nspaces ); if( nspaces == null ) m_Namespaces[nspace] = nspaces = new List(); nspaces.Add( info ); Type baseType = info.m_BaseType; if( baseType != null && InAssemblies( baseType, asms ) ) { TypeInfo baseInfo = null; m_Types.TryGetValue( baseType, out baseInfo ); if( baseInfo == null ) m_Types[baseType] = baseInfo = new TypeInfo( baseType ); if( baseInfo.m_Derived == null ) baseInfo.m_Derived = new List(); baseInfo.m_Derived.Add( info ); } Type decType = info.m_Declaring; if( decType != null ) { TypeInfo decInfo = null; m_Types.TryGetValue( decType, out decInfo ); if( decInfo == null ) m_Types[decType] = decInfo = new TypeInfo( decType ); if( decInfo.m_Nested == null ) decInfo.m_Nested = new List(); decInfo.m_Nested.Add( info ); } for( int j = 0; j < info.m_Interfaces.Length; ++j ) { Type iface = info.m_Interfaces[j]; if( !InAssemblies( iface, asms ) ) continue; TypeInfo ifaceInfo = null; m_Types.TryGetValue( iface, out ifaceInfo ); if( ifaceInfo == null ) m_Types[iface] = ifaceInfo = new TypeInfo( iface ); if( ifaceInfo.m_Derived == null ) ifaceInfo.m_Derived = new List(); ifaceInfo.m_Derived.Add( info ); } } } private static bool InAssemblies( Type t, Assembly[] asms ) { Assembly a = t.Assembly; for( int i = 0; i < asms.Length; ++i ) if( a == asms[i] ) return true; return false; } #region Constructable Objects private static Type typeofItem = typeof( Item ), typeofMobile = typeof( Mobile ), typeofMap = typeof( Map ); private static Type typeofCustomEnum = typeof( CustomEnumAttribute ); private static bool IsConstructable( Type t, out bool isItem ) { if( isItem = typeofItem.IsAssignableFrom( t ) ) return true; return typeofMobile.IsAssignableFrom( t ); } private static bool IsConstructable( ConstructorInfo ctor ) { return ctor.IsDefined( typeof( ConstructableAttribute ), false ); } private static void DocumentConstructableObjects() { List types = new List( m_Types.Values ); types.Sort( new TypeComparer() ); ArrayList items = new ArrayList(), mobiles = new ArrayList(); for( int i = 0; i < types.Count; ++i ) { Type t = types[i].m_Type; bool isItem; if( t.IsAbstract || !IsConstructable( t, out isItem ) ) continue; ConstructorInfo[] ctors = t.GetConstructors(); bool anyConstructable = false; for( int j = 0; !anyConstructable && j < ctors.Length; ++j ) anyConstructable = IsConstructable( ctors[j] ); if( anyConstructable ) { (isItem ? items : mobiles).Add( t ); (isItem ? items : mobiles).Add( ctors ); } } using( StreamWriter html = GetWriter( "docs/", "objects.html" ) ) { html.WriteLine( "" ); html.WriteLine( " " ); html.WriteLine( " RunUO Documentation - Constructable Objects" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "

Back to the index

" ); html.WriteLine( "

Constructable Items and Mobiles

" ); html.WriteLine( " " ); html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " " ); for( int i = 0; i < items.Count; i += 2 ) DocumentConstructableObject( html, (Type)items[i], (ConstructorInfo[])items[i + 1] ); html.WriteLine( "
Item NameUsage


" ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( "
" ); html.WriteLine( " " ); html.WriteLine( " " ); for( int i = 0; i < mobiles.Count; i += 2 ) DocumentConstructableObject( html, (Type)mobiles[i], (ConstructorInfo[])mobiles[i + 1] ); html.WriteLine( "
Mobile NameUsage
" ); html.WriteLine( " " ); html.WriteLine( "" ); } } private static void DocumentConstructableObject( StreamWriter html, Type t, ConstructorInfo[] ctors ) { html.Write( " {0}", t.Name ); bool first = true; for( int i = 0; i < ctors.Length; ++i ) { ConstructorInfo ctor = ctors[i]; if( !IsConstructable( ctor ) ) continue; if( !first ) html.Write( "
" ); first = false; html.Write( "{0}Add {1}", CommandSystem.Prefix, t.Name ); ParameterInfo[] parms = ctor.GetParameters(); for( int j = 0; j < parms.Length; ++j ) { html.Write( "
{1}", GetTooltipFor( parms[j] ), parms[j].Name ); } } html.WriteLine( "" ); } #endregion #region Tooltips private const string HtmlNewLine = " "; private static object[,] m_Tooltips = new object[,] { { typeof( Byte ), "Numeric value in the range from 0 to 255, inclusive." }, { typeof( SByte ), "Numeric value in the range from negative 128 to positive 127, inclusive." }, { typeof( UInt16 ), "Numeric value in the range from 0 to 65,535, inclusive." }, { typeof( Int16 ), "Numeric value in the range from negative 32,768 to positive 32,767, inclusive." }, { typeof( UInt32 ), "Numeric value in the range from 0 to 4,294,967,295, inclusive." }, { typeof( Int32 ), "Numeric value in the range from negative 2,147,483,648 to positive 2,147,483,647, inclusive." }, { typeof( UInt64 ), "Numeric value in the range from 0 through about 10^20." }, { typeof( Int64 ), "Numeric value in the approximate range from negative 10^19 through 10^19." }, { typeof( String ), "Text value. To specify a value containing spaces, encapsulate the value in quote characters:{0}{0}"Spaced text example"" }, { typeof( Boolean ), "Boolean value which can be either True or False." }, { typeof( Map ), "Map or facet name. Possible values include:{0}{0}- Felucca{0}- Trammel{0}- Ilshenar{0}- Malas" }, { typeof( Poison ), "Poison name or level. Possible values include:{0}{0}- Lesser{0}- Regular{0}- Greater{0}- Deadly{0}- Lethal" }, { typeof( Point3D ), "Three-dimensional coordinate value. Format as follows:{0}{0}"(, , )"" } }; private static string GetTooltipFor( ParameterInfo param ) { Type paramType = param.ParameterType; for( int i = 0; i < m_Tooltips.GetLength( 0 ); ++i ) { Type checkType = (Type)m_Tooltips[i, 0]; if( paramType == checkType ) return String.Format( (string)m_Tooltips[i, 1], HtmlNewLine ); } if( paramType.IsEnum ) { StringBuilder sb = new StringBuilder(); sb.AppendFormat( "Enumeration value or name. Possible named values include:{0}", HtmlNewLine ); string[] names = Enum.GetNames( paramType ); for( int i = 0; i < names.Length; ++i ) sb.AppendFormat( "{0}- {1}", HtmlNewLine, names[i] ); return sb.ToString(); } else if( paramType.IsDefined( typeofCustomEnum, false ) ) { object[] attributes = paramType.GetCustomAttributes( typeofCustomEnum, false ); if( attributes != null && attributes.Length > 0 ) { CustomEnumAttribute attr = attributes[0] as CustomEnumAttribute; if( attr != null ) { StringBuilder sb = new StringBuilder(); sb.AppendFormat( "Enumeration value or name. Possible named values include:{0}", HtmlNewLine ); string[] names = attr.Names; for( int i = 0; i < names.Length; ++i ) sb.AppendFormat( "{0}- {1}", HtmlNewLine, names[i] ); return sb.ToString(); } } } else if( paramType == typeofMap ) { StringBuilder sb = new StringBuilder(); sb.AppendFormat( "Enumeration value or name. Possible named values include:{0}", HtmlNewLine ); string[] names = Map.GetMapNames(); for( int i = 0; i < names.Length; ++i ) sb.AppendFormat( "{0}- {1}", HtmlNewLine, names[i] ); return sb.ToString(); } return ""; } #endregion #region Const Strings private const string RefString = "ref "; private const string GetString = " get;"; private const string SetString = " set;"; private const string InString = "in "; private const string OutString = "out "; private const string VirtString = "virtual "; private const string CtorString ="(ctor) "; private const string StaticString = "(static) "; #endregion private static void DocumentLoadedTypes() { using( StreamWriter indexHtml = GetWriter( "docs/", "overview.html" ) ) { indexHtml.WriteLine( "" ); indexHtml.WriteLine( " " ); indexHtml.WriteLine( " RunUO Documentation - Class Overview" ); indexHtml.WriteLine( " " ); indexHtml.WriteLine( " " ); indexHtml.WriteLine( "

Back to the index

" ); indexHtml.WriteLine( "

Namespaces

" ); SortedList> nspaces = new SortedList>( m_Namespaces ); foreach( KeyValuePair> kvp in nspaces ) { kvp.Value.Sort( new TypeComparer() ); SaveNamespace( kvp.Key, kvp.Value, indexHtml ); } indexHtml.WriteLine( " " ); indexHtml.WriteLine( "" ); } } private static void SaveNamespace( string name, List types, StreamWriter indexHtml ) { string fileName = GetFileName( "docs/namespaces/", name, ".html" ); indexHtml.WriteLine( " {1}
", fileName, name ); using( StreamWriter nsHtml = GetWriter( "docs/namespaces/", fileName ) ) { nsHtml.WriteLine( "" ); nsHtml.WriteLine( " " ); nsHtml.WriteLine( " RunUO Documentation - Class Overview - {0}", name ); nsHtml.WriteLine( " " ); nsHtml.WriteLine( " " ); nsHtml.WriteLine( "

Back to the namespace index

" ); nsHtml.WriteLine( "

{0}

", name ); for( int i = 0; i < types.Count; ++i ) SaveType( types[i], nsHtml, fileName, name ); nsHtml.WriteLine( " " ); nsHtml.WriteLine( "" ); } } private static void SaveType( TypeInfo info, StreamWriter nsHtml, string nsFileName, string nsName ) { if( info.m_Declaring == null ) nsHtml.WriteLine( " {1}
", info.m_FileName, info.m_TypeName ); using( StreamWriter typeHtml = info.m_Writer ) { typeHtml.WriteLine( "" ); typeHtml.WriteLine( " " ); typeHtml.WriteLine( " RunUO Documentation - Class Overview - {0}", info.m_TypeName ); typeHtml.WriteLine( " " ); typeHtml.WriteLine( " " ); typeHtml.WriteLine( "

Back to {1}

", nsFileName, nsName ); if( info.m_Type.IsEnum ) WriteEnum( info, typeHtml ); else WriteType( info, typeHtml ); typeHtml.WriteLine( " " ); typeHtml.WriteLine( "" ); } } private static void WriteEnum( TypeInfo info, StreamWriter typeHtml ) { Type type = info.m_Type; typeHtml.WriteLine( "

{0} (Enum)

", info.m_TypeName ); string[] names = Enum.GetNames( type ); bool flags = type.IsDefined( typeof( FlagsAttribute ), false ); string format; if( flags ) format = " {0:G} = 0x{1:X}{2}
"; else format = " {0:G} = {1:D}{2}
"; for( int i = 0; i < names.Length; ++i ) { object value = Enum.Parse( type, names[i] ); typeHtml.WriteLine( format, names[i], value, i < (names.Length - 1) ? "," : "" ); } } private static void WriteType( TypeInfo info, StreamWriter typeHtml ) { Type type = info.m_Type; typeHtml.Write( "

" ); Type decType = info.m_Declaring; if( decType != null ) { // We are a nested type typeHtml.Write( '(' ); TypeInfo decInfo = null; m_Types.TryGetValue( decType, out decInfo ); if( decInfo == null ) typeHtml.Write( decType.Name ); else typeHtml.Write( "{1}", decInfo.m_FileName, decInfo.m_TypeName ); typeHtml.Write( ") - " ); } typeHtml.Write( info.m_TypeName ); Type[] ifaces = info.m_Interfaces; Type baseType = info.m_BaseType; int extendCount = 0; if( baseType != null && baseType != typeof( object ) && baseType != typeof( ValueType ) && !baseType.IsPrimitive ) { typeHtml.Write( " : " ); TypeInfo baseInfo = null; m_Types.TryGetValue( baseType, out baseInfo ); if( baseInfo == null ) typeHtml.Write( baseType.Name ); else typeHtml.Write( "{1}", baseInfo.m_FileName, baseInfo.m_TypeName ); ++extendCount; } if( ifaces.Length > 0 ) { if( extendCount == 0 ) typeHtml.Write( " : " ); for( int i = 0; i < ifaces.Length; ++i ) { Type iface = ifaces[i]; TypeInfo ifaceInfo = null; m_Types.TryGetValue( iface, out ifaceInfo ); if( extendCount != 0 ) typeHtml.Write( ", " ); ++extendCount; if( ifaceInfo == null ) typeHtml.Write( iface.Name ); else typeHtml.Write( "{1}", ifaceInfo.m_FileName, ifaceInfo.m_TypeName ); } } typeHtml.WriteLine( "

" ); List derived = info.m_Derived; if( derived != null ) { typeHtml.Write( "

Derived Types: " ); derived.Sort( new TypeComparer() ); for( int i = 0; i < derived.Count; ++i ) { TypeInfo derivedInfo = derived[i]; if( i != 0 ) typeHtml.Write( ", " ); typeHtml.Write( "{1}", derivedInfo.m_FileName, derivedInfo.m_TypeName ); } typeHtml.WriteLine( "

" ); } List nested = info.m_Nested; if( nested != null ) { typeHtml.Write( "

Nested Types: " ); nested.Sort( new TypeComparer() ); for( int i = 0; i < nested.Count; ++i ) { TypeInfo nestedInfo = nested[i]; if( i != 0 ) typeHtml.Write( ", " ); typeHtml.Write( "{1}", nestedInfo.m_FileName, nestedInfo.m_TypeName ); } typeHtml.WriteLine( "

" ); } MemberInfo[] membs = type.GetMembers( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly ); Array.Sort( membs, new MemberComparer() ); for( int i = 0; i < membs.Length; ++i ) { MemberInfo mi = membs[i]; if( mi is PropertyInfo ) WriteProperty( (PropertyInfo)mi, typeHtml ); else if( mi is ConstructorInfo ) WriteCtor( info.m_TypeName, (ConstructorInfo)mi, typeHtml ); else if( mi is MethodInfo ) WriteMethod( (MethodInfo)mi, typeHtml ); } } private static void WriteProperty( PropertyInfo pi, StreamWriter html ) { html.Write( " " ); MethodInfo getMethod = pi.GetGetMethod(); MethodInfo setMethod = pi.GetSetMethod(); if( (getMethod != null && getMethod.IsStatic) || (setMethod != null && setMethod.IsStatic) ) html.Write( StaticString ); html.Write( GetPair( pi.PropertyType, pi.Name, false ) ); html.Write( '(' ); if( pi.CanRead ) html.Write( GetString ); if( pi.CanWrite ) html.Write( SetString ); html.WriteLine( " )
" ); } private static void WriteCtor( string name, ConstructorInfo ctor, StreamWriter html ) { if( ctor.IsStatic ) return; html.Write( " " ); html.Write( CtorString ); html.Write( name ); html.Write( '(' ); ParameterInfo[] parms = ctor.GetParameters(); if( parms.Length > 0 ) { html.Write( ' ' ); for( int i = 0; i < parms.Length; ++i ) { ParameterInfo pi = parms[i]; if( i != 0 ) html.Write( ", " ); if( pi.IsIn ) html.Write( InString ); else if( pi.IsOut ) html.Write( OutString ); html.Write( GetPair( pi.ParameterType, pi.Name, pi.IsOut ) ); } html.Write( ' ' ); } html.WriteLine( ")
" ); } private static void WriteMethod( MethodInfo mi, StreamWriter html ) { if( mi.IsSpecialName ) return; html.Write( " " ); if( mi.IsStatic ) html.Write( StaticString ); if( mi.IsVirtual ) html.Write( VirtString ); html.Write( GetPair( mi.ReturnType, mi.Name, false ) ); html.Write( '(' ); ParameterInfo[] parms = mi.GetParameters(); if( parms.Length > 0 ) { html.Write( ' ' ); for( int i = 0; i < parms.Length; ++i ) { ParameterInfo pi = parms[i]; if( i != 0 ) html.Write( ", " ); if( pi.IsIn ) html.Write( InString ); else if( pi.IsOut ) html.Write( OutString ); html.Write( GetPair( pi.ParameterType, pi.Name, pi.IsOut ) ); } html.Write( ' ' ); } html.WriteLine( ")
" ); } public static string GetGenericTypeName( Type type ) { return GetGenericTypeName( type, "<", ">" ); } public static string GetGenericTypeName( Type type, string leftGenericBracket, string rightGenericBracket ) { string name = type.Name; if( type.IsGenericType ) { int index = name.IndexOf( '`' ); if( index > 0 ) { StringBuilder sb = new StringBuilder( name.Substring( 0, index ) ); sb.Append( leftGenericBracket ); Type[] typeArguments = type.GetGenericArguments(); for( int i = 0; i < typeArguments.Length; i++ ) { if( i != 0 ) sb.Append( ',' ); sb.Append( typeArguments[i].Name ); } sb.Append( rightGenericBracket ); name = sb.ToString(); } } return name; } } #region BodyEntry & BodyType public enum ModelBodyType { Invalid=-1, Monsters, Sea, Animals, Human, Equipment } public class BodyEntry { private Body m_Body; private ModelBodyType m_BodyType; private string m_Name; public Body Body { get { return m_Body; } } public ModelBodyType BodyType { get { return m_BodyType; } } public string Name { get { return m_Name; } } public BodyEntry( Body body, ModelBodyType bodyType, string name ) { m_Body = body; m_BodyType = bodyType; m_Name = name; } public override bool Equals( object obj ) { BodyEntry e = (BodyEntry)obj; return (m_Body == e.m_Body && m_BodyType == e.m_BodyType && m_Name == e.m_Name); } public override int GetHashCode() { return m_Body.BodyID ^ (int)m_BodyType ^ m_Name.GetHashCode(); } } public class BodyEntrySorter : IComparer { public int Compare( BodyEntry a, BodyEntry b ) { int v = a.BodyType.CompareTo( b.BodyType ); if( v == 0 ) v = a.Body.BodyID.CompareTo( b.Body.BodyID ); if( v == 0 ) v = a.Name.CompareTo( b.Name ); return v; } } #endregion }