context: #region References
  using System;
  using System.CodeDom.Compiler;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using System.Reflection;
  using System.Security.Cryptography;
  using System.Text;
  
  using Microsoft.CSharp;
  #endregion
  
  namespace Server
  {
  	public static class ScriptCompiler
  	{
  		public static Assembly[] Assemblies { get; set; }
  
  		private static readonly List<string> m_AdditionalReferences = new List<string>();
  
  		public static string[] GetReferenceAssemblies()
  		{
  			var list = new List<string>();
  
  			var path = Path.Combine(Core.BaseDirectory, "Data/Assemblies.cfg");
  
  			if (File.Exists(path))
  			{
  				using (var 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 GetCompilerOptions(bool debug)
  		{
  			StringBuilder sb = null;
  
  			AppendCompilerOption(ref sb, "/d:ServUO");
  
  			AppendCompilerOption(ref sb, "/unsafe");
  
  			if (!debug)
  			{
  				AppendCompilerOption(ref sb, "/optimize");
  			}
  			else
  			{
  				AppendCompilerOption(ref sb, "/debug");
  				AppendCompilerOption(ref sb, "/d:DEBUG");
  				AppendCompilerOption(ref sb, "/d:TRACE");
  			}
  
  #if MONO
  			AppendCompilerOption( ref sb, "/d:MONO" );
  #endif
  
  			if (Core.Is64Bit)
  			{
  				AppendCompilerOption(ref sb, "/d:x64");
  			}
  
  #if NEWTIMERS
  			AppendCompilerOption(ref sb, "/d:NEWTIMERS");
  #endif
  
  #if NEWPARENT
  			AppendCompilerOption(ref sb, "/d:NEWPARENT");
  #endif
  
  			return (sb == null ? null : sb.ToString());
  		}
  
  		private static void AppendCompilerOption(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 (var ms = new MemoryStream())
  			{
  				using (var bin = new BinaryWriter(ms))
  				{
  					var fileInfo = new FileInfo(compiledFile);
  
  					bin.Write(fileInfo.LastWriteTimeUtc.Ticks);
  
  					foreach (var scriptFile in scriptFiles)
  					{
  						fileInfo = new FileInfo(scriptFile);
  
  						bin.Write(fileInfo.LastWriteTimeUtc.Ticks);
  					}
  
  					bin.Write(debug);
  					bin.Write(Core.Version.ToString());
  
  					ms.Position = 0;
  
  					using (var 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)
  		{
  			Utility.PushColor(ConsoleColor.Yellow);
  			Console.Write("Scripts: Compiling C# scripts...");
  			Utility.PopColor();
  			var files = GetScripts("*.cs");
  
  			if (files.Length == 0)
  			{
  				Utility.PushColor(ConsoleColor.Red);
  				Console.WriteLine("no files found.");
  				Utility.PopColor();
  				assembly = null;
  				return true;
  			}
  
  			if (File.Exists("Scripts/Output/Scripts.CS.dll"))
  			{
  				if (cache && File.Exists("Scripts/Output/Scripts.CS.hash"))
  				{
  					try
  					{
  						var hashCode = GetHashCode("Scripts/Output/Scripts.CS.dll", files, debug);
  
  						using (var fs = new FileStream("Scripts/Output/Scripts.CS.hash", FileMode.Open, FileAccess.Read, FileShare.Read))
  						{
  							using (var bin = new BinaryReader(fs))
  							{
  								var bytes = bin.ReadBytes(hashCode.Length);
  
  								if (bytes.Length == hashCode.Length)
  								{
  									var valid = true;
  
  									for (var 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);
  										}
  
  										Utility.PushColor(ConsoleColor.Green);
  										Console.WriteLine("done (cached)");
  										Utility.PopColor();
  
  										return true;
  									}
  								}
  							}
  						}
  					}
  					catch
  					{ }
  				}
  			}
  
  			DeleteFiles("Scripts.CS*.dll");
  
  			using (var provider = new CSharpCodeProvider())
  			{
  				var path = GetUnusedPath("Scripts.CS");
  
  				var parms = new CompilerParameters(GetReferenceAssemblies(), path, debug);
  
  				var options = GetCompilerOptions(debug);
  
  				if (options != null)
  				{
  					parms.CompilerOptions = options;
  				}
  
  				if (Core.HaltOnWarning)
  				{
  					parms.WarningLevel = 4;
  				}
  
  				if (Core.Unix)
                  {
  					parms.CompilerOptions = String.Format( "{0} /nowarn:169,219,414 /recurse:Scripts/*.cs", parms.CompilerOptions );
                      files = new string[0];
                  }
                  
  				var results = provider.CompileAssemblyFromFile(parms, files);
  				
  				m_AdditionalReferences.Add(path);
  
  				Display(results);
  
  
gt: 				if (results.Errors.Count > 0 && !Core.Unix)