context: /***************************************************************************
   *                                  Main.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.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using System.Net;
  using System.Net.Sockets;
  using System.Reflection;
  using System.Runtime.InteropServices;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;
  using Server;
  using Server.Accounting;
  using Server.Gumps;
  using Server.Network;
  using System.Runtime;
  
  namespace Server
  {
  	public delegate void Slice();
  
  	public static class Core
  	{
  		private static bool m_Crashed;
  		private static Thread timerThread;
  		private static string m_BaseDirectory;
  		private static string m_ExePath;
  		private static List<string> m_DataDirectories = new List<string>();
  		private static Assembly m_Assembly;
  		private static Process m_Process;
  		private static Thread m_Thread;
  		private static bool m_Service;
  		private static bool m_Debug;
  		private static bool m_Cache = true;
  		private static bool m_HaltOnWarning;
  		private static bool m_VBdotNET;
  		private static MultiTextWriter m_MultiConOut;
  
  		private static bool m_Profiling;
  		private static DateTime m_ProfileStart;
  		private static TimeSpan m_ProfileTime;
  
  		private static MessagePump m_MessagePump;
  
  		public static MessagePump MessagePump
  		{
  			get { return m_MessagePump; }
  			set { m_MessagePump = value; }
  		}
  
  		public static Slice Slice;
  
  		public static bool Profiling
  		{
  			get { return m_Profiling; }
  			set
  			{
  				if( m_Profiling == value )
  					return;
  
  				m_Profiling = value;
  
  				if( m_ProfileStart > DateTime.MinValue )
  					m_ProfileTime += DateTime.UtcNow - m_ProfileStart;
  
  				m_ProfileStart = (m_Profiling ? DateTime.UtcNow : DateTime.MinValue);
  			}
  		}
  
  		public static TimeSpan ProfileTime
  		{
  			get
  			{
  				if( m_ProfileStart > DateTime.MinValue )
  					return m_ProfileTime + (DateTime.UtcNow - m_ProfileStart);
  
  				return m_ProfileTime;
  			}
  		}
  
  		public static bool Service { get { return m_Service; } }
  		public static bool Debug { get { return m_Debug; } }
  		internal static bool HaltOnWarning { get { return m_HaltOnWarning; } }
  		internal static bool VBdotNet { get { return m_VBdotNET; } }
  		public static List<string> DataDirectories { get { return m_DataDirectories; } }
  		public static Assembly Assembly { get { return m_Assembly; } set { m_Assembly = value; } }
  		public static Version Version { get { return m_Assembly.GetName().Version; } }
  		public static Process Process { get { return m_Process; } }
  		public static Thread Thread { get { return m_Thread; } }
  		public static MultiTextWriter MultiConsoleOut { get { return m_MultiConOut; } }
  
  		/* DateTime.Now and DateTime.UtcNow are based on actual system clock time.
  		 * The resolution is acceptable but large clock jumps are possible and cause issues.
  		 * GetTickCount and GetTickCount64 have poor resolution.
  		 * GetTickCount64 is unavailable on Windows XP and Windows Server 2003.
  		 * Stopwatch.GetTimestamp() (QueryPerformanceCounter) is high resolution, but
  		 * somewhat expensive to call and unreliable with certain system configurations.
  		 */
  
  		/* The following implementation contains an effective substitute for GetTickCount64 that
  		 * is reliable as long as it is retrieved once every 2^32 ms (~49 days).
  		 */
  
  		/* We don't really need this, but it may be useful in the future.
  		private static ThreadLocal<long> _HighOrder = new ThreadLocal<long>();
  		private static ThreadLocal<uint> _LastTickCount = new ThreadLocal<uint>();
  		*/
  
  		private static readonly bool _HighRes = Stopwatch.IsHighResolution;
  		private static readonly double _Frequency = 1000.0 / Stopwatch.Frequency;
  
  		private static bool _UseHRT;
  
  		public static bool UsingHighResolutionTiming { get { return _UseHRT && _HighRes && !m_Unix; } }
  
  		public static long TickCount {
  			get {
  #if !MONO
  				if (_UseHRT && _HighRes)
  				{
  					long t = 0;
  					SafeNativeMethods.QueryPerformanceCounter(out t);
  					return (long)((double)t * _Frequency);
  				}
  				else
  #endif
  					return (long)((double)DateTime.UtcNow.Ticks * 0.0001);
  
  				/* We don't really need this, but it may be useful in the future.
  				uint t = (uint)Environment.TickCount;
  
  				if (_LastTickCount.Value > t) // Wrapped
  					_HighOrder.Value += 0x100000000;
  
  				_LastTickCount.Value = t;
  				
  				return _HighOrder.Value | _LastTickCount.Value;
  				*/
  			}
  		}
  
  		public static readonly bool Is64Bit = Environment.Is64BitProcess;
  
  		private static bool m_MultiProcessor;
  		private static int m_ProcessorCount;
  
  		public static bool MultiProcessor { get { return m_MultiProcessor; } }
  		public static int ProcessorCount { get { return m_ProcessorCount; } }
  
  		private static bool m_Unix;
  		
  		public static bool Unix { get { return m_Unix; } }
  
  		public static string FindDataFile( string path )
  		{
  			if( m_DataDirectories.Count == 0 )
  				throw new InvalidOperationException( "Attempted to FindDataFile before DataDirectories list has been filled." );
  
  			string fullPath = null;
  
  			for( int i = 0; i < m_DataDirectories.Count; ++i )
  			{
  				fullPath = Path.Combine( m_DataDirectories[i], path );
  
  				if( File.Exists( fullPath ) )
  					break;
  
  				fullPath = null;
  			}
  
  			return fullPath;
  		}
  
  		public static string FindDataFile( string format, params object[] args )
  		{
  			return FindDataFile( String.Format( format, args ) );
  		}
  
  		#region Expansions
  
  		private static Expansion m_Expansion;
  		public static Expansion Expansion
  		{
  
gt: 			get { return m_Expansion; }