diff --git a/Server/ScriptCompiler.cs b/Server/ScriptCompiler.cs index b3d6a74c3..39efd291b 100644 --- a/Server/ScriptCompiler.cs +++ b/Server/ScriptCompiler.cs @@ -1,793 +1,793 @@ -/*************************************************************************** - * ScriptCompiler.cs - * ------------------- - * begin : May 1, 2002 - * copyright : (C) The RunUO Software Team - * email : info@runuo.com - * - * $Id$ - * - ***************************************************************************/ - -/*************************************************************************** - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - ***************************************************************************/ - -using System; -using System.CodeDom; -using System.CodeDom.Compiler; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Reflection; -using System.Security.Cryptography; -using Microsoft.CSharp; -using Microsoft.VisualBasic; - -namespace Server -{ - public class ScriptCompiler - { - private static Assembly[] m_Assemblies; - - public static Assembly[] Assemblies - { - get - { - return m_Assemblies; - } - set - { - m_Assemblies = value; - } - } - - private static List m_AdditionalReferences = new List(); - - public static string[] GetReferenceAssemblies() - { - List list = new List(); - - string path = Path.Combine( Core.BaseDirectory, "Data/Assemblies.cfg" ); - - if( File.Exists( path ) ) - { - using( StreamReader ip = new StreamReader( path ) ) - { - string line; - - while( (line = ip.ReadLine()) != null ) - { - if( line.Length > 0 && !line.StartsWith( "#" ) ) - list.Add( line ); - } - } - } - - list.Add( Core.ExePath ); - - list.AddRange( m_AdditionalReferences ); - - return list.ToArray(); - } - - public static string GetDefines() - { - StringBuilder sb = null; - -#if MONO - AppendDefine( ref sb, "/d:MONO" ); -#endif - - //These two defines are legacy, ie, depreciated. - if( Core.Is64Bit ) - AppendDefine( ref sb, "/d:x64" ); - - AppendDefine( ref sb, "/d:Framework_2_0" ); - - return (sb == null ? null : sb.ToString()); - } - - public static void AppendDefine( ref StringBuilder sb, string define ) - { - if( sb == null ) - sb = new StringBuilder(); - else - sb.Append( ' ' ); - - sb.Append( define ); - } - - private static byte[] GetHashCode( string compiledFile, string[] scriptFiles, bool debug ) - { - using( MemoryStream ms = new MemoryStream() ) - { - using( BinaryWriter bin = new BinaryWriter( ms ) ) - { - FileInfo fileInfo = new FileInfo( compiledFile ); - - bin.Write( fileInfo.LastWriteTimeUtc.Ticks ); - - foreach( string scriptFile in scriptFiles ) - { - fileInfo = new FileInfo( scriptFile ); - - bin.Write( fileInfo.LastWriteTimeUtc.Ticks ); - } - - bin.Write( debug ); - - ms.Position = 0; - - using( SHA1 sha1 = SHA1.Create() ) - { - return sha1.ComputeHash( ms ); - } - } - } - } - - public static bool CompileCSScripts( out Assembly assembly ) - { - return CompileCSScripts( false, true, out assembly ); - } - - public static bool CompileCSScripts( bool debug, out Assembly assembly ) - { - return CompileCSScripts( debug, true, out assembly ); - } - - public static bool CompileCSScripts( bool debug, bool cache, out Assembly assembly ) - { - Console.Write( "Scripts: Compiling C# scripts..." ); - string[] files = GetScripts( "*.cs" ); - - if( files.Length == 0 ) - { - Console.WriteLine( "no files found." ); - assembly = null; - return true; - } - - if( File.Exists( "Scripts/Output/Scripts.CS.dll" ) ) - { - if( cache && File.Exists( "Scripts/Output/Scripts.CS.hash" ) ) - { - try - { - byte[] hashCode = GetHashCode( "Scripts/Output/Scripts.CS.dll", files, debug ); - - using( FileStream fs = new FileStream( "Scripts/Output/Scripts.CS.hash", FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - using( BinaryReader bin = new BinaryReader( fs ) ) - { - byte[] bytes = bin.ReadBytes( hashCode.Length ); - - if( bytes.Length == hashCode.Length ) - { - bool valid = true; - - for( int i = 0; i < bytes.Length; ++i ) - { - if( bytes[i] != hashCode[i] ) - { - valid = false; - break; - } - } - - if( valid ) - { - assembly = Assembly.LoadFrom( "Scripts/Output/Scripts.CS.dll" ); - - if( !m_AdditionalReferences.Contains( assembly.Location ) ) - { - m_AdditionalReferences.Add( assembly.Location ); - } - - Console.WriteLine( "done (cached)" ); - - return true; - } - } - } - } - } - catch - { - } - } - } - - DeleteFiles( "Scripts.CS*.dll" ); - - using( CSharpCodeProvider provider = new CSharpCodeProvider() ) - { - string path = GetUnusedPath( "Scripts.CS" ); - - CompilerParameters parms = new CompilerParameters( GetReferenceAssemblies(), path, debug ); - - string defines = GetDefines(); - - if( defines != null ) - parms.CompilerOptions = defines; - - if( Core.HaltOnWarning ) - parms.WarningLevel = 4; - -#if !MONO - CompilerResults results = provider.CompileAssemblyFromFile( parms, files ); -#else - parms.CompilerOptions = String.Format( "{0} /nowarn:169,219,414 /recurse:Scripts/*.cs", parms.CompilerOptions ); - CompilerResults results = provider.CompileAssemblyFromFile( parms, "" ); -#endif - m_AdditionalReferences.Add( path ); - - Display( results ); - -#if !MONO - if( results.Errors.Count > 0 ) - { - assembly = null; - return false; - } -#else - if( results.Errors.Count > 0 ) { - foreach( CompilerError err in results.Errors ) { - if ( !err.IsWarning ) { - assembly = null; - return false; - } - } - } -#endif - - - if( cache && Path.GetFileName( path ) == "Scripts.CS.dll" ) - { - try - { - byte[] hashCode = GetHashCode( path, files, debug ); - - using( FileStream fs = new FileStream( "Scripts/Output/Scripts.CS.hash", FileMode.Create, FileAccess.Write, FileShare.None ) ) - { - using( BinaryWriter bin = new BinaryWriter( fs ) ) - { - bin.Write( hashCode, 0, hashCode.Length ); - } - } - } - catch - { - } - } - - assembly = results.CompiledAssembly; - return true; - } - } - - public static bool CompileVBScripts( out Assembly assembly ) - { - return CompileVBScripts( false, out assembly ); - } - - public static bool CompileVBScripts( bool debug, out Assembly assembly ) - { - return CompileVBScripts( debug, true, out assembly ); - } - - public static bool CompileVBScripts( bool debug, bool cache, out Assembly assembly ) - { - Console.Write( "Scripts: Compiling VB.NET scripts..." ); - string[] files = GetScripts( "*.vb" ); - - if( files.Length == 0 ) - { - Console.WriteLine( "no files found." ); - assembly = null; - return true; - } - - if( File.Exists( "Scripts/Output/Scripts.VB.dll" ) ) - { - if( cache && File.Exists( "Scripts/Output/Scripts.VB.hash" ) ) - { - byte[] hashCode = GetHashCode( "Scripts/Output/Scripts.VB.dll", files, debug ); - - try - { - using( FileStream fs = new FileStream( "Scripts/Output/Scripts.VB.hash", FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - using( BinaryReader bin = new BinaryReader( fs ) ) - { - byte[] bytes = bin.ReadBytes( hashCode.Length ); - - if( bytes.Length == hashCode.Length ) - { - bool valid = true; - - for( int i = 0; i < bytes.Length; ++i ) - { - if( bytes[i] != hashCode[i] ) - { - valid = false; - break; - } - } - - if( valid ) - { - assembly = Assembly.LoadFrom( "Scripts/Output/Scripts.VB.dll" ); - - if( !m_AdditionalReferences.Contains( assembly.Location ) ) - { - m_AdditionalReferences.Add( assembly.Location ); - } - - Console.WriteLine( "done (cached)" ); - - return true; - } - } - } - } - } - catch - { - } - } - } - - DeleteFiles( "Scripts.VB*.dll" ); - - using( VBCodeProvider provider = new VBCodeProvider() ) - { - string path = GetUnusedPath( "Scripts.VB" ); - - CompilerParameters parms = new CompilerParameters( GetReferenceAssemblies(), path, debug ); - - string defines = GetDefines(); - - if( defines != null ) - parms.CompilerOptions = String.Format( "/D:{0}", defines ); - - if( Core.HaltOnWarning ) - parms.WarningLevel = 4; - - CompilerResults results = provider.CompileAssemblyFromFile( parms, files ); - m_AdditionalReferences.Add( path ); - - Display( results ); - - if( results.Errors.Count > 0 ) - { - assembly = null; - return false; - } - - if( cache && Path.GetFileName( path ) == "Scripts.VB.dll" ) - { - try - { - byte[] hashCode = GetHashCode( path, files, debug ); - - using( FileStream fs = new FileStream( "Scripts/Output/Scripts.VB.hash", FileMode.Create, FileAccess.Write, FileShare.None ) ) - { - using( BinaryWriter bin = new BinaryWriter( fs ) ) - { - bin.Write( hashCode, 0, hashCode.Length ); - } - } - } - catch - { - } - } - - assembly = results.CompiledAssembly; - return true; - } - } - - public static void Display( CompilerResults results ) - { - if( results.Errors.Count > 0 ) - { - Dictionary> errors = new Dictionary>( results.Errors.Count, StringComparer.OrdinalIgnoreCase ); - Dictionary> warnings = new Dictionary>( results.Errors.Count, StringComparer.OrdinalIgnoreCase ); - - foreach( CompilerError e in results.Errors ) - { - Dictionary> table = (e.IsWarning ? warnings : errors); - - List list = null; - table.TryGetValue( e.FileName, out list ); - - if( list == null ) - table[e.FileName] = list = new List(); - - list.Add( e ); - } - - if( errors.Count > 0 ) - Console.WriteLine( "failed ({0} errors, {1} warnings)", errors.Count, warnings.Count ); - else - Console.WriteLine( "done ({0} errors, {1} warnings)", errors.Count, warnings.Count ); - - string scriptRoot = Path.GetFullPath( Path.Combine( Core.BaseDirectory, "Scripts" + Path.DirectorySeparatorChar ) ); - Uri scriptRootUri = new Uri( scriptRoot ); - - Utility.PushColor( ConsoleColor.Yellow ); - - if( warnings.Count > 0 ) - Console.WriteLine( "Warnings:" ); - - foreach( KeyValuePair> kvp in warnings ) - { - string fileName = kvp.Key; - List list = kvp.Value; - - string fullPath = Path.GetFullPath( fileName ); - string usedPath = Uri.UnescapeDataString( scriptRootUri.MakeRelativeUri( new Uri( fullPath ) ).OriginalString ); - - Console.WriteLine( " + {0}:", usedPath ); - - Utility.PushColor( ConsoleColor.DarkYellow ); - - foreach( CompilerError e in list ) - Console.WriteLine( " {0}: Line {1}: {3}", e.ErrorNumber, e.Line, e.Column, e.ErrorText ); - - Utility.PopColor(); - } - - Utility.PopColor(); - - Utility.PushColor( ConsoleColor.Red ); - - if( errors.Count > 0 ) - Console.WriteLine( "Errors:" ); - - foreach( KeyValuePair> kvp in errors ) - { - string fileName = kvp.Key; - List list = kvp.Value; - - string fullPath = Path.GetFullPath( fileName ); - string usedPath = Uri.UnescapeDataString( scriptRootUri.MakeRelativeUri( new Uri( fullPath ) ).OriginalString ); - - Console.WriteLine( " + {0}:", usedPath ); - - Utility.PushColor( ConsoleColor.DarkRed ); - - foreach( CompilerError e in list ) - Console.WriteLine( " {0}: Line {1}: {3}", e.ErrorNumber, e.Line, e.Column, e.ErrorText ); - - Utility.PopColor(); - } - - Utility.PopColor(); - } - else - { - Console.WriteLine( "done (0 errors, 0 warnings)" ); - } - } - - public static string GetUnusedPath( string name ) - { - string path = Path.Combine( Core.BaseDirectory, String.Format( "Scripts/Output/{0}.dll", name ) ); - - for( int i = 2; File.Exists( path ) && i <= 1000; ++i ) - path = Path.Combine( Core.BaseDirectory, String.Format( "Scripts/Output/{0}.{1}.dll", name, i ) ); - - return path; - } - - public static void DeleteFiles( string mask ) - { - try - { - string[] files = Directory.GetFiles( Path.Combine( Core.BaseDirectory, "Scripts/Output" ), mask ); - - foreach( string file in files ) - { - try { File.Delete( file ); } - catch { } - } - } - catch - { - } - } - - private delegate CompilerResults Compiler( bool debug ); - - private void LoadScriptedAssembly( List assemblies, string fileName, Compiler compiler, bool debug ) - { - - - if( File.Exists( fileName ) ) - { - } - } - - public static bool Compile() - { - return Compile( false ); - } - - public static bool Compile( bool debug ) - { - return Compile( debug, true ); - } - - public static bool Compile( bool debug, bool cache ) - { - EnsureDirectory( "Scripts/" ); - EnsureDirectory( "Scripts/Output/" ); - - if( m_AdditionalReferences.Count > 0 ) - m_AdditionalReferences.Clear(); - - List assemblies = new List(); - - Assembly assembly; - - if( CompileCSScripts( debug, cache, out assembly ) ) - { - if( assembly != null ) - { - assemblies.Add( assembly ); - } - } - else - { - return false; - } - - if( CompileVBScripts( debug, cache, out assembly ) ) - { - if( assembly != null ) - { - assemblies.Add( assembly ); - } - } - else - { - return false; - } - - if( assemblies.Count == 0 ) - { - return false; - } - - m_Assemblies = assemblies.ToArray(); - - Console.Write( "Scripts: Verifying..." ); - Core.VerifySerialization(); - Console.WriteLine( "done ({0} items, {1} mobiles)", Core.ScriptItems, Core.ScriptMobiles ); - - List invoke = new List(); - - for( int a = 0; a < m_Assemblies.Length; ++a ) - { - Type[] types = m_Assemblies[a].GetTypes(); - - for( int i = 0; i < types.Length; ++i ) - { - MethodInfo m = types[i].GetMethod( "Configure", BindingFlags.Static | BindingFlags.Public ); - - if( m != null ) - invoke.Add( m ); - } - } - - invoke.Sort( new CallPriorityComparer() ); - - for( int i = 0; i < invoke.Count; ++i ) - invoke[i].Invoke( null, null ); - - invoke.Clear(); - - Region.Load(); - World.Load(); - - for( int a = 0; a < m_Assemblies.Length; ++a ) - { - Type[] types = m_Assemblies[a].GetTypes(); - - for( int i = 0; i < types.Length; ++i ) - { - MethodInfo m = types[i].GetMethod( "Initialize", BindingFlags.Static | BindingFlags.Public ); - - if( m != null ) - invoke.Add( m ); - } - } - - invoke.Sort( new CallPriorityComparer() ); - - for( int i = 0; i < invoke.Count; ++i ) - invoke[i].Invoke( null, null ); - - return true; - } - - private static Dictionary m_TypeCaches = new Dictionary(); - private static TypeCache m_NullCache; - - public static TypeCache GetTypeCache( Assembly asm ) - { - if( asm == null ) - { - if( m_NullCache == null ) - m_NullCache = new TypeCache( null ); - - return m_NullCache; - } - - TypeCache c = null; - m_TypeCaches.TryGetValue( asm, out c ); - - if( c == null ) - m_TypeCaches[asm] = c = new TypeCache( asm ); - - return c; - } - - public static Type FindTypeByFullName( string fullName ) - { - return FindTypeByFullName( fullName, true ); - } - - public static Type FindTypeByFullName( string fullName, bool ignoreCase ) - { - Type type = null; - - for( int i = 0; type == null && i < m_Assemblies.Length; ++i ) - type = GetTypeCache( m_Assemblies[i] ).GetTypeByFullName( fullName, ignoreCase ); - - if( type == null ) - type = GetTypeCache( Core.Assembly ).GetTypeByFullName( fullName, ignoreCase ); - - return type; - } - - public static Type FindTypeByName( string name ) - { - return FindTypeByName( name, true ); - } - - public static Type FindTypeByName( string name, bool ignoreCase ) - { - Type type = null; - - for( int i = 0; type == null && i < m_Assemblies.Length; ++i ) - type = GetTypeCache( m_Assemblies[i] ).GetTypeByName( name, ignoreCase ); - - if( type == null ) - type = GetTypeCache( Core.Assembly ).GetTypeByName( name, ignoreCase ); - - return type; - } - - public static void EnsureDirectory( string dir ) - { - string path = Path.Combine( Core.BaseDirectory, dir ); - - if( !Directory.Exists( path ) ) - Directory.CreateDirectory( path ); - } - - public static string[] GetScripts( string filter ) - { - List list = new List(); - - GetScripts( list, Path.Combine( Core.BaseDirectory, "Scripts" ), filter ); - - return list.ToArray(); - } - - public static void GetScripts( List list, string path, string filter ) - { - foreach( string dir in Directory.GetDirectories( path ) ) - GetScripts( list, dir, filter ); - - list.AddRange( Directory.GetFiles( path, filter ) ); - } - } - - public class TypeCache - { - private Type[] m_Types; - private TypeTable m_Names, m_FullNames; - - public Type[] Types { get { return m_Types; } } - public TypeTable Names { get { return m_Names; } } - public TypeTable FullNames { get { return m_FullNames; } } - - public Type GetTypeByName( string name, bool ignoreCase ) - { - return m_Names.Get( name, ignoreCase ); - } - - public Type GetTypeByFullName( string fullName, bool ignoreCase ) - { - return m_FullNames.Get( fullName, ignoreCase ); - } - - public TypeCache( Assembly asm ) - { - if( asm == null ) - m_Types = Type.EmptyTypes; - else - m_Types = asm.GetTypes(); - - m_Names = new TypeTable( m_Types.Length ); - m_FullNames = new TypeTable( m_Types.Length ); - - Type typeofTypeAliasAttribute = typeof( TypeAliasAttribute ); - - for( int i = 0; i < m_Types.Length; ++i ) - { - Type type = m_Types[i]; - - m_Names.Add( type.Name, type ); - m_FullNames.Add( type.FullName, type ); - - if( type.IsDefined( typeofTypeAliasAttribute, false ) ) - { - object[] attrs = type.GetCustomAttributes( typeofTypeAliasAttribute, false ); - - if( attrs != null && attrs.Length > 0 ) - { - TypeAliasAttribute attr = attrs[0] as TypeAliasAttribute; - - if( attr != null ) - { - for( int j = 0; j < attr.Aliases.Length; ++j ) - m_FullNames.Add( attr.Aliases[j], type ); - } - } - } - } - } - } - - public class TypeTable - { - private Dictionary m_Sensitive, m_Insensitive; - - public void Add( string key, Type type ) - { - m_Sensitive[key] = type; - m_Insensitive[key] = type; - } - - public Type Get( string key, bool ignoreCase ) - { - Type t = null; - - if( ignoreCase ) - m_Insensitive.TryGetValue( key, out t ); - else - m_Sensitive.TryGetValue( key, out t ); - - return t; - } - - public TypeTable( int capacity ) - { - m_Sensitive = new Dictionary( capacity ); - m_Insensitive = new Dictionary( capacity, StringComparer.OrdinalIgnoreCase ); - } - } -} +/*************************************************************************** + * ScriptCompiler.cs + * ------------------- + * begin : May 1, 2002 + * copyright : (C) The RunUO Software Team + * email : info@runuo.com + * + * $Id$ + * + ***************************************************************************/ + +/*************************************************************************** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + ***************************************************************************/ + +using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Reflection; +using System.Security.Cryptography; +using Microsoft.CSharp; +using Microsoft.VisualBasic; + +namespace Server +{ + public class ScriptCompiler + { + private static Assembly[] m_Assemblies; + + public static Assembly[] Assemblies + { + get + { + return m_Assemblies; + } + set + { + m_Assemblies = value; + } + } + + private static List m_AdditionalReferences = new List(); + + public static string[] GetReferenceAssemblies() + { + List list = new List(); + + string path = Path.Combine( Core.BaseDirectory, "Data/Assemblies.cfg" ); + + if( File.Exists( path ) ) + { + using( StreamReader ip = new StreamReader( path ) ) + { + string line; + + while( (line = ip.ReadLine()) != null ) + { + if( line.Length > 0 && !line.StartsWith( "#" ) ) + list.Add( line ); + } + } + } + + list.Add( Core.ExePath ); + + list.AddRange( m_AdditionalReferences ); + + return list.ToArray(); + } + + public static string GetDefines() + { + StringBuilder sb = null; + +#if MONO + AppendDefine( ref sb, "/d:MONO" ); +#endif + + //These two defines are legacy, ie, depreciated. + if( Core.Is64Bit ) + AppendDefine( ref sb, "/d:x64" ); + + AppendDefine( ref sb, "/d:Framework_2_0" ); + + return (sb == null ? null : sb.ToString()); + } + + public static void AppendDefine( ref StringBuilder sb, string define ) + { + if( sb == null ) + sb = new StringBuilder(); + else + sb.Append( ' ' ); + + sb.Append( define ); + } + + private static byte[] GetHashCode( string compiledFile, string[] scriptFiles, bool debug ) + { + using( MemoryStream ms = new MemoryStream() ) + { + using( BinaryWriter bin = new BinaryWriter( ms ) ) + { + FileInfo fileInfo = new FileInfo( compiledFile ); + + bin.Write( fileInfo.LastWriteTimeUtc.Ticks ); + + foreach( string scriptFile in scriptFiles ) + { + fileInfo = new FileInfo( scriptFile ); + + bin.Write( fileInfo.LastWriteTimeUtc.Ticks ); + } + + bin.Write( debug ); + + ms.Position = 0; + + using( SHA1 sha1 = SHA1.Create() ) + { + return sha1.ComputeHash( ms ); + } + } + } + } + + public static bool CompileCSScripts( out Assembly assembly ) + { + return CompileCSScripts( false, true, out assembly ); + } + + public static bool CompileCSScripts( bool debug, out Assembly assembly ) + { + return CompileCSScripts( debug, true, out assembly ); + } + + public static bool CompileCSScripts( bool debug, bool cache, out Assembly assembly ) + { + Console.Write( "Scripts: Compiling C# scripts..." ); + string[] files = GetScripts( "*.cs" ); + + if( files.Length == 0 ) + { + Console.WriteLine( "no files found." ); + assembly = null; + return true; + } + + if( File.Exists( "Scripts/Output/Scripts.CS.dll" ) ) + { + if( cache && File.Exists( "Scripts/Output/Scripts.CS.hash" ) ) + { + try + { + byte[] hashCode = GetHashCode( "Scripts/Output/Scripts.CS.dll", files, debug ); + + using( FileStream fs = new FileStream( "Scripts/Output/Scripts.CS.hash", FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + using( BinaryReader bin = new BinaryReader( fs ) ) + { + byte[] bytes = bin.ReadBytes( hashCode.Length ); + + if( bytes.Length == hashCode.Length ) + { + bool valid = true; + + for( int i = 0; i < bytes.Length; ++i ) + { + if( bytes[i] != hashCode[i] ) + { + valid = false; + break; + } + } + + if( valid ) + { + assembly = Assembly.LoadFrom( "Scripts/Output/Scripts.CS.dll" ); + + if( !m_AdditionalReferences.Contains( assembly.Location ) ) + { + m_AdditionalReferences.Add( assembly.Location ); + } + + Console.WriteLine( "done (cached)" ); + + return true; + } + } + } + } + } + catch + { + } + } + } + + DeleteFiles( "Scripts.CS*.dll" ); + + using( CSharpCodeProvider provider = new CSharpCodeProvider() ) + { + string path = GetUnusedPath( "Scripts.CS" ); + + CompilerParameters parms = new CompilerParameters( GetReferenceAssemblies(), path, debug ); + + string defines = GetDefines(); + + if( defines != null ) + parms.CompilerOptions = defines; + + if( Core.HaltOnWarning ) + parms.WarningLevel = 4; + +#if !MONO + CompilerResults results = provider.CompileAssemblyFromFile( parms, files ); +#else + parms.CompilerOptions = String.Format( "{0} /nowarn:169,219,414 /recurse:Scripts/*.cs", parms.CompilerOptions ); + CompilerResults results = provider.CompileAssemblyFromFile( parms, "" ); +#endif + m_AdditionalReferences.Add( path ); + + Display( results ); + +#if !MONO + if( results.Errors.Count > 0 ) + { + assembly = null; + return false; + } +#else + if( results.Errors.Count > 0 ) { + foreach( CompilerError err in results.Errors ) { + if ( !err.IsWarning ) { + assembly = null; + return false; + } + } + } +#endif + + + if( cache && Path.GetFileName( path ) == "Scripts.CS.dll" ) + { + try + { + byte[] hashCode = GetHashCode( path, files, debug ); + + using( FileStream fs = new FileStream( "Scripts/Output/Scripts.CS.hash", FileMode.Create, FileAccess.Write, FileShare.None ) ) + { + using( BinaryWriter bin = new BinaryWriter( fs ) ) + { + bin.Write( hashCode, 0, hashCode.Length ); + } + } + } + catch + { + } + } + + assembly = results.CompiledAssembly; + return true; + } + } + + public static bool CompileVBScripts( out Assembly assembly ) + { + return CompileVBScripts( false, out assembly ); + } + + public static bool CompileVBScripts( bool debug, out Assembly assembly ) + { + return CompileVBScripts( debug, true, out assembly ); + } + + public static bool CompileVBScripts( bool debug, bool cache, out Assembly assembly ) + { + Console.Write( "Scripts: Compiling VB.NET scripts..." ); + string[] files = GetScripts( "*.vb" ); + + if( files.Length == 0 ) + { + Console.WriteLine( "no files found." ); + assembly = null; + return true; + } + + if( File.Exists( "Scripts/Output/Scripts.VB.dll" ) ) + { + if( cache && File.Exists( "Scripts/Output/Scripts.VB.hash" ) ) + { + byte[] hashCode = GetHashCode( "Scripts/Output/Scripts.VB.dll", files, debug ); + + try + { + using( FileStream fs = new FileStream( "Scripts/Output/Scripts.VB.hash", FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + using( BinaryReader bin = new BinaryReader( fs ) ) + { + byte[] bytes = bin.ReadBytes( hashCode.Length ); + + if( bytes.Length == hashCode.Length ) + { + bool valid = true; + + for( int i = 0; i < bytes.Length; ++i ) + { + if( bytes[i] != hashCode[i] ) + { + valid = false; + break; + } + } + + if( valid ) + { + assembly = Assembly.LoadFrom( "Scripts/Output/Scripts.VB.dll" ); + + if( !m_AdditionalReferences.Contains( assembly.Location ) ) + { + m_AdditionalReferences.Add( assembly.Location ); + } + + Console.WriteLine( "done (cached)" ); + + return true; + } + } + } + } + } + catch + { + } + } + } + + DeleteFiles( "Scripts.VB*.dll" ); + + using( VBCodeProvider provider = new VBCodeProvider() ) + { + string path = GetUnusedPath( "Scripts.VB" ); + + CompilerParameters parms = new CompilerParameters( GetReferenceAssemblies(), path, debug ); + + string defines = GetDefines(); + + if( defines != null ) + parms.CompilerOptions = String.Format( "/D:{0}", defines ); + + if( Core.HaltOnWarning ) + parms.WarningLevel = 4; + + CompilerResults results = provider.CompileAssemblyFromFile( parms, files ); + m_AdditionalReferences.Add( path ); + + Display( results ); + + if( results.Errors.Count > 0 ) + { + assembly = null; + return false; + } + + if( cache && Path.GetFileName( path ) == "Scripts.VB.dll" ) + { + try + { + byte[] hashCode = GetHashCode( path, files, debug ); + + using( FileStream fs = new FileStream( "Scripts/Output/Scripts.VB.hash", FileMode.Create, FileAccess.Write, FileShare.None ) ) + { + using( BinaryWriter bin = new BinaryWriter( fs ) ) + { + bin.Write( hashCode, 0, hashCode.Length ); + } + } + } + catch + { + } + } + + assembly = results.CompiledAssembly; + return true; + } + } + + public static void Display( CompilerResults results ) + { + if( results.Errors.Count > 0 ) + { + Dictionary> errors = new Dictionary>( results.Errors.Count, StringComparer.OrdinalIgnoreCase ); + Dictionary> warnings = new Dictionary>( results.Errors.Count, StringComparer.OrdinalIgnoreCase ); + + foreach( CompilerError e in results.Errors ) + { + Dictionary> table = (e.IsWarning ? warnings : errors); + + List list = null; + table.TryGetValue( e.FileName, out list ); + + if( list == null ) + table[e.FileName] = list = new List(); + + list.Add( e ); + } + + if( errors.Count > 0 ) + Console.WriteLine( "failed ({0} errors, {1} warnings)", errors.Count, warnings.Count ); + else + Console.WriteLine( "done ({0} errors, {1} warnings)", errors.Count, warnings.Count ); + + string scriptRoot = Path.GetFullPath( Path.Combine( Core.BaseDirectory, "Scripts" + Path.DirectorySeparatorChar ) ); + Uri scriptRootUri = new Uri( scriptRoot ); + + Utility.PushColor( ConsoleColor.Yellow ); + + if( warnings.Count > 0 ) + Console.WriteLine( "Warnings:" ); + + foreach( KeyValuePair> kvp in warnings ) + { + string fileName = kvp.Key; + List list = kvp.Value; + + string fullPath = Path.GetFullPath( fileName ); + string usedPath = Uri.UnescapeDataString( scriptRootUri.MakeRelativeUri( new Uri( fullPath ) ).OriginalString ); + + Console.WriteLine( " + {0}:", usedPath ); + + Utility.PushColor( ConsoleColor.DarkYellow ); + + foreach( CompilerError e in list ) + Console.WriteLine( " {0}: Line {1}: {3}", e.ErrorNumber, e.Line, e.Column, e.ErrorText ); + + Utility.PopColor(); + } + + Utility.PopColor(); + + Utility.PushColor( ConsoleColor.Red ); + + if( errors.Count > 0 ) + Console.WriteLine( "Errors:" ); + + foreach( KeyValuePair> kvp in errors ) + { + string fileName = kvp.Key; + List list = kvp.Value; + + string fullPath = Path.GetFullPath( fileName ); + string usedPath = Uri.UnescapeDataString( scriptRootUri.MakeRelativeUri( new Uri( fullPath ) ).OriginalString ); + + Console.WriteLine( " + {0}:", usedPath ); + + Utility.PushColor( ConsoleColor.DarkRed ); + + foreach( CompilerError e in list ) + Console.WriteLine( " {0}: Line {1}: {3}", e.ErrorNumber, e.Line, e.Column, e.ErrorText ); + + Utility.PopColor(); + } + + Utility.PopColor(); + } + else + { + Console.WriteLine( "done (0 errors, 0 warnings)" ); + } + } + + public static string GetUnusedPath( string name ) + { + string path = Path.Combine( Core.BaseDirectory, String.Format( "Scripts/Output/{0}.dll", name ) ); + + for( int i = 2; File.Exists( path ) && i <= 1000; ++i ) + path = Path.Combine( Core.BaseDirectory, String.Format( "Scripts/Output/{0}.{1}.dll", name, i ) ); + + return path; + } + + public static void DeleteFiles( string mask ) + { + try + { + string[] files = Directory.GetFiles( Path.Combine( Core.BaseDirectory, "Scripts/Output" ), mask ); + + foreach( string file in files ) + { + try { File.Delete( file ); } + catch { } + } + } + catch + { + } + } + + private delegate CompilerResults Compiler( bool debug ); + + private void LoadScriptedAssembly( List assemblies, string fileName, Compiler compiler, bool debug ) + { + + + if( File.Exists( fileName ) ) + { + } + } + + public static bool Compile() + { + return Compile( false ); + } + + public static bool Compile( bool debug ) + { + return Compile( debug, true ); + } + + public static bool Compile( bool debug, bool cache ) + { + EnsureDirectory( "Scripts/" ); + EnsureDirectory( "Scripts/Output/" ); + + if( m_AdditionalReferences.Count > 0 ) + m_AdditionalReferences.Clear(); + + List assemblies = new List(); + + Assembly assembly; + + if( CompileCSScripts( debug, cache, out assembly ) ) + { + if( assembly != null ) + { + assemblies.Add( assembly ); + } + } + else + { + return false; + } + + if( CompileVBScripts( debug, cache, out assembly ) ) + { + if( assembly != null ) + { + assemblies.Add( assembly ); + } + } + else + { + return false; + } + + if( assemblies.Count == 0 ) + { + return false; + } + + m_Assemblies = assemblies.ToArray(); + + Console.Write( "Scripts: Verifying..." ); + Core.VerifySerialization(); + Console.WriteLine( "done ({0} items, {1} mobiles)", Core.ScriptItems, Core.ScriptMobiles ); + + List invoke = new List(); + + for( int a = 0; a < m_Assemblies.Length; ++a ) + { + Type[] types = m_Assemblies[a].GetTypes(); + + for( int i = 0; i < types.Length; ++i ) + { + MethodInfo m = types[i].GetMethod( "Configure", BindingFlags.Static | BindingFlags.Public ); + + if( m != null ) + invoke.Add( m ); + } + } + + invoke.Sort( new CallPriorityComparer() ); + + for( int i = 0; i < invoke.Count; ++i ) + invoke[i].Invoke( null, null ); + + invoke.Clear(); + + Region.Load(); + World.Load(); + + for( int a = 0; a < m_Assemblies.Length; ++a ) + { + Type[] types = m_Assemblies[a].GetTypes(); + + for( int i = 0; i < types.Length; ++i ) + { + MethodInfo m = types[i].GetMethod( "Initialize", BindingFlags.Static | BindingFlags.Public ); + + if( m != null ) + invoke.Add( m ); + } + } + + invoke.Sort( new CallPriorityComparer() ); + + for( int i = 0; i < invoke.Count; ++i ) + invoke[i].Invoke( null, null ); + + return true; + } + + private static Dictionary m_TypeCaches = new Dictionary(); + private static TypeCache m_NullCache; + + public static TypeCache GetTypeCache( Assembly asm ) + { + if( asm == null ) + { + if( m_NullCache == null ) + m_NullCache = new TypeCache( null ); + + return m_NullCache; + } + + TypeCache c = null; + m_TypeCaches.TryGetValue( asm, out c ); + + if( c == null ) + m_TypeCaches[asm] = c = new TypeCache( asm ); + + return c; + } + + public static Type FindTypeByFullName( string fullName ) + { + return FindTypeByFullName( fullName, true ); + } + + public static Type FindTypeByFullName( string fullName, bool ignoreCase ) + { + Type type = null; + + for( int i = 0; type == null && i < m_Assemblies.Length; ++i ) + type = GetTypeCache( m_Assemblies[i] ).GetTypeByFullName( fullName, ignoreCase ); + + if( type == null ) + type = GetTypeCache( Core.Assembly ).GetTypeByFullName( fullName, ignoreCase ); + + return type; + } + + public static Type FindTypeByName( string name ) + { + return FindTypeByName( name, true ); + } + + public static Type FindTypeByName( string name, bool ignoreCase ) + { + Type type = null; + + for( int i = 0; type == null && i < m_Assemblies.Length; ++i ) + type = GetTypeCache( m_Assemblies[i] ).GetTypeByName( name, ignoreCase ); + + if( type == null ) + type = GetTypeCache( Core.Assembly ).GetTypeByName( name, ignoreCase ); + + return type; + } + + public static void EnsureDirectory( string dir ) + { + string path = Path.Combine( Core.BaseDirectory, dir ); + + if( !Directory.Exists( path ) ) + Directory.CreateDirectory( path ); + } + + public static string[] GetScripts( string filter ) + { + List list = new List(); + + GetScripts( list, Path.Combine( Core.BaseDirectory, "Scripts" ), filter ); + + return list.ToArray(); + } + + public static void GetScripts( List list, string path, string filter ) + { + foreach( string dir in Directory.GetDirectories( path ) ) + GetScripts( list, dir, filter ); + + list.AddRange( Directory.GetFiles( path, filter ) ); + } + } + + public class TypeCache + { + private Type[] m_Types; + private TypeTable m_Names, m_FullNames; + + public Type[] Types { get { return m_Types; } } + public TypeTable Names { get { return m_Names; } } + public TypeTable FullNames { get { return m_FullNames; } } + + public Type GetTypeByName( string name, bool ignoreCase ) + { + return m_Names.Get( name, ignoreCase ); + } + + public Type GetTypeByFullName( string fullName, bool ignoreCase ) + { + return m_FullNames.Get( fullName, ignoreCase ); + } + + public TypeCache( Assembly asm ) + { + if( asm == null ) + m_Types = Type.EmptyTypes; + else + m_Types = asm.GetTypes(); + + m_Names = new TypeTable( m_Types.Length ); + m_FullNames = new TypeTable( m_Types.Length ); + + Type typeofTypeAliasAttribute = typeof( TypeAliasAttribute ); + + for( int i = 0; i < m_Types.Length; ++i ) + { + Type type = m_Types[i]; + + m_Names.Add( type.Name, type ); + m_FullNames.Add( type.FullName, type ); + + if( type.IsDefined( typeofTypeAliasAttribute, false ) ) + { + object[] attrs = type.GetCustomAttributes( typeofTypeAliasAttribute, false ); + + if( attrs != null && attrs.Length > 0 ) + { + TypeAliasAttribute attr = attrs[0] as TypeAliasAttribute; + + if( attr != null ) + { + for( int j = 0; j < attr.Aliases.Length; ++j ) + m_FullNames.Add( attr.Aliases[j], type ); + } + } + } + } + } + } + + public class TypeTable + { + private Dictionary m_Sensitive, m_Insensitive; + + public void Add( string key, Type type ) + { + m_Sensitive[key] = type; + m_Insensitive[key] = type; + } + + public Type Get( string key, bool ignoreCase ) + { + Type t = null; + + if( ignoreCase ) + m_Insensitive.TryGetValue( key, out t ); + else + m_Sensitive.TryGetValue( key, out t ); + + return t; + } + + public TypeTable( int capacity ) + { + m_Sensitive = new Dictionary( capacity ); + m_Insensitive = new Dictionary( capacity, StringComparer.OrdinalIgnoreCase ); + } + } +} diff --git a/Server/TileMatrixPatch.cs b/Server/TileMatrixPatch.cs index 4e4bfe856..39e516d75 100644 --- a/Server/TileMatrixPatch.cs +++ b/Server/TileMatrixPatch.cs @@ -1,249 +1,249 @@ -/*************************************************************************** - * TileMatrixPatch.cs - * ------------------- - * begin : May 1, 2002 - * copyright : (C) The RunUO Software Team - * email : info@runuo.com - * - * $Id$ - * - ***************************************************************************/ - -/*************************************************************************** - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - ***************************************************************************/ - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace Server -{ - public class TileMatrixPatch - { - private int m_LandBlocks, m_StaticBlocks; - - private static bool m_Enabled = true; - - public static bool Enabled - { - get - { - return m_Enabled; - } - set - { - m_Enabled = value; - } - } - -#if !MONO - [DllImport( "Kernel32" )] - private unsafe static extern int _lread( IntPtr hFile, void *lpBuffer, int wBytes ); -#endif - - public int LandBlocks - { - get - { - return m_LandBlocks; - } - } - - public int StaticBlocks - { - get - { - return m_StaticBlocks; - } - } - - public TileMatrixPatch( TileMatrix matrix, int index ) - { - if ( !m_Enabled ) - return; - - string mapDataPath = Core.FindDataFile( "mapdif{0}.mul", index ); - string mapIndexPath = Core.FindDataFile( "mapdifl{0}.mul", index ); - - if ( File.Exists( mapDataPath ) && File.Exists( mapIndexPath ) ) - m_LandBlocks = PatchLand( matrix, mapDataPath, mapIndexPath ); - - string staDataPath = Core.FindDataFile( "stadif{0}.mul", index ); - string staIndexPath = Core.FindDataFile( "stadifl{0}.mul", index ); - string staLookupPath = Core.FindDataFile( "stadifi{0}.mul", index ); - - if ( File.Exists( staDataPath ) && File.Exists( staIndexPath ) && File.Exists( staLookupPath ) ) - m_StaticBlocks = PatchStatics( matrix, staDataPath, staIndexPath, staLookupPath ); - } - - private unsafe int PatchLand( TileMatrix matrix, string dataPath, string indexPath ) - { - using ( FileStream fsData = new FileStream( dataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - using ( FileStream fsIndex = new FileStream( indexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - BinaryReader indexReader = new BinaryReader( fsIndex ); - - int count = (int)(indexReader.BaseStream.Length / 4); - - for ( int i = 0; i < count; ++i ) - { - int blockID = indexReader.ReadInt32(); - int x = blockID / matrix.BlockHeight; - int y = blockID % matrix.BlockHeight; - - fsData.Seek( 4, SeekOrigin.Current ); - - Tile[] tiles = new Tile[64]; - - fixed ( Tile *pTiles = tiles ) - { -#if !MONO - _lread( fsData.SafeFileHandle.DangerousGetHandle(), pTiles, 192 ); -#else - if ( m_Buffer == null || 192 > m_Buffer.Length ) - m_Buffer = new byte[192]; - - fsData.Read( m_Buffer, 0, 192 ); - - fixed ( byte *pbBuffer = m_Buffer ) - { - Tile *pBuffer = (Tile *)pbBuffer; - Tile *pEnd = pBuffer + 64; - Tile *pCur = pTiles; - - while ( pBuffer < pEnd ) { - *pCur = *pBuffer; - pCur = pCur + 1; - pBuffer = pBuffer + 1; - } - } -#endif - } - - matrix.SetLandBlock( x, y, tiles ); - } - - indexReader.Close(); - - return count; - } - } - } - -#if MONO - private static byte[] m_Buffer; -#endif - - private static StaticTile[] m_TileBuffer = new StaticTile[128]; - - private unsafe int PatchStatics( TileMatrix matrix, string dataPath, string indexPath, string lookupPath ) - { - using ( FileStream fsData = new FileStream( dataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - using ( FileStream fsIndex = new FileStream( indexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - using ( FileStream fsLookup = new FileStream( lookupPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) - { - BinaryReader indexReader = new BinaryReader( fsIndex ); - BinaryReader lookupReader = new BinaryReader( fsLookup ); - - int count = (int)(indexReader.BaseStream.Length / 4); - - TileList[][] lists = new TileList[8][]; - - for ( int x = 0; x < 8; ++x ) - { - lists[x] = new TileList[8]; - - for ( int y = 0; y < 8; ++y ) - lists[x][y] = new TileList(); - } - - for ( int i = 0; i < count; ++i ) - { - int blockID = indexReader.ReadInt32(); - int blockX = blockID / matrix.BlockHeight; - int blockY = blockID % matrix.BlockHeight; - - int offset = lookupReader.ReadInt32(); - int length = lookupReader.ReadInt32(); - lookupReader.ReadInt32(); // Extra - - if ( offset < 0 || length <= 0 ) - { - matrix.SetStaticBlock( blockX, blockY, matrix.EmptyStaticBlock ); - continue; - } - - fsData.Seek( offset, SeekOrigin.Begin ); - - int tileCount = length / 7; - - if ( m_TileBuffer.Length < tileCount ) - m_TileBuffer = new StaticTile[tileCount]; - - StaticTile[] staTiles = m_TileBuffer; - - fixed ( StaticTile *pTiles = staTiles ) - { -#if !MONO - _lread( fsData.SafeFileHandle.DangerousGetHandle(), pTiles, length ); -#else - if ( m_Buffer == null || length > m_Buffer.Length ) - m_Buffer = new byte[length]; - - fsData.Read( m_Buffer, 0, length ); - - fixed ( byte *pbBuffer = m_Buffer ) - { - StaticTile *pCopyBuffer = (StaticTile *)pbBuffer; - StaticTile *pCopyEnd = pCopyBuffer + tileCount; - StaticTile *pCopyCur = pTiles; - - while ( pCopyBuffer < pCopyEnd ) { - *pCopyCur = *pCopyBuffer; - pCopyCur = pCopyCur + 1; - pCopyBuffer = pCopyBuffer + 1; - } - } -#endif - - StaticTile *pCur = pTiles, pEnd = pTiles + tileCount; - - while ( pCur < pEnd ) - { - lists[pCur->m_X & 0x7][pCur->m_Y & 0x7].Add( (short)((pCur->m_ID & 0x3FFF) + 0x4000), pCur->m_Z ); - pCur = pCur + 1; - } - - Tile[][][] tiles = new Tile[8][][]; - - for ( int x = 0; x < 8; ++x ) - { - tiles[x] = new Tile[8][]; - - for ( int y = 0; y < 8; ++y ) - tiles[x][y] = lists[x][y].ToArray(); - } - - matrix.SetStaticBlock( blockX, blockY, tiles ); - } - } - - indexReader.Close(); - lookupReader.Close(); - - return count; - } - } - } - } - } +/*************************************************************************** + * TileMatrixPatch.cs + * ------------------- + * begin : May 1, 2002 + * copyright : (C) The RunUO Software Team + * email : info@runuo.com + * + * $Id$ + * + ***************************************************************************/ + +/*************************************************************************** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + ***************************************************************************/ + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Server +{ + public class TileMatrixPatch + { + private int m_LandBlocks, m_StaticBlocks; + + private static bool m_Enabled = true; + + public static bool Enabled + { + get + { + return m_Enabled; + } + set + { + m_Enabled = value; + } + } + +#if !MONO + [DllImport( "Kernel32" )] + private unsafe static extern int _lread( IntPtr hFile, void *lpBuffer, int wBytes ); +#endif + + public int LandBlocks + { + get + { + return m_LandBlocks; + } + } + + public int StaticBlocks + { + get + { + return m_StaticBlocks; + } + } + + public TileMatrixPatch( TileMatrix matrix, int index ) + { + if ( !m_Enabled ) + return; + + string mapDataPath = Core.FindDataFile( "mapdif{0}.mul", index ); + string mapIndexPath = Core.FindDataFile( "mapdifl{0}.mul", index ); + + if ( File.Exists( mapDataPath ) && File.Exists( mapIndexPath ) ) + m_LandBlocks = PatchLand( matrix, mapDataPath, mapIndexPath ); + + string staDataPath = Core.FindDataFile( "stadif{0}.mul", index ); + string staIndexPath = Core.FindDataFile( "stadifl{0}.mul", index ); + string staLookupPath = Core.FindDataFile( "stadifi{0}.mul", index ); + + if ( File.Exists( staDataPath ) && File.Exists( staIndexPath ) && File.Exists( staLookupPath ) ) + m_StaticBlocks = PatchStatics( matrix, staDataPath, staIndexPath, staLookupPath ); + } + + private unsafe int PatchLand( TileMatrix matrix, string dataPath, string indexPath ) + { + using ( FileStream fsData = new FileStream( dataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + using ( FileStream fsIndex = new FileStream( indexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + BinaryReader indexReader = new BinaryReader( fsIndex ); + + int count = (int)(indexReader.BaseStream.Length / 4); + + for ( int i = 0; i < count; ++i ) + { + int blockID = indexReader.ReadInt32(); + int x = blockID / matrix.BlockHeight; + int y = blockID % matrix.BlockHeight; + + fsData.Seek( 4, SeekOrigin.Current ); + + Tile[] tiles = new Tile[64]; + + fixed ( Tile *pTiles = tiles ) + { +#if !MONO + _lread( fsData.SafeFileHandle.DangerousGetHandle(), pTiles, 192 ); +#else + if ( m_Buffer == null || 192 > m_Buffer.Length ) + m_Buffer = new byte[192]; + + fsData.Read( m_Buffer, 0, 192 ); + + fixed ( byte *pbBuffer = m_Buffer ) + { + Tile *pBuffer = (Tile *)pbBuffer; + Tile *pEnd = pBuffer + 64; + Tile *pCur = pTiles; + + while ( pBuffer < pEnd ) { + *pCur = *pBuffer; + pCur = pCur + 1; + pBuffer = pBuffer + 1; + } + } +#endif + } + + matrix.SetLandBlock( x, y, tiles ); + } + + indexReader.Close(); + + return count; + } + } + } + +#if MONO + private static byte[] m_Buffer; +#endif + + private static StaticTile[] m_TileBuffer = new StaticTile[128]; + + private unsafe int PatchStatics( TileMatrix matrix, string dataPath, string indexPath, string lookupPath ) + { + using ( FileStream fsData = new FileStream( dataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + using ( FileStream fsIndex = new FileStream( indexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + using ( FileStream fsLookup = new FileStream( lookupPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) + { + BinaryReader indexReader = new BinaryReader( fsIndex ); + BinaryReader lookupReader = new BinaryReader( fsLookup ); + + int count = (int)(indexReader.BaseStream.Length / 4); + + TileList[][] lists = new TileList[8][]; + + for ( int x = 0; x < 8; ++x ) + { + lists[x] = new TileList[8]; + + for ( int y = 0; y < 8; ++y ) + lists[x][y] = new TileList(); + } + + for ( int i = 0; i < count; ++i ) + { + int blockID = indexReader.ReadInt32(); + int blockX = blockID / matrix.BlockHeight; + int blockY = blockID % matrix.BlockHeight; + + int offset = lookupReader.ReadInt32(); + int length = lookupReader.ReadInt32(); + lookupReader.ReadInt32(); // Extra + + if ( offset < 0 || length <= 0 ) + { + matrix.SetStaticBlock( blockX, blockY, matrix.EmptyStaticBlock ); + continue; + } + + fsData.Seek( offset, SeekOrigin.Begin ); + + int tileCount = length / 7; + + if ( m_TileBuffer.Length < tileCount ) + m_TileBuffer = new StaticTile[tileCount]; + + StaticTile[] staTiles = m_TileBuffer; + + fixed ( StaticTile *pTiles = staTiles ) + { +#if !MONO + _lread( fsData.SafeFileHandle.DangerousGetHandle(), pTiles, length ); +#else + if ( m_Buffer == null || length > m_Buffer.Length ) + m_Buffer = new byte[length]; + + fsData.Read( m_Buffer, 0, length ); + + fixed ( byte *pbBuffer = m_Buffer ) + { + StaticTile *pCopyBuffer = (StaticTile *)pbBuffer; + StaticTile *pCopyEnd = pCopyBuffer + tileCount; + StaticTile *pCopyCur = pTiles; + + while ( pCopyBuffer < pCopyEnd ) { + *pCopyCur = *pCopyBuffer; + pCopyCur = pCopyCur + 1; + pCopyBuffer = pCopyBuffer + 1; + } + } +#endif + + StaticTile *pCur = pTiles, pEnd = pTiles + tileCount; + + while ( pCur < pEnd ) + { + lists[pCur->m_X & 0x7][pCur->m_Y & 0x7].Add( (short)((pCur->m_ID & 0x3FFF) + 0x4000), pCur->m_Z ); + pCur = pCur + 1; + } + + Tile[][][] tiles = new Tile[8][][]; + + for ( int x = 0; x < 8; ++x ) + { + tiles[x] = new Tile[8][]; + + for ( int y = 0; y < 8; ++y ) + tiles[x][y] = lists[x][y].ToArray(); + } + + matrix.SetStaticBlock( blockX, blockY, tiles ); + } + } + + indexReader.Close(); + lookupReader.Close(); + + return count; + } + } + } + } + } } \ No newline at end of file