RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[RUO 2.0 F+] Complete Automated Web-Accounting Service V2.0.1

Zaphieon

Wanderer
Warning: mysql_fetch_array() [function.mysql-fetch-array]: The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH. in \webaccounting\Internal\WAConfig.php on line 225

Code:
	for($foo = 0; $row = mysql_fetch_array($Result[COLOR="Red"],$database[/COLOR]); $foo /// line 225

remove the red portion of the code. that will fix the above posters issue.. or you would have to define $database as a constant - MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH


though I am still having issues with it locating the web_accounts table.
Code:
  Table 'web_accounts' Not found! - I Will Create It...
  I have failed to create the Table 'web_accounts'...
  Table 'web_accounts' already exists

maybe i am missing something
 

Zaphieon

Wanderer
Vorspire;765849 said:
i have updated the first post with the new PHP

works great.. still had to remove that small section from line 225.. also the part where you have..

//Admin E-Mail Address
//
define("ADMIN_EMAIL_ADDR", "[email protected]");

//Admin E-Mail Address Name
//
define("ADMIN_EMAIL_NAME", "");

if you put anything in the admin email name it fubars my smtp becuase it adds it onto the email address for some reason.
 

Zaphieon

Wanderer
quick question before i leave my office lol.. does this port over all the accounts already on the server are do you start a new?
 

Vorspire

Knight
php mail() function uses this format:

Code:
ADMIN_EMAIL_ADDR - ADMIN_EMAIL_NAME

when sending e-mails, because mail-servers should be capable of identifying the NAME after the dash '-' for the From header... This is so that e-mails show up in your inbox as the NAME instead of just the EMAIL :)
 

Zaphieon

Wanderer
Vorspire;765862 said:
php mail() function uses this format:

Code:
ADMIN_EMAIL_ADDR - ADMIN_EMAIL_NAME

when sending e-mails, because mail-servers should be capable of identifying the NAME after the dash '-' for the From header... This is so that e-mails show up in your inbox as the NAME instead of just the EMAIL :)

aye I understand that. Ill see if i cant play with it a bit to get it to work with my php version.
 

LordHogFred

Knight
First of all awesome system dude, will make my life so much easier :p.

Just one question though, is it possible to make the accounts synchronize at regular intervals that aren't world saves? I have my world saves 4 hours apart but I'd like to synchronize the accounts every 10 mins or so, is there a way to do this or does it rely on the save function?

Thanks :),


EDIT: Hmm, it doesn't seem to be importing the accounts in from UO properly. Any ideas?
 

Vorspire

Knight
It should work in a way that, if both WorldLoad and worldSave are set to false, it will use a timer to update every 10 minutes.

Also, what you will need to do is take out the "World.Save" line in the SynchronizeDatabase
() method at the bottom of WebAccounting.cs

As for not importing accounts properly, check that the "state" of the account is correct, if the account is in-game, but isn't in your mysql database, then it should automatically insert it into the database and vice-versa.
 

LordHogFred

Knight
Vorspire;767143 said:
It should work in a way that, if both WorldLoad and worldSave are set to false, it will use a timer to update every 10 minutes.

Also, what you will need to do is take out the "World.Save" line in the SynchronizeDatabase
() method at the bottom of WebAccounting.cs

As for not importing accounts properly, check that the "state" of the account is correct, if the account is in-game, but isn't in your mysql database, then it should automatically insert it into the database and vice-versa.

Awesome thanks, I've altered it to update every 10 mins and on World Save now :).

As for the accounts, it doesn't seem to be reading any accounts from the game to the database. It inserts them fine but it doesn't work the other way :confused:. Any ideas?

Cheers :),
 

LordHogFred

Knight
Ok just a quick question, is anyone else having issues with this system not exporting accounts from the game to the database? I've spent the last couple of days trying to sort it out by trying different exporting methods and such but without any luck. Anyone else had any luck?

Cheers :),
 

jhs59

Sorceror
LordHogFred;767336 said:
Ok just a quick question, is anyone else having issues with this system not exporting accounts from the game to the database?

Yes, I am also having this problem. My shard pulls accounts down from the database correctly but it is not pushing them up to the database.

LordHogFred;767336 said:
Anyone else had any luck?

Nope!


Does anyone have any insight into the problem with is?
 

jhs59

Sorceror
Ok.. I think I've found an error message at least.

During my last database sync I received a message saying.

System.NullReferenceException: object reference not set to an instance of an object.
at Server.Accounting.WebAccounting.CreateAccountsFromUO() in WebAccounting.cs:line 199

This only happens when I create an account using WebAccounting and then delete the account in game. I wonder if it might have something to do with exporting existing accounts as well.

Here is my WebAccounting.cs file. I've marked like 199.

Code:
using System;
using System.Data.Odbc;
using System.Security;
using System.Security.Cryptography;
using System.Net;
using System.Collections;
using System.Xml;
using System.Text;
using Server;
using Server.Misc;
using Server.Network;
using Server.Commands;

namespace Server.Accounting
{
	public class WebAccounting
	{

		public enum Status
		{
			Void = 0,
			Pending = 1,
			Active = 2,
			PWChanged = 3,
			EmailChanged = 4,
			Delete = 5
		}

		private static int QueryCount = 0; //Offset 0 values.

		public static bool UpdateOnWorldSave = true;
		public static bool UpdateOnWorldLoad = true;

		private static string
			DatabaseDriver = WAConfig.DatabaseDriver,
			DatabaseServer = WAConfig.DatabaseServer,
			DatabaseName = WAConfig.DatabaseName,
			DatabaseTable = WAConfig.DatabaseTable,
			DatabaseUserID = WAConfig.DatabaseUserID,
			DatabasePassword = WAConfig.DatabasePassword;

		static string ConnectionString = string.Format( "DRIVER={0};SERVER={1};DATABASE={2};UID={3};PASSWORD={4};",
			DatabaseDriver, DatabaseServer, DatabaseName, DatabaseUserID, DatabasePassword );

		static bool Synchronizing = false;

		public static void Initialize( )
		{
			SynchronizeDatabase( );
			CommandSystem.Register( "AccSync", AccessLevel.Administrator, new CommandEventHandler( Sync_OnCommand ) );

			if( UpdateOnWorldLoad )
			{
				EventSink.WorldLoad += new WorldLoadEventHandler( OnLoaded );
			}

			if( UpdateOnWorldSave )
			{
				EventSink.WorldSave += new WorldSaveEventHandler( OnSaved );
			}
			else
			{
				Timer.DelayCall( TimeSpan.FromMinutes( 10.0 ), TimeSpan.FromMinutes( 10.0 ), new TimerCallback( SynchronizeDatabase ) );
			}
		}

		public static void OnSaved( WorldSaveEventArgs e )
		{
			if( Synchronizing )
				return;

			SynchronizeDatabase( );
		}

		public static void OnLoaded( )
		{
			if( Synchronizing )
				return;

			SynchronizeDatabase( );
		}

		[Usage( "AccSync" )]
		[Description( "Synchronizes the Accounts Database" )]
		public static void Sync_OnCommand( CommandEventArgs e )
		{
			if( Synchronizing )
				return;

			Mobile from = e.Mobile;

			SynchronizeDatabase( );
			from.SendMessage( "Done Synchronizing Database!" );
		}

		public static void CreateAccountsFromDB( )
		{
			//Console.WriteLine( "Getting New Accounts..." );
			try
			{
				ArrayList ToCreateFromDB = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name,password,email FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.Pending );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );
					string password = reader.GetString( 1 );
					string email = reader.GetString( 2 );

					if( Accounts.GetAccount( username ) == null )
						ToCreateFromDB.Add( Accounts.AddAccount( username, password, email ) );
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToCreateFromDB )
				{
					int ALevel = 0;

	[B][COLOR="Red"]199 ---->[/COLOR][/B]		   if( a.AccessLevel == AccessLevel.Player )
					{
						ALevel = 1;
					}
					else if( a.AccessLevel == AccessLevel.Counselor )
					{
						ALevel = 2;
					}
					else if( a.AccessLevel == AccessLevel.GameMaster )
					{
						ALevel = 3;
					}
					else if( a.AccessLevel == AccessLevel.Seer )
					{
						ALevel = 4;
					}
					else if( a.AccessLevel == AccessLevel.Administrator )
					{
						ALevel = 6;
					}

					QueryCount += 1;

					Command.CommandText = string.Format( "UPDATE {0} SET email='{1}',password='{2}',state='{3}',access='{4}' WHERE name='{5}'", DatabaseTable, a.Email, a.CryptPassword, ( int )Status.Active, ALevel, a.Username );
					Command.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} In-Game Accounts Created] ", ToCreateFromDB.Count );
			}
			catch( Exception e )
			{
				Console.WriteLine( "[In-Game Account Create] Error..." );
				Console.WriteLine( e );
			}
		}


		public static void CreateAccountsFromUO( )
		{
			//Console.WriteLine( "Exporting New Accounts..." );
			try
			{
				ArrayList ToCreateFromUO = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name FROM {0}", DatabaseTable );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );

					Account toCheck = Accounts.GetAccount( username ) as Account;

					if( toCheck == null )
						ToCreateFromUO.Add( toCheck );
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToCreateFromUO )
				{
					int ALevel = 0;

					if( a.AccessLevel == AccessLevel.Player )
					{
						ALevel = 1;
					}
					else if( a.AccessLevel == AccessLevel.Counselor )
					{
						ALevel = 2;
					}
					else if( a.AccessLevel == AccessLevel.GameMaster )
					{
						ALevel = 3;
					}
					else if( a.AccessLevel == AccessLevel.Seer )
					{
						ALevel = 4;
					}
					else if( a.AccessLevel == AccessLevel.Administrator )
					{
						ALevel = 6;
					}

					PasswordProtection PWMode = AccountHandler.ProtectPasswords;
					string Password = "";

					switch( PWMode )
					{
						case PasswordProtection.None: { Password = a.PlainPassword; } break;
						case PasswordProtection.Crypt: { Password = a.CryptPassword; } break;
						default: { Password = a.NewCryptPassword; } break;
					}

					QueryCount += 1;

					OdbcCommand InsertCommand = Connection.CreateCommand( );

					InsertCommand.CommandText = string.Format( "INSERT INTO {0} (name,password,email,access,timestamp,state) VALUES( '{1}', '{2}', '{3}', '{4}', '{5}', '{6}')", DatabaseTable, a.Username, Password, a.Email, ALevel, ToUnixTimestamp( a.Created ), ( int )Status.Active );
					InsertCommand.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} Database Accounts Added] ", ToCreateFromUO.Count );
			}
			catch( Exception e )
			{
				Console.WriteLine( "[Database Account Create] Error..." );
				Console.WriteLine( e );
			}
		}

		public static void UpdateUOPasswords( )
		{
			//Console.WriteLine( "Getting New Passwords..." );
			try
			{
				ArrayList ToUpdatePWFromDB = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name,password FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.PWChanged );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );
					string password = reader.GetString( 1 );

					Account AtoUpdate = Accounts.GetAccount( username ) as Account;

					if( AtoUpdate != null )
					{
						PasswordProtection PWMode = AccountHandler.ProtectPasswords;
						string Password = "";

						switch( PWMode )
						{
							case PasswordProtection.None: { Password = AtoUpdate.PlainPassword; } break;
							case PasswordProtection.Crypt: { Password = AtoUpdate.CryptPassword; } break;
							default: { Password = AtoUpdate.NewCryptPassword; } break;
						}

						if( Password == null || Password == "" || Password != password )
						{
							AtoUpdate.SetPassword( password );
							ToUpdatePWFromDB.Add( AtoUpdate );
						}
					}
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToUpdatePWFromDB )
				{
					PasswordProtection PWModeU = AccountHandler.ProtectPasswords;
					string PasswordU = "";

					switch( PWModeU )
					{
						case PasswordProtection.None: { PasswordU = a.PlainPassword; } break;
						case PasswordProtection.Crypt: { PasswordU = a.CryptPassword; } break;
						default: { PasswordU = a.NewCryptPassword; } break;
					}

					QueryCount += 1;

					Command.CommandText = string.Format( "UPDATE {0} SET state='{1}',password='{2}' WHERE name='{3}'", DatabaseTable, ( int )Status.Active, PasswordU, a.Username );
					Command.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} In-game Passwords Changed] ", ToUpdatePWFromDB.Count );
			}
			catch( System.Exception e )
			{
				Console.WriteLine( "[In-Game Password Change] Error..." );
				Console.WriteLine( e );
			}
		}

		public static void UpdateDBPasswords( )
		{
			//Console.WriteLine( "Exporting New Passwords..." );
			try
			{
				ArrayList ToUpdatePWFromUO = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name,password FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.Active );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );
					string password = reader.GetString( 1 );

					Account AtoUpdate = Accounts.GetAccount( username ) as Account;

					if( AtoUpdate != null )
					{
						PasswordProtection PWMode = AccountHandler.ProtectPasswords;
						string Password = "";

						switch( PWMode )
						{
							case PasswordProtection.None: { Password = AtoUpdate.PlainPassword; } break;
							case PasswordProtection.Crypt: { Password = AtoUpdate.CryptPassword; } break;
							default: { Password = AtoUpdate.NewCryptPassword; } break;
						}

						if( Password == null || Password == "" || Password != password )
						{
							ToUpdatePWFromUO.Add( AtoUpdate );
						}
					}
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToUpdatePWFromUO )
				{
					PasswordProtection PWModeU = AccountHandler.ProtectPasswords;
					string PasswordU = "";

					switch( PWModeU )
					{
						case PasswordProtection.None: { PasswordU = a.PlainPassword; } break;
						case PasswordProtection.Crypt: { PasswordU = a.CryptPassword; } break;
						default: { PasswordU = a.NewCryptPassword; } break;
					}

					QueryCount += 1;

					Command.CommandText = string.Format( "UPDATE {0} SET state='{1}',password='{2}' WHERE name='{3}'", DatabaseTable, ( int )Status.Active, PasswordU, a.Username );
					Command.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} Database Passwords Changed] ", ToUpdatePWFromUO.Count );
			}
			catch( Exception e )
			{
				Console.WriteLine( "[Database Password Change] Error..." );
				Console.WriteLine( e );
			}
		}



		public static void UpdateUOEmails( )
		{
			//Console.WriteLine( "Getting New Emails..." );
			try
			{
				ArrayList ToUpdateEmailFromDB = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name,email FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.EmailChanged );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );
					string email = reader.GetString( 1 );

					Account AtoUpdate = Accounts.GetAccount( username ) as Account;

					if( AtoUpdate != null && ( AtoUpdate.Email == null || AtoUpdate.Email == "" || AtoUpdate.Email != email ) )
					{
						AtoUpdate.Email = email;
						ToUpdateEmailFromDB.Add( AtoUpdate );
					}
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToUpdateEmailFromDB )
				{
					QueryCount += 1;

					Command.CommandText = string.Format( "UPDATE {0} SET state='{1}',email='{2}' WHERE name='{3}'", DatabaseTable, ( int )Status.Active, a.Email, a.Username );
					Command.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} In-Game Emails Changed] ", ToUpdateEmailFromDB.Count );
			}
			catch( System.Exception e )
			{
				Console.WriteLine( "[In-Game Email Change] Error..." );
				Console.WriteLine( e );
			}
		}

		public static void UpdateDBEmails( )
		{
			//Console.WriteLine( "Exporting New Emails..." );
			try
			{
				ArrayList ToUpdateEmailFromUO = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name,email FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.Active );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );
					string email = reader.GetString( 1 );

					Account AtoUpdate = Accounts.GetAccount( username ) as Account;

					if( AtoUpdate != null && ( AtoUpdate.Email == null || AtoUpdate.Email == "" || AtoUpdate.Email != email ) )
						ToUpdateEmailFromUO.Add( AtoUpdate );
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToUpdateEmailFromUO )
				{
					QueryCount += 1;

					Command.CommandText = string.Format( "UPDATE {0} SET state='{1}',email='{2}' WHERE name='{3}'", DatabaseTable, ( int )Status.Active, a.Email, a.Username );
					Command.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} Database Emails Changed] ", ToUpdateEmailFromUO.Count );
			}
			catch( Exception e )
			{
				Console.WriteLine( "[Database Email Change] Error..." );
				Console.WriteLine( e );
			}
		}

		public static void SynchronizeDatabase( )
		{
			if( Synchronizing || !WAConfig.Enabled )
				return;

			Synchronizing = true;

			Console.WriteLine( "Accounting System..." );

			CreateAccountsFromDB( );
			CreateAccountsFromUO( );

			UpdateUOEmails( );
			UpdateDBEmails( );

			UpdateUOPasswords( );
			UpdateDBPasswords( );

			Console.WriteLine( string.Format( "[Executed {0} Database Queries]", QueryCount.ToString( ) ) );

			QueryCount = 0;

			// World.Save( );

			Synchronizing = false;
		}

		static double ToUnixTimestamp( DateTime date )
		{
			DateTime origin = new DateTime( 1970, 1, 1, 0, 0, 0, 0 );

			TimeSpan diff = date - origin;

			return Math.Floor( diff.TotalSeconds );
		}


	}
}

I hope this report helps to figure out the problem.
 

Vorspire

Knight
Changed the line in red where == to !=

Code:
public static void CreateAccountsFromUO( )
		{
			//Console.WriteLine( "Exporting New Accounts..." );
			try
			{
				ArrayList ToCreateFromUO = new ArrayList( );
				OdbcConnection Connection = new OdbcConnection( ConnectionString );

				Connection.Open( );
				OdbcCommand Command = Connection.CreateCommand( );

				Command.CommandText = string.Format( "SELECT name FROM {0}", DatabaseTable );
				OdbcDataReader reader = Command.ExecuteReader( );

				QueryCount += 1;

				while( reader.Read( ) )
				{
					string username = reader.GetString( 0 );

					Account toCheck = Accounts.GetAccount( username ) as Account;

					[color=red]if( toCheck == null )[/color]
						ToCreateFromUO.Add( toCheck );
				}
				reader.Close( );

				//Console.WriteLine( "Updating Database..." );
				foreach( Account a in ToCreateFromUO )
				{
					int ALevel = 0;

					if( a.AccessLevel == AccessLevel.Player )
					{
						ALevel = 1;
					}
					else if( a.AccessLevel == AccessLevel.Counselor )
					{
						ALevel = 2;
					}
					else if( a.AccessLevel == AccessLevel.GameMaster )
					{
						ALevel = 3;
					}
					else if( a.AccessLevel == AccessLevel.Seer )
					{
						ALevel = 4;
					}
					else if( a.AccessLevel == AccessLevel.Administrator )
					{
						ALevel = 6;
					}

					PasswordProtection PWMode = AccountHandler.ProtectPasswords;
					string Password = "";

					switch( PWMode )
					{
						case PasswordProtection.None: { Password = a.PlainPassword; } break;
						case PasswordProtection.Crypt: { Password = a.CryptPassword; } break;
						default: { Password = a.NewCryptPassword; } break;
					}

					QueryCount += 1;

					OdbcCommand InsertCommand = Connection.CreateCommand( );

					InsertCommand.CommandText = string.Format( "INSERT INTO {0} (name,password,email,access,timestamp,state) VALUES( '{1}', '{2}', '{3}', '{4}', '{5}', '{6}')", DatabaseTable, a.Username, Password, a.Email, ALevel, ToUnixTimestamp( a.Created ), ( int )Status.Active );
					InsertCommand.ExecuteNonQuery( );
				}

				Connection.Close( );

				Console.WriteLine( "[{0} Database Accounts Added] ", ToCreateFromUO.Count );
			}
			catch( Exception e )
			{
				Console.WriteLine( "[Database Account Create] Error..." );
				Console.WriteLine( e );
			}
		}
 

jhs59

Sorceror
StrikeIII;767459 said:
heh, good work, but could be better

Seriously unnecessary comment...

Anyway...

I tried Vorspire's fix above and it gets rid of that error I was having. The thing is, now when the shard connects to the database it creates a duplicate account every single time when it syncs up.

Still doesn't add accounts that were already in game, though.
 

Vorspire

Knight
TBH, he's right in a way, it really could be better... Thanks for the support and constructive critisism.

I am currently working on a 3.0.0.0 Version that should be ready for release soon.

It will have full in-game administration, so you won't have to edit your WAConfig anymore...

I've already upgraded the main database connection algorithms to be less resource-intense and to be much more stable than the system currently is.

I will also release a new Front-End (WebSite) both in ASP.NET/Ajax and PHP to interact with the database.

This version should be fully upgrade compatible, but it will be posted in a seperate thread.

Once again, thanks to all who have supported this project!

Regards
 

Attachments

  • WAManager.jpg
    WAManager.jpg
    127 KB · Views: 182

LordHogFred

Knight
Vorspire;767595 said:
TBH, he's right in a way, it really could be better... Thanks for the support and constructive critisism.

I am currently working on a 3.0.0.0 Version that should be ready for release soon.

It will have full in-game administration, so you won't have to edit your WAConfig anymore...

I've already upgraded the main database connection algorithms to be less resource-intense and to be much more stable than the system currently is.

I will also release a new Front-End (WebSite) both in ASP.NET/Ajax and PHP to interact with the database.

This version should be fully upgrade compatible, but it will be posted in a seperate thread.

Once again, thanks to all who have supported this project!

Regards

Fantastic, I look forward to it :D.
 
Top