diff --git a/Data/Assemblies.cfg b/Data/Assemblies.cfg index 7d560989a..357aefb97 100644 --- a/Data/Assemblies.cfg +++ b/Data/Assemblies.cfg @@ -1,5 +1,4 @@ System.dll -System.Core.dll System.Web.dll System.Xml.dll System.Data.dll diff --git a/Scripts/Accounting/Account.cs b/Scripts/Accounting/Account.cs index b0199d785..ce9be7c38 100644 --- a/Scripts/Accounting/Account.cs +++ b/Scripts/Accounting/Account.cs @@ -665,9 +665,11 @@ namespace Server.Accounting break; } } - +#if Framework_4_0 Enum.TryParse( Utility.GetText( node["accessLevel"], "Player" ), true, out m_AccessLevel ); - +#else + m_AccessLevel = (AccessLevel)Enum.Parse( typeof( AccessLevel ), Utility.GetText( node["accessLevel"], "Player" ), true ); +#endif m_Flags = Utility.GetXMLInt32( Utility.GetText( node["flags"], "0" ), 0 ); m_Created = Utility.GetXMLDateTime( Utility.GetText( node["created"], null ), DateTime.Now ); m_LastLogin = Utility.GetXMLDateTime( Utility.GetText( node["lastLogin"], null ), DateTime.Now ); diff --git a/Scripts/Commands/Skills.cs b/Scripts/Commands/Skills.cs index bcca1bf34..71dd69911 100644 --- a/Scripts/Commands/Skills.cs +++ b/Scripts/Commands/Skills.cs @@ -25,7 +25,7 @@ namespace Server.Commands else { SkillName skill; - +#if Framework_4_0 if( Enum.TryParse( arg.GetString( 0 ), true, out skill ) ) { arg.Mobile.Target = new SkillTarget( skill, arg.GetDouble( 1 ) ); @@ -34,6 +34,18 @@ namespace Server.Commands { arg.Mobile.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. } +#else + try + { + skill = (SkillName)Enum.Parse( typeof( SkillName ), arg.GetString( 0 ), true ); + } + catch + { + arg.Mobile.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. + return; + } + arg.Mobile.Target = new SkillTarget( skill, arg.GetDouble( 1 ) ); +#endif } } @@ -62,7 +74,7 @@ namespace Server.Commands else { SkillName skill; - +#if Framework_4_0 if( Enum.TryParse( arg.GetString( 0 ), true, out skill ) ) { arg.Mobile.Target = new SkillTarget( skill ); @@ -71,6 +83,19 @@ namespace Server.Commands { arg.Mobile.SendMessage( "You have specified an invalid skill to get." ); } +#else + try + { + skill = (SkillName)Enum.Parse( typeof( SkillName ), arg.GetString( 0 ), true ); + } + catch + { + arg.Mobile.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. + return; + } + + arg.Mobile.Target = new SkillTarget( skill ); +#endif } } diff --git a/Scripts/SpecialSystems/Engines/TestCenter.cs b/Scripts/SpecialSystems/Engines/TestCenter.cs index 588790ef5..075256a09 100644 --- a/Scripts/SpecialSystems/Engines/TestCenter.cs +++ b/Scripts/SpecialSystems/Engines/TestCenter.cs @@ -121,13 +121,29 @@ namespace Server.Misc private static void ChangeSkill( Mobile from, string name, double value ) { SkillName index; - +#if Framework_4_0 if( !Enum.TryParse( name, true, out index ) || (!Core.SE && (int)index > 51) || (!Core.AOS && (int)index > 48) ) { from.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. return; } +#else + try + { + index = (SkillName)Enum.Parse( typeof( SkillName ), name, true ); + } + catch + { + from.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. + return; + } + if ( ( !Core.SE && (int)index > 51 ) || ( !Core.AOS && (int)index > 48 ) ) + { + from.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set. + return; + } +#endif Skill skill = from.Skills[index]; if ( skill != null ) diff --git a/Server/Body.cs b/Server/Body.cs index e2a7c7c0a..251d791fe 100644 --- a/Server/Body.cs +++ b/Server/Body.cs @@ -55,7 +55,7 @@ namespace Server continue; string[] split = line.Split( '\t' ); - +#if Framework_4_0 BodyType type; int bodyID; @@ -68,6 +68,21 @@ namespace Server Console.WriteLine( "Warning: Invalid bodyTable entry:" ); Console.WriteLine( line ); } +#else + try + { + int bodyID = int.Parse( split[0] ); + BodyType type = (BodyType)Enum.Parse( typeof( BodyType ), split[1], true ); + + if ( bodyID >= 0 && bodyID < m_Types.Length ) + m_Types[bodyID] = type; + } + catch + { + Console.WriteLine( "Warning: Invalid bodyTable entry:" ); + Console.WriteLine( line ); + } +#endif } } } diff --git a/Server/Main.cs b/Server/Main.cs index 48e500c6c..9692a9623 100644 --- a/Server/Main.cs +++ b/Server/Main.cs @@ -28,7 +28,9 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; +#if Framework_4_0 using System.Threading.Tasks; +#endif using Server; using Server.Accounting; @@ -110,7 +112,11 @@ namespace Server public static Thread Thread { get { return m_Thread; } } public static MultiTextWriter MultiConsoleOut { get { return m_MultiConOut; } } +#if Framework_4_0 public static readonly bool Is64Bit = Environment.Is64BitProcess; +#else + public static readonly bool Is64Bit = (IntPtr.Size == 8); //Returns the size for the current /process/ +#endif private static bool m_MultiProcessor; private static int m_ProcessorCount; @@ -662,10 +668,17 @@ namespace Server if( a == null ) return; +#if Framework_4_0 Parallel.ForEach(a.GetTypes(), t => { VerifyType(t); }); +#else + foreach (Type t in a.GetTypes()) + { + VerifyType(t); + } +#endif } } diff --git a/Server/Network/Listener.cs b/Server/Network/Listener.cs index 88ca8a690..593c94811 100644 --- a/Server/Network/Listener.cs +++ b/Server/Network/Listener.cs @@ -36,7 +36,11 @@ namespace Server.Network private Queue m_Accepted; private object m_AcceptedSyncRoot; +#if Framework_4_0 private SocketAsyncEventArgs m_EventArgs; +#else + private AsyncCallback m_OnAccept; +#endif private static Socket[] m_EmptySockets = new Socket[0]; @@ -59,9 +63,19 @@ namespace Server.Network DisplayListener(); +#if Framework_4_0 m_EventArgs = new SocketAsyncEventArgs(); m_EventArgs.Completed += new EventHandler( Accept_Completion ); Accept_Start(); +#else + m_OnAccept = new AsyncCallback( OnAccept ); + try { + IAsyncResult res = m_Listener.BeginAccept( m_OnAccept, m_Listener ); + } catch ( SocketException ex ) { + NetState.TraceException( ex ); + } catch ( ObjectDisposedException ) { + } +#endif } private Socket Bind( IPEndPoint ipep ) @@ -132,6 +146,7 @@ namespace Server.Network } } +#if Framework_4_0 private void Accept_Start() { bool result = false; @@ -169,6 +184,38 @@ namespace Server.Network e.AcceptSocket = null; } +#else + + private void OnAccept( IAsyncResult asyncResult ) { + Socket listener = (Socket) asyncResult.AsyncState; + + Socket accepted = null; + + try { + accepted = listener.EndAccept( asyncResult ); + } catch ( SocketException ex ) { + NetState.TraceException( ex ); + } catch ( ObjectDisposedException ) { + return; + } + + if ( accepted != null ) { + if ( VerifySocket( accepted ) ) { + Enqueue( accepted ); + } else { + Release( accepted ); + } + } + + try { + listener.BeginAccept( m_OnAccept, listener ); + } catch ( SocketException ex ) { + NetState.TraceException( ex ); + } catch ( ObjectDisposedException ) { + } + } +#endif + private bool VerifySocket( Socket socket ) { try { SocketConnectEventArgs args = new SocketConnectEventArgs( socket ); diff --git a/Server/Network/NetState.cs b/Server/Network/NetState.cs index b795e220e..299cdf957 100644 --- a/Server/Network/NetState.cs +++ b/Server/Network/NetState.cs @@ -51,7 +51,11 @@ namespace Server.Network { private bool m_Seeded; private bool m_Running; +#if Framework_4_0 private SocketAsyncEventArgs m_ReceiveEventArgs, m_SendEventArgs; +#else + private AsyncCallback m_OnReceive, m_OnSend; +#endif private MessagePump m_MessagePump; private ServerInfo[] m_ServerInfo; @@ -611,8 +615,17 @@ namespace Server.Network { } if ( gram != null ) { +#if Framework_4_0 m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length ); Send_Start(); +#else + try { + m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } +#endif } } catch ( CapacityExceededException ) { Console.WriteLine( "Client: {0}: Too much data pending, disconnecting...", this ); @@ -635,6 +648,7 @@ namespace Server.Network { } } +#if Framework_4_0 public void Start() { m_ReceiveEventArgs = new SocketAsyncEventArgs(); m_ReceiveEventArgs.Completed += new EventHandler( Receive_Completion ); @@ -810,6 +824,172 @@ namespace Server.Network { return false; } +#else + + public void Start() { + m_OnReceive = new AsyncCallback( OnReceive ); + m_OnSend = new AsyncCallback( OnSend ); + + m_Running = true; + + if ( m_Socket == null || m_Paused ) { + return; + } + + try { + lock ( m_AsyncLock ) { + if ( ( m_AsyncState & ( AsyncState.Pending | AsyncState.Paused ) ) == 0 ) { + InternalBeginReceive(); + } + } + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + + private void InternalBeginReceive() { + m_AsyncState |= AsyncState.Pending; + + m_Socket.BeginReceive( m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, m_OnReceive, m_Socket ); + } + + private void OnReceive( IAsyncResult asyncResult ) { + Socket s = (Socket)asyncResult.AsyncState; + + try { + int byteCount = s.EndReceive( asyncResult ); + + if ( byteCount > 0 ) { + m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); + + byte[] buffer = m_RecvBuffer; + + if ( m_Encoder != null ) + m_Encoder.DecodeIncomingPacket( this, ref buffer, ref byteCount ); + + lock ( m_Buffer ) + m_Buffer.Enqueue( buffer, 0, byteCount ); + + m_MessagePump.OnReceive( this ); + + lock ( m_AsyncLock ) { + m_AsyncState &= ~AsyncState.Pending; + + if ( ( m_AsyncState & AsyncState.Paused ) == 0 ) { + try { + InternalBeginReceive(); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + } + } else { + Dispose( false ); + } + } catch { + Dispose( false ); + } + } + + private void OnSend( IAsyncResult asyncResult ) { + Socket s = (Socket)asyncResult.AsyncState; + + try { + int bytes = s.EndSend( asyncResult ); + + if ( bytes <= 0 ) { + Dispose( false ); + return; + } + + m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); + + if ( m_CoalesceSleep >= 0 ) { + Thread.Sleep( m_CoalesceSleep ); + } + + SendQueue.Gram gram; + + lock ( m_SendQueue ) { + gram = m_SendQueue.Dequeue(); + } + + if ( gram != null ) { + try { + s.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s ); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + } catch ( Exception ){ + Dispose( false ); + } + } + + public static void Pause() { + m_Paused = true; + + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState |= AsyncState.Paused; + } + } + } + + public static void Resume() { + m_Paused = false; + + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + if ( ns.m_Socket == null ) { + continue; + } + + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState &= ~AsyncState.Paused; + + try { + if ( ( ns.m_AsyncState & AsyncState.Pending ) == 0 ) + ns.InternalBeginReceive(); + } catch ( Exception ex ) { + TraceException( ex ); + ns.Dispose( false ); + } + } + } + } + + public bool Flush() { + if ( m_Socket == null || !m_SendQueue.IsFlushReady ) { + return false; + } + + SendQueue.Gram gram; + + lock ( m_SendQueue ) { + gram = m_SendQueue.CheckFlushReady(); + } + + if ( gram != null ) { + try { + m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); + return true; + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + + return false; + } +#endif + public PacketHandler GetHandler( int packetID ) { if ( ContainerGridLines ) @@ -908,8 +1088,13 @@ namespace Server.Network { m_Buffer = null; m_RecvBuffer = null; +#if Framework_4_0 m_ReceiveEventArgs = null; m_SendEventArgs = null; +#else + m_OnReceive = null; + m_OnSend = null; +#endif m_Running = false; diff --git a/Server/Persistence/DynamicSaveStrategy.cs b/Server/Persistence/DynamicSaveStrategy.cs index 44227194f..c5a9c5386 100644 --- a/Server/Persistence/DynamicSaveStrategy.cs +++ b/Server/Persistence/DynamicSaveStrategy.cs @@ -18,6 +18,8 @@ * ***************************************************************************/ +#if Framework_4_0 + using System; using System.Collections.Generic; using System.Text; @@ -308,4 +310,5 @@ namespace Server } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Server/Persistence/SaveStrategy.cs b/Server/Persistence/SaveStrategy.cs index 765f3d32c..6d91da9b7 100644 --- a/Server/Persistence/SaveStrategy.cs +++ b/Server/Persistence/SaveStrategy.cs @@ -31,10 +31,13 @@ namespace Server { int processorCount = Core.ProcessorCount; - //TODO: Upon realworld verification of DynamicSaveStrategy, change this method around. if (processorCount > 16) { +#if Framework_4_0 return new DynamicSaveStrategy(); +#else + return new ParallelSaveStrategy(processorCount); +#endif } else { diff --git a/Server/Region.cs b/Server/Region.cs index 6d7bc10b9..1359a8f75 100644 --- a/Server/Region.cs +++ b/Server/Region.cs @@ -1137,7 +1137,7 @@ namespace Server if ( s == null ) return false; - +#if Framework_4_0 Type type = typeof(T); T tempVal; @@ -1151,6 +1151,19 @@ namespace Server Console.WriteLine( "Could not parse {0} enum attribute '{1}' in element '{2}'", type, attribute, xml.Name ); return false; } +#else + try + { + value = (T)Enum.Parse(type, s, true); + } + catch + { + Console.WriteLine( "Could not parse {0} enum attribute '{1}' in element '{2}'", type, attribute, xml.Name ); + return false; + } + + return true; +#endif } public static bool ReadMap( XmlElement xml, string attribute, ref Map value ) diff --git a/Server/ScriptCompiler.cs b/Server/ScriptCompiler.cs index 01e4f47f9..d9667b111 100644 --- a/Server/ScriptCompiler.cs +++ b/Server/ScriptCompiler.cs @@ -86,16 +86,17 @@ namespace Server AppendCompilerOption( ref sb, "/optimize" ); #if MONO - AppendDefine( ref sb, "/d:MONO" ); + AppendCompilerOption( ref sb, "/d:MONO" ); #endif - //These following defines are legacy, ie, depreciated. + //These two defines are legacy, ie, depreciated. if( Core.Is64Bit ) AppendCompilerOption( ref sb, "/d:x64" ); AppendCompilerOption( ref sb, "/d:Framework_2_0" ); - +#if Framework_4_0 AppendCompilerOption( ref sb, "/d:Framework_4_0" ); +#endif return (sb == null ? null : sb.ToString()); } diff --git a/Server/Serialization.cs b/Server/Serialization.cs index 6d8e16363..200ee4baa 100644 --- a/Server/Serialization.cs +++ b/Server/Serialization.cs @@ -38,7 +38,9 @@ namespace Server public abstract string ReadString(); public abstract DateTime ReadDateTime(); +#if Framework_4_0 public abstract DateTimeOffset ReadDateTimeOffset(); +#endif public abstract TimeSpan ReadTimeSpan(); public abstract DateTime ReadDeltaTime(); public abstract decimal ReadDecimal(); @@ -83,7 +85,7 @@ namespace Server public abstract List ReadStrongGuildList(); public abstract List ReadStrongGuildList() where T : BaseGuild; - +#if Framework_4_0 public abstract HashSet ReadItemSet(); public abstract HashSet ReadItemSet() where T: Item; @@ -92,7 +94,7 @@ namespace Server public abstract HashSet ReadGuildSet(); public abstract HashSet ReadGuildSet() where T : BaseGuild; - +#endif public abstract Race ReadRace(); public abstract bool End(); @@ -108,7 +110,9 @@ namespace Server public abstract void Write( string value ); public abstract void Write( DateTime value ); +#if Framework_4_0 public abstract void Write( DateTimeOffset value ); +#endif public abstract void Write( TimeSpan value ); public abstract void Write( decimal value ); public abstract void Write( long value ); @@ -158,37 +162,37 @@ namespace Server public abstract void WriteItemList( List list ) where T : Item; public abstract void WriteItemList( List list, bool tidy ) where T : Item; - +#if Framework_4_0 public abstract void Write( HashSet list ); public abstract void Write( HashSet list, bool tidy ); public abstract void WriteItemSet( HashSet set ) where T : Item; public abstract void WriteItemSet( HashSet set, bool tidy ) where T : Item; - +#endif public abstract void Write( List list ); public abstract void Write( List list, bool tidy ); public abstract void WriteMobileList( List list ) where T : Mobile; public abstract void WriteMobileList( List list, bool tidy ) where T : Mobile; - +#if Framework_4_0 public abstract void Write( HashSet list ); public abstract void Write( HashSet list, bool tidy ); public abstract void WriteMobileSet( HashSet set ) where T : Mobile; public abstract void WriteMobileSet( HashSet set, bool tidy ) where T : Mobile; - +#endif public abstract void Write( List list ); public abstract void Write( List list, bool tidy ); public abstract void WriteGuildList( List list ) where T : BaseGuild; public abstract void WriteGuildList( List list, bool tidy ) where T : BaseGuild; - +#if Framework_4_0 public abstract void Write( HashSet list ); public abstract void Write( HashSet list, bool tidy ); public abstract void WriteGuildSet( HashSet set ) where T : BaseGuild; public abstract void WriteGuildSet( HashSet set, bool tidy ) where T : BaseGuild; - +#endif //Stupid compiler won't notice there 'where' to differentiate the generic methods. } @@ -365,13 +369,13 @@ namespace Server { Write( value.Ticks ); } - +#if Framework_4_0 public override void Write( DateTimeOffset value ) { Write( value.Ticks ); Write( value.Offset.Ticks ); } - +#endif public override void WriteDeltaTime( DateTime value ) { long ticks = value.Ticks; @@ -732,7 +736,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -770,7 +774,7 @@ namespace Server Write( item ); } } - +#endif public override void Write( List list ) { Write( list, false ); @@ -816,7 +820,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -854,7 +858,7 @@ namespace Server Write( mob ); } } - +#endif public override void Write( List list ) { Write( list, false ); @@ -900,7 +904,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -938,6 +942,7 @@ namespace Server Write( guild ); } } +#endif } public sealed class BinaryFileReader : GenericReader @@ -1010,7 +1015,7 @@ namespace Server { return new DateTime( m_File.ReadInt64() ); } - +#if Framework_4_0 public override DateTimeOffset ReadDateTimeOffset() { long ticks = m_File.ReadInt64(); @@ -1018,7 +1023,7 @@ namespace Server return new DateTimeOffset( ticks, offset ); } - +#endif public override TimeSpan ReadTimeSpan() { return new TimeSpan( m_File.ReadInt64() ); @@ -1232,7 +1237,7 @@ namespace Server return new List(); } } - +#if Framework_4_0 public override HashSet ReadItemSet() { return ReadItemSet(); @@ -1263,7 +1268,7 @@ namespace Server return new HashSet(); } } - +#endif public override List ReadStrongMobileList() { return ReadStrongMobileList(); @@ -1289,7 +1294,7 @@ namespace Server return new List(); } } - +#if Framework_4_0 public override HashSet ReadMobileSet() { return ReadMobileSet(); @@ -1320,7 +1325,7 @@ namespace Server return new HashSet(); } } - +#endif public override List ReadStrongGuildList() { return ReadStrongGuildList(); @@ -1346,7 +1351,7 @@ namespace Server return new List(); } } - +#if Framework_4_0 public override HashSet ReadGuildSet() { return ReadGuildSet(); @@ -1377,7 +1382,7 @@ namespace Server return new HashSet(); } } - +#endif public override Race ReadRace() { return Race.Races[ReadByte()]; @@ -1559,14 +1564,14 @@ namespace Server m_Bin.Write( value.Ticks ); OnWrite(); } - +#if Framework_4_0 public override void Write( DateTimeOffset value ) { m_Bin.Write( value.Ticks ); m_Bin.Write( value.Offset.Ticks ); OnWrite(); } - +#endif public override void Write( TimeSpan value ) { m_Bin.Write( value.Ticks ); @@ -1859,7 +1864,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -1897,7 +1902,7 @@ namespace Server Write( item ); } } - +#endif public override void Write( List list ) { Write( list, false ); @@ -1943,7 +1948,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -1981,7 +1986,7 @@ namespace Server Write( mob ); } } - +#endif public override void Write( List list ) { Write( list, false ); @@ -2027,7 +2032,7 @@ namespace Server for( int i = 0; i < list.Count; ++i ) Write( list[i] ); } - +#if Framework_4_0 public override void Write( HashSet set ) { Write( set, false ); @@ -2065,6 +2070,7 @@ namespace Server Write( guild ); } } +#endif } public interface ISerializable diff --git a/Server/Utility.cs b/Server/Utility.cs index e9132bd6f..5299e6fe6 100644 --- a/Server/Utility.cs +++ b/Server/Utility.cs @@ -554,7 +554,7 @@ namespace Server return defaultValue; } } - +#if Framework_4_0 public static DateTimeOffset GetXMLDateTimeOffset( string dateTimeOffsetString, DateTimeOffset defaultValue ) { try @@ -571,7 +571,7 @@ namespace Server return defaultValue; } } - +#endif public static TimeSpan GetXMLTimeSpan( string timeSpanString, TimeSpan defaultValue ) { try diff --git a/Server/World.cs b/Server/World.cs index 41534dfcb..e8ad5384d 100644 --- a/Server/World.cs +++ b/Server/World.cs @@ -287,7 +287,7 @@ namespace Server { } private static readonly Type[] m_SerialTypeArray = new Type[1] { typeof(Serial) }; - +#if Framework_4_0 private static List> ReadTypes( BinaryReader tdbReader ) { int count = tdbReader.ReadInt32(); @@ -667,6 +667,387 @@ namespace Server { Console.WriteLine( "done ({1} items, {2} mobiles) ({0:F2} seconds)", watch.Elapsed.TotalSeconds, m_Items.Count, m_Mobiles.Count ); } +#else + private static List ReadTypes( BinaryReader tdbReader ) + { + int count = tdbReader.ReadInt32(); + + List types = new List(count); + + for (int i = 0; i < count; ++i) + { + string typeName = tdbReader.ReadString(); + + Type t = ScriptCompiler.FindTypeByFullName(typeName); + + if (t == null) + { + Console.WriteLine("failed"); + + if (!Core.Service) + { + Console.WriteLine("Error: Type '{0}' was not found. Delete all of those types? (y/n)", typeName); + + if (Console.ReadKey(true).Key == ConsoleKey.Y) + { + types.Add(null); + Console.Write("World: Loading..."); + continue; + } + + Console.WriteLine("Types will not be deleted. An exception will be thrown."); + } + else + { + Console.WriteLine("Error: Type '{0}' was not found.", typeName); + } + + throw new Exception(String.Format("Bad type '{0}'", typeName)); + } + + ConstructorInfo ctor = t.GetConstructor(m_SerialTypeArray); + + if (ctor != null) + { + types.Add(new object[] { ctor, typeName }); + } + else + { + throw new Exception(String.Format("Type '{0}' does not have a serialization constructor", t)); + } + } + + return types; + } + + public static void Load() { + if ( m_Loaded ) + return; + + m_Loaded = true; + m_LoadingType = null; + + Console.Write( "World: Loading..." ); + + Stopwatch watch = Stopwatch.StartNew(); + + m_Loading = true; + + _addQueue = new Queue(); + _deleteQueue = new Queue(); + + int mobileCount = 0, itemCount = 0, guildCount = 0; + + object[] ctorArgs = new object[1]; + + List items = new List(); + List mobiles = new List(); + List guilds = new List(); + + if ( File.Exists( MobileIndexPath ) && File.Exists( MobileTypesPath ) ) { + using ( FileStream idx = new FileStream( MobileIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryReader idxReader = new BinaryReader( idx ); + + using ( FileStream tdb = new FileStream( MobileTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryReader tdbReader = new BinaryReader( tdb ); + + List types = ReadTypes( tdbReader ); + + mobileCount = idxReader.ReadInt32(); + + m_Mobiles = new Dictionary( mobileCount ); + + for ( int i = 0; i < mobileCount; ++i ) { + int typeID = idxReader.ReadInt32(); + int serial = idxReader.ReadInt32(); + long pos = idxReader.ReadInt64(); + int length = idxReader.ReadInt32(); + + object[] objs = types[typeID]; + + if ( objs == null ) + continue; + + Mobile m = null; + ConstructorInfo ctor = ( ConstructorInfo ) objs[0]; + string typeName = ( string ) objs[1]; + + try { + ctorArgs[0] = ( Serial ) serial; + m = ( Mobile ) ( ctor.Invoke( ctorArgs ) ); + } catch { + } + + if ( m != null ) { + mobiles.Add( new MobileEntry( m, typeID, typeName, pos, length ) ); + AddMobile( m ); + } + } + + tdbReader.Close(); + } + + idxReader.Close(); + } + } else { + m_Mobiles = new Dictionary(); + } + + if ( File.Exists( ItemIndexPath ) && File.Exists( ItemTypesPath ) ) { + using ( FileStream idx = new FileStream( ItemIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryReader idxReader = new BinaryReader( idx ); + + using ( FileStream tdb = new FileStream( ItemTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryReader tdbReader = new BinaryReader( tdb ); + + List types = ReadTypes( tdbReader ); + + itemCount = idxReader.ReadInt32(); + + m_Items = new Dictionary( itemCount ); + + for ( int i = 0; i < itemCount; ++i ) { + int typeID = idxReader.ReadInt32(); + int serial = idxReader.ReadInt32(); + long pos = idxReader.ReadInt64(); + int length = idxReader.ReadInt32(); + + object[] objs = types[typeID]; + + if ( objs == null ) + continue; + + Item item = null; + ConstructorInfo ctor = ( ConstructorInfo ) objs[0]; + string typeName = ( string ) objs[1]; + + try { + ctorArgs[0] = ( Serial ) serial; + item = ( Item ) ( ctor.Invoke( ctorArgs ) ); + } catch { + } + + if ( item != null ) { + items.Add( new ItemEntry( item, typeID, typeName, pos, length ) ); + AddItem( item ); + } + } + + tdbReader.Close(); + } + + idxReader.Close(); + } + } else { + m_Items = new Dictionary(); + } + + if ( File.Exists( GuildIndexPath ) ) { + using ( FileStream idx = new FileStream( GuildIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryReader idxReader = new BinaryReader( idx ); + + guildCount = idxReader.ReadInt32(); + + CreateGuildEventArgs createEventArgs = new CreateGuildEventArgs( -1 ); + for ( int i = 0; i < guildCount; ++i ) { + idxReader.ReadInt32();//no typeid for guilds + int id = idxReader.ReadInt32(); + long pos = idxReader.ReadInt64(); + int length = idxReader.ReadInt32(); + + createEventArgs.Id = id; + BaseGuild guild = EventSink.InvokeCreateGuild( createEventArgs ); + if ( guild != null ) + guilds.Add( new GuildEntry( guild, pos, length ) ); + } + + idxReader.Close(); + } + } + + bool failedMobiles = false, failedItems = false, failedGuilds = false; + Type failedType = null; + Serial failedSerial = Serial.Zero; + Exception failed = null; + int failedTypeID = 0; + + if ( File.Exists( MobileDataPath ) ) { + using ( FileStream bin = new FileStream( MobileDataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryFileReader reader = new BinaryFileReader( new BinaryReader( bin ) ); + + for ( int i = 0; i < mobiles.Count; ++i ) { + MobileEntry entry = mobiles[i]; + Mobile m = entry.Mobile; + + if ( m != null ) { + reader.Seek( entry.Position, SeekOrigin.Begin ); + + try { + m_LoadingType = entry.TypeName; + m.Deserialize( reader ); + + if ( reader.Position != ( entry.Position + entry.Length ) ) + throw new Exception( String.Format( "***** Bad serialize on {0} *****", m.GetType() ) ); + } catch ( Exception e ) { + mobiles.RemoveAt( i ); + + failed = e; + failedMobiles = true; + failedType = m.GetType(); + failedTypeID = entry.TypeID; + failedSerial = m.Serial; + + break; + } + } + } + + reader.Close(); + } + } + + if ( !failedMobiles && File.Exists( ItemDataPath ) ) { + using ( FileStream bin = new FileStream( ItemDataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryFileReader reader = new BinaryFileReader( new BinaryReader( bin ) ); + + for ( int i = 0; i < items.Count; ++i ) { + ItemEntry entry = items[i]; + Item item = entry.Item; + + if ( item != null ) { + reader.Seek( entry.Position, SeekOrigin.Begin ); + + try { + m_LoadingType = entry.TypeName; + item.Deserialize( reader ); + + if ( reader.Position != ( entry.Position + entry.Length ) ) + throw new Exception( String.Format( "***** Bad serialize on {0} *****", item.GetType() ) ); + } catch ( Exception e ) { + items.RemoveAt( i ); + + failed = e; + failedItems = true; + failedType = item.GetType(); + failedTypeID = entry.TypeID; + failedSerial = item.Serial; + + break; + } + } + } + + reader.Close(); + } + } + + m_LoadingType = null; + + if ( !failedMobiles && !failedItems && File.Exists( GuildDataPath ) ) { + using ( FileStream bin = new FileStream( GuildDataPath, FileMode.Open, FileAccess.Read, FileShare.Read ) ) { + BinaryFileReader reader = new BinaryFileReader( new BinaryReader( bin ) ); + + for ( int i = 0; i < guilds.Count; ++i ) { + GuildEntry entry = guilds[i]; + BaseGuild g = entry.Guild; + + if ( g != null ) { + reader.Seek( entry.Position, SeekOrigin.Begin ); + + try { + g.Deserialize( reader ); + + if ( reader.Position != ( entry.Position + entry.Length ) ) + throw new Exception( String.Format( "***** Bad serialize on Guild {0} *****", g.Id ) ); + } catch ( Exception e ) { + guilds.RemoveAt( i ); + + failed = e; + failedGuilds = true; + failedType = typeof( BaseGuild ); + failedTypeID = g.Id; + failedSerial = g.Id; + + break; + } + } + } + + reader.Close(); + } + } + + if ( failedItems || failedMobiles || failedGuilds ) { + Console.WriteLine( "An error was encountered while loading a saved object" ); + + Console.WriteLine( " - Type: {0}", failedType ); + Console.WriteLine( " - Serial: {0}", failedSerial ); + + if ( !Core.Service ) { + Console.WriteLine( "Delete the object? (y/n)" ); + + if ( Console.ReadKey( true ).Key == ConsoleKey.Y ) { + if ( failedType != typeof( BaseGuild ) ) { + Console.WriteLine( "Delete all objects of that type? (y/n)" ); + + if ( Console.ReadKey( true ).Key == ConsoleKey.Y ) { + if ( failedMobiles ) { + for ( int i = 0; i < mobiles.Count; ) { + if ( mobiles[i].TypeID == failedTypeID ) + mobiles.RemoveAt( i ); + else + ++i; + } + } else if ( failedItems ) { + for ( int i = 0; i < items.Count; ) { + if ( items[i].TypeID == failedTypeID ) + items.RemoveAt( i ); + else + ++i; + } + } + } + } + + SaveIndex( mobiles, MobileIndexPath ); + SaveIndex( items, ItemIndexPath ); + SaveIndex( guilds, GuildIndexPath ); + } + + Console.WriteLine( "After pressing return an exception will be thrown and the server will terminate." ); + Console.ReadLine(); + } else { + Console.WriteLine( "An exception will be thrown and the server will terminate." ); + } + + throw new Exception( String.Format( "Load failed (items={0}, mobiles={1}, guilds={2}, type={3}, serial={4})", failedItems, failedMobiles, failedGuilds, failedType, failedSerial ), failed ); + } + + EventSink.InvokeWorldLoad(); + + m_Loading = false; + + ProcessSafetyQueues(); + + foreach ( Item item in m_Items.Values ) { + if ( item.Parent == null ) + item.UpdateTotals(); + + item.ClearProperties(); + } + + foreach ( Mobile m in m_Mobiles.Values ) { + m.UpdateRegion(); // Is this really needed? + m.UpdateTotals(); + + m.ClearProperties(); + } + + watch.Stop(); + + Console.WriteLine( "done ({1} items, {2} mobiles) ({0:F2} seconds)", watch.Elapsed.TotalSeconds, m_Items.Count, m_Mobiles.Count ); + } +#endif private static void ProcessSafetyQueues() { while ( _addQueue.Count > 0 ) {