Game Development Community

dev|Pro Game Development Curriculum

Introduction: FreeBuild, phpBB2 integrations and SAX chat

by Thomas -elfprince13- Dickerson · 10/21/2009 (5:14 pm) · 15 comments

Project Introduction

I suppose I might as well introduce my project at this time as well so that my screenshots make sense. I'm sure most people who've been around GarageGames long enough are familiar with Blockland. What most of you probably aren't familiar with is a lot of the drama surrounding the Blockland community. Long before Blockland released it's Retail version, a thriving modding community grew up around it. One of the mod development teams, TBM, made no bones about the fact that they intended to make their mod a better game than Eric Hartman's eventual Blockland Retail release, and a lot of resentment sprung up between TBM and the mainline Blockland community. When modders of from another "faction" stole code + artwork from TBM, the TBM developers at the time retaliated by including a script in TBM that would delete the stolen artwork from the other mod directories. Eric used this as an excuse to accuse TBM of planting a virus, and banned it's developers and players from the community. I began playing sometime later, when it was recommended to me by a friend, and put significant amounts of time into mapping and coding AI scripts for multiplayer games in TBM. Probably 6 months after this came an increasing desire in the TBM community to get out from under the shadow of tensions with the Blockland community and develop our own game. I joined the dev-team for a Lego-themed game based on the old TBM. Eventually this effort fell apart too, and I was left in control of the project. I spent a long time working with script only on the TGE 1.4 demo, until I saved up money this spring for a TGE 1.5 license and picked up a couple people to help with scripting and artwork. The project is now in full swing, and is titled "FreeBuild: The Builder's Game"

I'm hoping to making a beta release by the end of this semester, and I'll be posting about interesting new features as I finish them. In that light I'll begin (later this evening) with explaining the process I've gone through to integrate FreeBuild with the phpBB forum and MySQL powered SAX chat on the Cemetech programming+technology community of which I'm an administrator and which is home to this project.



phpBB2 and SAX Walkthrough: Part 1


In the development of FreeBuild I presented with an interesting dilemma. I wanted to allow users to have a central place to register their in-game nicknames, share builds, and chat as a cohesive community, but the game servers are user hosted, and not running on any sort of official dedicated box over which I would have any control. To this end I set up a 3-part system to handle the following tasks
  • Registering servers with Cemetech (the central login database + chat location, serving as a stand-in Master Server).
  • Allowing clients to log in to Cemetech for chatting, protecting their usernames
  • Checking that clients connecting to servers are authenticated with Cemetech.
This is made more difficult by the fact that I don't want to just kick off anyone who isn't logged in, to allow for LAN situations or times when Cemetech is down. The system is still a little rough around the edges, and doesn't support all the features I'd like yet, but it's still worth giving the basic tour, since the solution will be different for anyone who's implementing it.

The first thing is the client login. I originally tried implementing this with TGE's built in HTTP and TCP objects, but it was way too slow, and fairly hard to work with. So I compiled in bank's libcurl integration, and modified it to the point that you see here.

Here are my base client-side login functions:
function trylogin(%username, %password, %autologin){
	%auth = new SimCurl();
	%auth.setUrl("http://www.cemetech.net/scripts/torqueauth.php?login");
	%auth.setCookieJar("core/client/cookies/auth.txt");
	%auth.addPostField("username",%username);
	%auth.addPostField("password",%password);
	if(%autologin) %auth.addPostField("autologin","1");
	%auth.setFinishCallback("handleLoginResponse");
	%auth.setFailedCallback("handleLoginFailure");
	%auth.setProgressCallback("handleLoginProgress");
	$Pref::Player::SID = "";
	echo("Logging in...");
	%auth.start();
}


function handleLoginResponse(%auth){
	while(!%auth.isEOF()){
		%line = %auth.readLine();
		if(getword(%line, 0) $=  "LOGIN:"){
			%line = restwords(%line);
			$pref::Player::SID = getword(%line, 0);
			$pref::Player::Name = restwords(%line);
			echo("Logged in successfully");
		} else{
			echo(%line);
		}
	}
	%auth.delete();
}

function handleLoginFailure(%auth){
	echo("Could not login. Status follows: " @ %auth.getStatus());
	%auth.delete();
}

function handleLoginProgress(%auth){
	%total = %auth.getSizeTotal();
	%now = %auth.getSizeNow();
	if(%total) echo("Logging in:" @ ((%now/%total)*100) @ "%");
	else echo("Logging in: progress unknown");
	
	//-^ save this for a gui
}



function checksession(){
	%auth = new SimCurl();
	%auth.setUrl("http://www.cemetech.net/scripts/torqueauth.php?sid="@$pref::player::sid);
	%auth.loadCookieFile("core/client/cookies/auth.txt");
	%auth.setCookieJar("core/client/cookies/auth.txt");
	%auth.addPostField("check_session","1");
	%auth.setFinishCallback("handleLoginResponse");
	%auth.setFailedCallback("handleLoginFailure");
	%auth.setProgressCallback("handleLoginProgress");
	$Pref::Player::SID = "";
	echo("Logging in...");
	%auth.start();
}

function handleLogoutResponse(%auth){
	while(!%auth.isEOF()){
		%line = %auth.readLine();
		if(getword(%line, 0) $=  "LOGOUT:"){
			$pref::Player::SID = "";
			echo("Logged out successfully");
		} else{
			echo(%line);
		}
	}
	%auth.delete();
}

function handleLogoutFailure(%auth){
	echo("Could not logout. Status follows: " @ %auth.getStatus());
	%auth.delete();
}

function handleLogoutProgress(%auth){
	%total = %auth.getSizeTotal();
	%now = %auth.getSizeNow();
	if(%total) echo("Logging out:" @ ((%now/%total)*100) @ "%");
	else echo("Logging out: progress unknown");
}


function logout(){
	%auth = new SimCurl();
	%auth.setUrl("http://www.cemetech.net/scripts/torqueauth.php?logout&sid="@$pref::Player::SID);
	%auth.loadCookieFile("core/client/cookies/auth.txt");
	%auth.setCookieJar("core/client/cookies/auth.txt");
	%auth.setFinishCallback("handleLogoutResponse");
	%auth.setFailedCallback("handleLogoutFailure");
	%auth.setProgressCallback("handleLogoutProgress");
	echo("Logging out...");
	%auth.start();
}

There are 3 critical functions here.
trylogin(), checksession() and logout(), and some important things to note. trylogin() sets the cookie jar for reading cookies, but doesn't try to send any. SID is stored in the cookie, but more importantly, this saves the data necessary for autologin to behave correctly under phpBB2. checksession() is used to refresh the SID upon opening FreeBuild, but is only called if the autologin $pref::* variable is set. You'll notice that checksession() uses the same callbacks as trylogin(), this is because we want it to have the same effect. If the stored SID is still valid, or there's any valid auto-login data in the stored cookies, Cemetech will return exactly the same info as if you were logging in the for the first time. If you don't have any valid session hanging around, the old session data is destroyed so that the engine knows you aren't logged in. Finally, it's important to note that if logging out fails (due to server downtime, temporary database issues, whatever), that the logout() callbacks do not destroy the session data. This is so that the users are aware that their session and autologin keys are most probably still valid in the database which in turn will hopefully encourage them to try to log out again (and protect their account from compromise) instead of leaving sessions open. This is the account-safety equivalent of protecting against memory leaks by calling delete on an object before you set pointers to it to null.

All this is well and good, but the system above is still entirely console based, and unhelpful to most endusers. The next step is adding an interface to allow the users to interact with this. I created a 2-tabbed interface in my main menu, pictured here.
farm3.static.flickr.com/2580/4029341891_2375c07548_o.png
In reality this is a hidden 3-tab system, where the contents of the Cemetech On tab are replaced depending on whether or not you are logged in. The Cemetech Off tab disables logging in (and server registration) for LAN play, or falling back to use of the GarageGames master server in case of an outage at Cemetech.

I also added a small dialog with a progress bar to show the progress of logging in + out operations. I next added a second code file that ties the login/checksession/logout functions and their callbacks to the gui system.
package loginOverrides{
	
	function trylogin(%username, %password, %autologin){
		canvas.pushDialog(LoginProgressGui);
		LoginProgressBar.setValue(0);
		Parent::trylogin(%username, %password, %autologin);
	}
	
	function checksession(){
		canvas.pushDialog(LoginProgressGui);
		LoginProgressBar.setValue(0);
		Parent::checksession();
	}
	
	
	function handleLoginResponse(%auth){
		%loginfail = 1;
		%loginstatus = "";
		while(!%auth.isEOF()){
			%line = %auth.readLine();
			if(getword(%line, 0) $=  "LOGIN:"){
				%line = restwords(%line);
				$pref::Player::SID = getword(%line, 0);
				$pref::Player::Name = restwords(%line);
				LoginProgressText.setText("Logged in successfully");
				LoginProgressBar.setValue(100);
				%loginfail = 0;
			} else if(getword(%line, 0) $= "ERROR:"){
				%loginstatus = %line;
			}
		}
		%auth.delete();
		Canvas.popDialog(LoginProgressGui);
		if(%loginfail){
			$pref::player::sid = "";
			messageboxok("Error Logging In...", %loginstatus);
		} else{
			toggleCemetech(1);
		}
	}
	
	function handleLoginFailure(%auth){
		%auth.delete();
		Canvas.popDialog(LoginProgressGui);
		$pref::player::sid = "";
		messageboxok("Error Logging In...", %auth.getStatus());
	}
	
	function handleLoginProgress(%auth){
		%total = %auth.getSizeTotal();
		%now = %auth.getSizeNow();
		
		if(%total){
			LoginProgressText.setText("Logging In:" @ ((%now/%total)*100) @ "%");
			LoginProgressBar.setValue(mFloor((%now/%total)*100));
		}
		else{
			LoginProgressText.setText("Logging In: progress unknown");
			LoginProgressBar.setValue(0);
		}
	}
	
	function logout(){		
		canvas.pushDialog(LoginProgressGui);
		LoginProgressBar.setValue(0);
		Parent::logout();
	}
	
	
	function handleLogoutResponse(%auth){
		%logoutfailure = 1;
		%logoutstatus = "";
		while(!%auth.isEOF()){
			%line = %auth.readLine();
			if(getword(%line, 0) $=  "LOGOUT:"){
				$pref::Player::SID = "";
				LoginProgressBar.setValue(100);
				%logoutfailure = 0;
			} else if(getword(%line, 0) $= "ERROR:"){
				%logoutstatus = %line;
			}
		}
		%auth.delete();
		Canvas.popDialog(LoginProgressGui);
		if(%logoutfailure){
			messageboxok("Error Logging Out...", %logoutstatus);
		} else{
			toggleCemetech($pref::CemetechOn);
		}
	}
	
	function handleLogoutFailure(%auth){
		LoginProgressText.setText("Could not logout.");
		LoginProgressBar.setValue(100);
		Canvas.popDialog(LoginProgressGui);
		%auth.delete();
		messageboxok("Could not logout", "Status follows: " @ %auth.getStatus());
	}
	
	function handleLogoutProgress(%auth){
		%total = %auth.getSizeTotal();
		%now = %auth.getSizeNow();
		if(%total){
			LoginProgressText.setText("Logging out: " @ ((%now/%total)*100) @ "%");
			LoginProgressBar.setValue(mFloor((%now/%total)*100));
		} else{
			LoginProgressText.setText("Logging out: progress unknown");
			LoginProgressBar.setValue(0);
		}
	}
	
};

activatepackage(loginOverrides);


if($pref::player::autologin && $pref::player::sid !$= ""){
	checksession();
}

This is fairly self-explanatory, as it mirrors the previous bit of code, but adds in the necessary elements for interacting with the GUI. The call to toggleCemetech() makes sure the tabs are in a consistent state. Now we'll take a look at how SAX is implemented. Note that this has not yet been tied in to the gui, because I still need to figure out some formatting issues.


package sax{
	function saxsay(%what){
		%saxsay = new SimCurl();
		%saxsay.setUrl("http://www.cemetech.net/scripts/torqueauth.php?saxsay&sid=" @ $pref::player::sid @ "&what=" @ urlencode(%what));
		%saxsay.loadCookieFile("core/client/cookies/auth.txt");
		%saxsay.setCookieJar("core/client/cookies/auth.txt");
		%saxsay.setFinishCallback("onSaxPostResponse");
		%saxsay.setFailedCallback("onSaxPostFailed");
		%saxsay.setProgressCallback("onSaxPostProgress");
		%saxsay.start();
	}

	
	function onSaxPostProgress(%this)
	{
	}
	
	function onSaxPostFailed(%this)
	{
		messageboxok("Sax Error!", %this.getStatus());
		%this.delete();
	}

	function onSaxPostResponse(%this)
	{
		while(!%this.isEOF()){
			%line = %this.readLine();
			if(%line !$= "OK"){
				messageboxok("Sax Error!", %line);
			}
		}
		%this.delete();
	}

	function initSaxRead(){
		echo("Initializing SAX...");
		if(!$pref::sax::lastread){
			$pref::sax::lastread = 1;
		}
	}
	
	function onSaxReadProgress(%this){}
	function onSaxReadFailed(%this){
		messageboxok("Sax Error!", %this.getStatus());
		%this.delete();
	}
	
	function onSaxReadResponse(%this){
		//Cemetech sense in reverse chronological order
		//this makes our job a pain in the butt.
		%readin = "";
		%lineid = "";
		%who = "";
		%what = "";
		%timestamp = 0;
		%linetype = 0;
		%app = "";
		while(!%this.isEOF()){
			%line = %this.readLine();
			if(%readin $= "") %readin = %line;
			else %readin = %line NL %readin;
		}
		
		//split on \x1b
		for(%i = 0; %i < getRecordCount(%readin); %i++){
			%line = getRecord(%readin, %i);
			%lineid =	getDelimitedItem(%line, "\x1b", 0);
			%who = 		getDelimitedItem(%line, "\x1b", 1);
			%what = 	getDelimitedItem(%line, "\x1b", 2);
			%timestamp = 	getDelimitedItem(%line, "\x1b", 3);
			%linetype = 	getDelimitedItem(%line, "\x1b", 4);
			%app = 		getDelimitedItem(%line, "\x1b", 5);
			if(%linetype != 2){
				echo("(" @ %app @ ")" SPC %who SPC ":" SPC %what);
			} else{
				echo("(" @ %app @ ") ***" @ %who SPC %what );
			}
			if(%lineid > $pref::sax::lastread) $pref::sax::lastread = %lineid;
		}
	}
	
	function saxUpdate(){
		%saxread = new SimCurl();
		%saxread.setUrl("http://www.cemetech.net/scripts/saxpop.php?i=" @ $pref::sax::lastread);
		%saxread.loadCookieFile("core/client/cookies/auth.txt");
		%saxread.setCookieJar("core/client/cookies/auth.txt");
		%saxread.setFinishCallback("onSaxReadResponse");
		%saxread.setFailedCallback("onSaxReadFailed");
		%saxread.setProgressCallback("onSaxReadProgress");
		%saxread.start();
	}

};

activatePackage(sax);
initSaxRead();

Posting to SAX is fairly straight forward, reading is a bit more interesting.
$pref::sax::lastread stores the row number of the last line read. initSaxRead() just makes sure that if it hasn't been set yet, it's set to 1. SAX either returns the most current 30 lines (if $pref::sax::lastread is less than the row number of the 30th most recent message), or if it's more recent, however many messages have happened since the last read. Since SAX publishes messages in reverse chronological order (like a Facebook newsfeed), my read method firsts reads them in and builds a correctly ordered list. Each row has 6 fields, which may or may not be empty, and are delimited with an "\\x1b" character. This presents a problem, since TGE's string manipulation functions are largely limited to dealing with spaces, tabs and new lines, or "tokens." At first glance tokens seem like a good match, since you can set custom delimiters, but the problem is that nextToken uses a greedy algorithm which reads as many delimiting characters as it can until it runs into something else. This means that any empty fields are skipped over, and values end up getting assigned in the wrong place. To work around this, I implemented new Console functions, based on the same internal getUnit() functions that are used by getWord(), getField(), and getRecord(). I've released this as a resource here, and you'll see calls to getDelimitedItem() in my source.


That's it for now, and I'll try to cover the server side interactions and the contents of torqueauth.php when I polish them up a little bit.

About the author

C.S. PhD student at Brown University. Project lead for FreeBuild. Administrator, Cemetech tech community. Webmaster for the Village2Village Projects and the Vermont Sustainable Heating Initiative.


#1
10/22/2009 (9:11 am)
Well, the introduction looks definitively biased, and probably was not a good idea to share your 'perspective' on things that you were not involved into, nor witnessed either. The result, honestly, reads really inconsistent in several senses.

Deleting information from a computer at whim is plainly a punk behaviour and while you call that an "excuse", is clearly a mandatory reason to exclude the punks responsible for it from any community. I would not like to release a game and later found some cowboys making mods of my game that delete files from my customers computers.


That beeing said, your work looks outstanding, so Im looking forward to read more blogs about your progress.
#2
10/22/2009 (9:37 am)
Oh, you're definitely right that it was punk behavior, (though you should remember that at the time this was happening, Eric was still 2 or 3 years short of releasing Retail so in that sense there weren't really any "customers"), but I felt it was important to have that background information, because it helps explain a lot of aspects about my game, (for example many of the maps and models are "legacy" artwork from TBM). And I've been a first hand witness to the tensions that resulted from these events. Three years after they happened, I was banned from the Blockland forums for being a TBM player and trying to share videos of my AI scripts. I've looked over that code many many times, and any trace of the "virus" has been gone for years, and we're STILL being painted with the same brush. That being said, I'm not here to complain about Eric (I've already put him in the credits for my game), and my hope in writing it is to make clear that this isn't some next step in a war that I had no part in starting, it's an attempt to start fresh. I know he used to be a well known name around GarageGames, and hopefully if he's still around he see's it as being that.

As for my work, I'm glad to here that you think it's outstanding, and I look forward to posting more information for aspiring game developers, both with this project, and some of my side projects which haven't been given enough time recently.
#3
12/26/2009 (6:03 am)
Models from TBM? You mean Blocklands beta days right? First, the Lego player model was modeled by Eric. Secondly, as far as I can remember the TBM Devs ported brick models from LDraw.
#4
12/26/2009 (7:55 am)
TBM is just basically stolen code/models from Eric Hartman's Blockland. I am still surprised they are even still online. It seems like this new "the better mod" is stealing ideas from retail and making their own free version including older models from Eric Hartman's v0002 blockland. See what happened a few years back TBM had malicious codes that could erase your whole Blockland directory. However Eric Hartman prevented this and banned TBM from his game forever. Since then the so called makers of TBM still have this 3-5 year grudge of being banned they decided to always try to be better than Blockland even if they are just using stolen code, they spread biased messages and propaganda against retail Blockland ever since this little grudge they still have a few years ago. The funny thing is they try to always find ways to bypass the key system (meaning to get a free version of retail) if they hated retail so much why do they try so hard to get it for free? This new TBM is still the same piece of shit just like it was years ago, they will never change no matter how many new shit versions they make TBM, TBM2, DTB, TOB, the list just goes on and on.
#5
12/26/2009 (11:21 am)
"""Models from TBM? You mean Blocklands beta days right? First, the Lego player model was modeled by Eric. Secondly, as far as I can remember the TBM Devs ported brick models from LDraw."""

Nope. The TBM team modeled their on blocks. I seem to remember attempts at porting LDraw models to dts format, and then deciding they didn't want that much detail. I'm well aware that the Lego player model came from Eric, and the only reason that I haven't replaced it already is that I have some really nice plans for after the first demo comes out, and I don't want to tip my hand to early. No one is claiming Eric's work as their own, and there has even been discussion of modeling a new temporary player model for use in the short time between the first playable demo and release of the initial full version just to steer clear of stepping on any toes.



Tony, feel free to examine my code, and if you can find any code that has been copied from Blockland, please post it here publicly so I can deal with it. I've gone over the entire original TBM code base and stripped everything I could find that was copied from Eric's fps directory, and very little of the TBM code even remains at this point.

I can't speak for the Orange Block guys, but they make no bones of the fact that they are still based on the Blockland demo. There are a couple 12 year old script kiddies hanging around their website, who keep hoping to crack the key system out of spite, but they have nothing to do with my efforts. FreeBuild is/was supposed to be a clean break, and I made a point of acknowledging our history in previous posts to clean out any possible skeletons in the closet that people like you might try to dangle over me. Your history is still a little inaccurate in that,
a) Neither Death to Block, nor The Orange Block were "new versions" of TBM. DTB is a collection of (original) weapons, vehicles, and game play modes for TBM, and Orange Block is a standalone collection of DTB, new weapons, and hacked together script fixes to alleviate some of the traditional difficulties in setting up a TBM installation.
b) The list does not just go "on and on." You've listed the only projects with a base in Blockland v0002, none of which are still undergoing particularly active development.
#6
12/26/2009 (3:17 pm)
I find it incredible that people try to pull off revisionist history on the internet when the original facts remain preserved: http://www.torquepowered.com/community/forums/viewthread/32226


[u]The Facts:[/u]

(Confirmed by third party experts, or confessed to by the perpetrators themselves.)

  • TBM contained a backdoor that allowed anyone who knew about it to upload and execute arbitrary scripts to any server.
  • TBM contained code to automatically delete competing mods (in their entirety, not just specific parts as claimed)
  • TBM contained further malicious code that would automatically target certain usernames and IP addresses for special abuse.
  • One of the primary features of TBM was a "magic staff" that would give special abilities only to those who knew the secret codes to access them. The primary purpose of this appeared to be to give special privileges to TBM developers on any server they wished.
  • Members of TBM staff created spam scripts to attack RTB 1.045 servers. This was done to showcase the weaknesses of RTB and the supposed strengths of TBM spam blocking.
  • Members of TBM staff have discussed, at length, methods for obtaining retail Blockland for free and circumventing its various demo mode restrictions.
  • Members of TBM staff observed the retail Blockland GUI scheme in a preview video, made a clone of it for TBM, then attempted to claim that I had stolen it from them.

This behavior represents a complete ethical bankruptcy. These people should not be trusted.
#7
12/26/2009 (5:01 pm)
"""TBM contained a backdoor that allowed anyone who knew about it to upload and execute arbitrary scripts to any server."""

Interesting. I've reviewed the TBM code base in its entirety, and seen no evidence of this. It's entirely possible that it was there at some point in the past, and then removed. I wouldn't know. There has never been a discussion of the technical details of the incident in the community, only lots of propaganda from both sides, and I'm not interested in propaganda. I'm interested in making a fun game.


"""TBM contained code to automatically delete competing mods (in their entirety, not just specific parts as claimed)"""
Even a couple years ago, the only remnants of anti-theft code that I could find was code that would prevent scripts from running if aio or rtb were detected in the mod path. From the link you posted above, it seems this was not always the case, however Rob, Kier, and Chris have all been gone for a lot longer than that, and my work here is *not* by any means TBM.

"""One of the primary features of TBM was a "magic staff" that would give special abilities only to those who knew the secret codes to access them. The primary purpose of this appeared to be to give special privileges to TBM developers on any server they wished."""

Are you referring to servercmdadjustobj? It's not exactly a 'secret code', but it certainly performs functions that are poorly documented, and of which most players are unaware. But feel free to point out anything that you feel is particularly heinous. pastebin.com/f40be090c
TBM also had at one point several convenience functions, I think "mcp" and "mytourdeforce" which would automatically apply those players preferred character settings, however these were client side functions and did not affect server side permissions.

"""Members of TBM staff created spam scripts to attack RTB 1.045 servers. This was done to showcase the weaknesses of RTB and the supposed strengths of TBM spam blocking.
Members of TBM staff have discussed, at length, methods for obtaining retail Blockland for free and circumventing its various demo mode restrictions.
Members of TBM staff observed the retail Blockland GUI scheme in a preview video, made a clone of it for TBM, then attempted to claim that I had stolen it from them."""
Which staff members were these? I wouldn't put the spamming or the demo mode restrictions past certain of the script kiddy-esque forum members, but they have nothing to do with the development of my game, FreeBuild. Kier publicly performed several analyses of the Blockland key-registration system and determined (if I remember correctly) that unlike most game DRM schemes, they weren't algorithmically checked, but checked against a privately held list of keys on the blockland master server, and that each key was uniquely created at purchase. This does not offer any sort of circumvention.

I have to say, it's fairly frustrating to be accused of ethical bankruptcy because the previous developers of the code which forms the base of my hobby project made some bad decisions, even though they later had the good sense to remove the offending code, in a set of events which took place nearly 5 years ago. I tried to make a peace offering and a clean break in my blog post, and you came back to make your first Garage Games post in 3.5 years to complain.
#8
12/26/2009 (8:12 pm)
I think Novack is right. Don't talk, just ship your game. :)
#9
12/30/2009 (3:36 pm)
About the "magic staff," at one point MPC (old developer) actually showed me some of its "hidden" commands in my server. At that time the commands were no longer included in TBM but he linked me to an old version of the file. I remember him telling me Rob removed it from the official distribution, so that was a good move on the TBM developers' part, but at one point the code was still in everyone's files.

Of course all of this is the past, I agree with Novack too and would just concentrate on this now (which you are doing).
#10
01/01/2010 (8:22 pm)
... well, it seems most of the Blockland community is bitching about this, but I actually think its quite awesome.
Obviously I can't comment on the old TBM since I wasn't around to witness it, but I've always wanted to find a Blockland alternative that wasn't as crumby as Roblox. Maybe I'll give this a try if its ever released (hmm, is it released)?

I do think that its cute how Blockland players have come to complain about this. As usual, the Blockland community has to cry about it and start posting drama topics on the forums. Typical Blockland, eh?
#11
01/02/2010 (10:16 pm)
Icy, check out my newest blog post. It's not quite ready for the demo release, but I have opened up the SVN for checkout.
#12
01/04/2010 (6:44 am)
Does this "better mod" still have horrid brick bounding boxes because of improper/incomplete code just like every other TBM game?
#13
02/01/2010 (7:12 pm)
if you could do another blog on how torqueauth.php on the server is set up I would be very interested, since I am attempting to get the same basic system going :)
#14
02/01/2010 (7:54 pm)
Sure thing Scooby, I haven't worked on this side of things much for the last few months, but I have *most* of the torqueauth.php script setup and running. The "most" refers to a couple bits of funkiness in how I'm handling the replacement of the GG master servers with my php script.

I'll try and write something up during my free time tomorrow.
#15
02/01/2010 (9:00 pm)
Thank you very much. I appreciate it since it may help me a great deal