mem.dll (nude) + MySQL Support
by KingTomato

About:

	Basically, I'm working on this project to improve Tribes and its
	functionality. The basis of the project is to include MySQL support
	in to the game. Why? Simply to give it more flexibility.

	Think of it in terms of what you could do to tribes if you had a
	global server storing multiple aspects to the game. Things such as
	client logins, player stats, event logging, and more. Furthermore,
	all those aspects could be changed not only via a single query to a
	global server, but managed from a web server AND retrieved from
	queries made by the client.
	
	Some ideas:
	- Web integrated admin control
		Add, remove, change passwords/levels all by the web for your
		admins in game.
	- Advanced logging
		Server events can be logged to a MySQL server not only for ease
		on the server (as far as load) but think about how easy it'd be
		to search for an event by time/date.
	- IP storing and searching (clone scaning)
		Imagine a central server with the IPs of users from various
		servers. From here, you can add user clones and the server last
		joined in to the database, as well as search IPs by range (i.e.
		127.0.*.*), or all user ips relating to "KingTomato".

Thanks to:

	Andrew (http://www.team5150.com/~andrew/)
	
Included:

	mem.dll
	libmysql.dll
	readme.txt
	
Installation:

	Copy mem.dll and libmysql.dll to \dynamix\tribes directory and viola.
	When tribes loads, you should see a message in the console statting:
	
		mem.dll(nude) loaded
		- MySQL plugin loaded
		
Functions List (LISTED ALPHABETICALLY (order changed below)):

	MySQL::Close(ref_name);
	MySQL::Connect(ref_name,host,user,pass,db);
	MySQL::Create(ref_name);
	MySQL::Destroy(ref_name);
	MySQL::Escape(query);
	MySQL::Fetch(ref_name,column_name_or_id);
	MySQL::FetchRow(ref_name);
	MySQL::Find(ref_name);							(Disabled for now)
	MySQL::Query(ref_name,query);
	MySQL::Rows(ref_name);
	MySQL::Unescape(query);
		
How to use (listed by order they should appear in script):

	MySQL::Create(ref_name);
	
		Must be called above all functions. This will create a place on the
		stack to handle your new connection. ref_name is the name you would
		like to assign your connection (can be foo, bar, stats, whatever) up
		to 25 characters (the dll will limit length when created). Keep in
		mind when the dll does add the connection id, it is stored in lowercase
		form. This means a connection with the name "foo" and "FOO" are
		identical when being referenced.
		
		Return:
		
			true	Connection identifier was created
			false	Connection identifier could not be made (check console)
			
	MySQL::Connect(ref_name,host,user,pass,db);
	
		This will take the new connection id and assign it a connection to
		the MySQL server. Host is the server to connect to (could be localhost,
		sql.server.com, or 127.0.0.1), user and passwords should be self-
		explainitory, and db is the name of the database to connect to (saves
		you from having to perform a select_db).
		
		Returns:
		
			true	Connection established, no problems (a success message is
					echoed to the console to prevent concealed queries)
			false	Could not connect to the server (check $MySQL::Error for
					possible reasons). If MySQL::Error returns empty, the
					connection id is bad (see console).
					
	MySQL::Escape(string);
	MySQL::Unescape(string);
	
		These are functions to provide [un]escaping means for query items. MySQL dislikes
		it when you insert text with quotes (for instance) in a text field, so the first
		function will escape the string. Likewise, when retrieving the data, you need to
		remove this excess meta-data. So to do this, use Unescape.
		
		Replaced items:
			Unescaped:		Escaped:
			\				\\
			\n				\\n
			\r				\\r
			'				\'
			"				\"
			
		Returns:
			Formatted string 
	
	MySQL::Find(ref_name);
	
		Verifies a connection is created. NOTE; This is not implimented in this version,
		but I may re-add it later.
		
		Returns:
		
			true	Connection id found
			false	No connection id with the name specified
			
	MySQL::Query(ref_name,query);
	
		Queries the database and returns the result of the query. $MySQL::Error
		will be present for any kind of error MySQL-related. If it's empty however,
		the error is concerning a bad connection id, missing connection (didn't
		use MySQL::Connect), etc. (see console).
		
		Returns:
			true	Query went well, no errors
			false	with $MySQL::Error - MySQL syntax error
					without $MySQL::Error - Bad id, connection, or missing argument
					
	MySQL::Rows(ref_name);
	
		Returns how many rows were affected in the last query (albeit a SELECT,
		DELETE, UPDATE, etc.)
		
		Returns:
			-4	Missing arguments
			-3	Bad connection id
			-2	No query open
			-1	MySQL not connected
			0+	Number of rows affected
			
	MySQL::FetchRow(ref_name);
	
		Retrieves a row from the query (assuming one is there to grab) allowing
		you to then use MySQL::Fetch(...) to grab a column's information. This
		must be called before you can fetch any kind of information from a row,
		and must then be called every time you want to change rows.
		
		Returns:
		
			true	The fetch was a success
			false	for most errors, $MySQL::Error will return the problem. The
					only exceptions are a missing arguments error (shown in console)
					or when you've reached the end of the results.
					
	MySQL::Fetch(ref_name,column_name_or_id);
	
		After calling MySQL::FetchRow, this will return a row's column information
		either by reference name (name of the column) or by a numeric id (the Nth
		column resulted).
		
		Return:
		
			string	Result of the information in the column (value)
			false	An error occured while trying to grab the column (check
					the $MySQL:Error variable)
					
	MySQL::Close(ref_name);
	
		Called when all is said and done. This performs a clean up on the
		connection and disconnects the link between the game and the MySQL
		server.
		
		Return:
		
			true	Closed the connection
			false	Couldn't close connection (check console)
			
	MySQL::Destroy(ref_name);
	
		Kills the connection id and frees memory. This can be used after a
		MySQL::Close call, or in replace of one (this calls MySQL::Close if
		the connection is open first, then destroys the id).
		
		Returns:
		
			true	Memory was freed, and connection (if present) was
					closed without any problems
			false	Either the connection close failed (see console) or
					it could not free the memory for the connection id
					(maybe bad id?, either way see console)
					
Demo Script:

	function foo()
	{
		$mysql      = "demo_connection";
		$info[host] = "localhost";
		$info[user] = "root";
		$info[pass] = "secret";
		$info[db]   = "demo_table";
		
		if (MySQL::Create($mysql))
		{
			if (MySQL::Connect($mysql,$info[host],$info[user],$info[pass],$info[db]))
			{
				// Connection is open, keep in mind it MUST be closed at some point
				
				
				
				// clones_table
				//   clone_id     Unique id for clone
				//   clone_ip     Player's IP address
				//   clone_names  List of names seen used by the player
				$sql = "SELECT * FROM clones_table";
				if (MySQL::Query($mysql,$sql))
				{
					$results = MySQL::Rows($mysql);
					
					if ($results > 0)
					{
						// You can do this two ways. Use a results variable as I have,
						// or loop until it returns false (but if it returns false, the
						// $MySQL::Error variable must be empty or else something bad
						// happened (other than hitting the end of the list)
						while ($results > 0)
						{
							MySQL::FetchRow($mysql);
							
							echo(sprintf("%1. IP: %2 - Clones: %3",
								MySQL::Fetch($mysql,"clone_id"),
								MySQL::Fetch($mysql,"clone_ip"),
								MySQL::Fetch($mysql,"clone_names")));
							
							$results--;
						}
					}
					else
					{
						echo("No Results Found");
					}
				}
				else if ($MySQL::Error)
					echo("MySQL Query Failed: " @ $MySQL::Error);
				
				
				
				// close the connection
				MySQL::Close($mysql);
				// You don't have to destroy it technically until the server is exiting,
				// but it's good practice to remember to destroy it. Additionally, if you
				// plan on calling both these like I have, just use Destroy--it calls close
				// for you. I am just giving you a step-by-step to give you understanding.
				MySQL::Destroy($mysql);
			}
			else if ($MySQL::Error != "")
				echo ("Could not connect: " @ $MySQL::Error);
		}
	}