Game Development Community

dev|Pro Game Development Curriculum

News GUI control for receiving news content from a web server

by Nathan Martin · 09/02/2002 (12:17 pm) · 39 comments

Download Code File

Well here is an on-line version of the news control's file data and I'll explain after it:

//--- OBJECT WRITE BEGIN ---
new GuiControl(NewsDlg) {
   profile = "GuiDefaultProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 8";
   visible = "1";
   helpTag = "0";

   new GuiWindowCtrl() {
      profile = "GuiWindowProfile";
      horizSizing = "center";
      vertSizing = "center";
      position = "75 36";
      extent = "618 459";
      minExtent = "300 200";
      visible = "1";
      helpTag = "0";
      text = "Game News!";
      maxLength = "255";
      resizeWidth = "1";
      resizeHeight = "1";
      canMove = "1";
      canClose = "1";
      canMinimize = "1";
      canMaximize = "1";
      minSize = "50 50";
      closeCommand = "Canvas.popDialog(NewsDlg);";

      new GuiScrollCtrl() {
         profile = "GuiScrollProfile";
         horizSizing = "right";
         vertSizing = "height";
         position = "8 26";
         extent = "132 400";
         minExtent = "8 8";
         visible = "1";
         helpTag = "0";
         willFirstRespond = "1";
         hScrollBar = "alwaysOff";
         vScrollBar = "dynamic";
         constantThumbHeight = "0";
         childMargin = "0 0";

         new GuiTextListCtrl(NewsList) {
            profile = "GuiTextListProfile";
            horizSizing = "right";
            vertSizing = "bottom";
            position = "1 1";
            extent = "130 8";
            minExtent = "8 8";
            visible = "1";
            helpTag = "0";
            enumerate = "0";
            resizeCell = "1";
            columns = "0";
            fitParentWidth = "1";
            clipColumnText = "0";
         };
      };
      new GuiButtonCtrl() {
         profile = "GuiButtonProfile";
         horizSizing = "right";
         vertSizing = "top";
         position = "8 432";
         extent = "133 21";
         minExtent = "8 8";
         visible = "1";
         command = "GetNews(NewsList.getRowTextById(NewsList.getSelectedId()));";
         helpTag = "0";
         text = "Refresh News";
         groupNum = "-1";
         buttonType = "PushButton";
      };

      new GuiScrollCtrl() {
         profile = "GuiScrollProfile";
         horizSizing = "width";
         vertSizing = "height";
         position = "146 26";
         extent = "465 426";
         minExtent = "8 8";
         visible = "1";
         helpTag = "0";
         willFirstRespond = "1";
         hScrollBar = "alwaysOn";
         vScrollBar = "alwaysOn";
         constantThumbHeight = "0";
         childMargin = "0 0";

         new GuiMLTextCtrl(NewsText) {
            profile = "GuiMLTextProfile";
            horizSizing = "width";
            vertSizing = "bottom";
            position = "1 1";
            extent = "457 14";
            minExtent = "8 8";
            visible = "1";
            helpTag = "0";
            lineSpacing = "2";
            allowColorChars = "0";
            maxChars = "-1";
            autoSizeWidth = true;
            autoSizeHeight = true;
         };
      };
   };
};
//--- OBJECT WRITE END ---

function NewsDlg::onWake(%this)
{
   // Web server to connect to in order
   // to download the news. Note ':80'
   // part must be left there or else
   // this will not work.
   $NewsHTTPHost="mywebserver.com:80";

   // Directory on the web server where
   // the news files are kept:
   $NewsHTTPPath="/path_to_news_dir/";
}

//----------------------------------------

function GetItemList()
{
   NewsList.entryCount = 0;
   NewsList.clear();
   %newsc = new HTTPObject(ItemList){};
   %newsc.get($NewsHTTPHost, $NewsHTTPPath @ "news.txt", "");
}

function ItemList::onLine( %this, %line )
{
   if(%line $= "[done]")
   {
      if($NewsName $= "")
      {
         NewsList.setSelectedRow(0);
      } else {
         %index = NewsList.findTextIndex($NewsName);
         NewsList.setSelectedRow(%index);
         //$NewsName="";
      }
   } else {
      NewsList.addRow( NewsList.entryCount, %line );
      %line = strreplace( %line, " ", "_" );
      %line = strlwr( %line );
      NewsList.fileName[NewsList.entryCount] = %line @ ".hfl";
      NewsList.entryCount++;
   }
}

function ItemList::onConnectFailed()
{
   MessageBoxOK("ERROR","Couldn't connect to news server to receive news!"@
   " The news server might be down for right now\n\nPlease try again later"@
   " at least 20 minutes from now. That will give it enough time to come back up.\n\nSorry :(");
}

function ItemList::onConnected()
{
}

function ItemList::onDisconnect()
{
}


//----------------------------------------

function NewsList::onSelect(%this, %row)
{
   GetNewsFile(%this.fileName[%row]);
}

function getNews(%NewsName)
{
   if(%NewsName !$= "") { $NewsName=%NewsName; }
   NewsList.entryCount = 0;
   NewsList.clear();
   GetItemList();

   //NewsList.setSelectedRow(0);
   Canvas.pushDialog(NewsDlg);
}

function GuiMLTextCtrl::onURL(%this, %url)
{
   // Check to see if the user clicked on
   // a section selection command link and
   // not an actual URL.
   %x = strpos( %url, ".." );
   if(%x !$= -1 ) {
      // yep it's a section selection command link!
      // Now let's see what section we should select
      // to automatically jump to that section.
      %call = getSubStr( %url, 0, %x );
      if(%call $= "news") { getNews(getSubStr( %url, %x + 2, strlen(%url) - %x )); }
   } else {
      // nope, it's just a URL. Therefore
      // open the user's default web browser
      // to that URL link that's provided.
      gotoWebPage( %url );
   }
}   

//-------------------------------------------

function GetNewsFile(%filename)
{
   %newsi = new HTTPObject(TheNews){};
   %newsi.get($NewsHTTPHost, $NewsHTTPPath @ %filename, "");
}

function TheNews::onLine( %this, %line )
{
   if(%line $= "[done]")
   {
      NewsText.setText($newslines);
      $newslines="";
   } else {
      $newslines=$newslines @ "\n" @ %line;
   }
}

function TheNews::onConnectFailed()
{
}

function TheNews::onConnected()
{
}

function TheNews::onDisconnect()
{
}

Now that data should be saved into a file named NewsGui.gui. Now the content of the file news.txt which is needed for all of this to work smoothly:

News Test
About Test
[done]


Now the content of news_test.hfl:

<just:center><lmargin%:5><rmargin%:95><font:Arial Bold:25>News Test!
<just:left>
<font:Arial Bold:20>[00/01/2002 @ 1:33 AM (CST)] - <a:t2n.org>TRON</a><font:Arial:16>
<font:Lucida Console:12>
This is a news test of my news control which I
scripted out myself! I hope you are happy with
the results...  :p

Also <a:news..About Test>click here</a> to find info about this test.

[done]


Content of about_test.hfl:

<just:center><lmargin%:5><rmargin%:95><font:Arial Bold:25>Abouts Test!
<just:left>
<font:Arial Bold:20>[00/01/2002 @ 1:33 AM (CST)] - <a:t2n.org>TRON</a><font:Arial:16>
<font:Lucida Console:12>
This is a news test of my news control which I
scripted out myself! Which I use the HTTPObject
to 'pull' the news right off of a web server
which I think is the smartest move to take to
provide a news model for on-line games. It's
simple and web-based dynamically generated
news could easily be implemented just by
tweating around with the news script a bit
and of course build a news system that works
on the web server such as using PHP.

[done]


Now you have the following files NewsGui.gui, news.txt, news_test.hfl, and about_test.hfl. Upload the last three files onto a web server and put the first file which is NewsGui.gui into your game's /[mod]/client/ui/ directory and don't forget to implement it into the game by editing init.cs file that's located one directory up from where you placed the news control at. Add this line in init.cs file:

exec("./ui/NewsGui.gui");

That will have the game loadup and process the news control for usage.


Now edit the NewsGui.gui control file and scroll down to the point where you see:

function NewsDlg::onWake(%this)
{
   // Web server to connect to in order
   // to download the news. Note ':80'
   // part must be left there or else
   // this will not work.
   $NewsHTTPHost="mywebserver.com:80";

   // Directory on the web server where
   // the news files are kept:
   $NewsHTTPPath="/path_to_news_dir/";
}

You need to edit both of those variable's values to your web server's address and path to where the news files are kept. Then save the file. After you have done all of this create a button somewhere in your game and put this line in command property:

getnews();

Now click on that new button and tada! If you did everything correctly it should have worked!

Sorry for the lack of comments in the code and the lack of information in this resource since this is my first resource posting I am not really sure what all I should disclose and it's pretty late right now, so I'm very tired.
I've also uploaded the files needed for all of this just in case someone is too lazy to copy and paste into notepad(or your favorite text editor) to do all of this.

I hope you all like this resource since I know this one could have helped me out a lot when I needed to know how to use HTTPObject.


ScreenShot:

t2n.org/downloads/pics/prg_again_news.jpg

About the author

By day I work as an embedded microcontroller programmer for mainly Blackfin MCU/DSPs, and by night, and free time too, I'm a hobbyist game developer.

Page«First 1 2 Next»
#21
10/20/2002 (3:06 am)
this is my site addy i'm using atm:

pointdestruction.port5.com ..

and this is what my vars look like: $NewsHTTPHost="pointdestruction.port5.com:80";
$NewsHTTPPath="pointdestruction.port5.com/";

and i'm getting a "bad request" deal or something .... cant quite see it all
#22
10/20/2002 (3:21 am)
w000000t I got it ... hehe, nm ;)

one question ... how do you do more than one variable in the query ... In the example above they only was calling one variable in the php script - what if you wanted to do more than one?
#23
10/20/2002 (11:51 am)
To make it possible to do multiple query variables you have to comment out one line of code in the httpObject.cc source code of Torque of void HTTPObject::expandPath.

Just comment out this line:
asciiEscapeTable['&'] = true;
to
//asciiEscapeTable['&'] = true;

Since that is now commented out you can use & to define another query variable infront of another, but there is a bad thing about this. Torque will not beable to convert & to the HTTP standard ASCii code which web server require in order to have a & character in a variable's value field. Same goes for using =, you have to convert it yourself in order to use
it in a variable's value field. I do not know what the code string is for & and =. I'll figure it out here in a few minutes and then I will let you know.
#24
10/20/2002 (12:36 pm)
That did it - dude, your friggin awesome!
*bows down before nathan*...

lol nice work ;)
#25
10/20/2002 (1:42 pm)
Alright I have the results of the tests I've preformed to get the answers:
%26 is &
%3D is =

Tada, there ya go and enjoy!
:)

Edited: Had the values backwards, oops :P
#26
10/20/2002 (1:54 pm)
how about ~ lol ... heres the addy i'm trying to use now :/
www.yaddah.com/~name/ ... how would THAT work lol.
So many problems .. aaahhh haha

Nm ... maybe I should wait a few errors before posting eh - got it ;)
#27
07/12/2003 (5:38 pm)
What am I doing wrong?

I can get hte default pages to work, but if I edit news.txt the dialog only loads the list and not that pages, I have all the .hfl files there...?
#28
07/12/2003 (7:06 pm)
each line except for [done] should reflect a file name that is located in the same directory as the news.txt file. So if you have one line that is My Info then there has to be a file named my_info.hfl. So ' '(spaces) are replaced with _ (underscores) and the name must be in lower case that way it's easier to manage or else the web server won't send the file to the client if using a UNIX type of a server operating system. Understand now? :)
#29
11/24/2004 (10:01 am)
This resource was extremely useful..

Two things to make this work:

1.. The IP Address and the Path must be set before call the method 'get' into getItemList, because the onWake method runs after that..

function GetItemList()
{
NewsList.entryCount = 0;
NewsList.clear();
%newsc = new HTTPObject(ItemList){};

$NewsHTTPHost="192.168.3.130:80";
$NewsHTTPPath="/news/";

%newsc.get($NewsHTTPHost, $NewsHTTPPath @ "news.txt", "");
}

2.. All the files of news must have a blank line at the end of them.

...
...
[done]
--> blank line
#30
05/22/2005 (11:55 pm)
Is there anyway to transfer a variable from the initial function to the onLine function with out global variables?

Ex:

function getNews(%url, %path, %client)
{
%news = new HTTPObject(theNews){};
%news.get(%url, %path, "");
}

function theNews::onLine(%this, %line)
{
echo(%client); //the %client variable being the one from the getNews function
echo(%line);
}
#31
10/10/2005 (11:16 am)
didn't work in MacOS tiger ....:( see http://www.garagegames.com/mg/forums/result.thread.php?qt=35461
#32
11/14/2005 (12:17 pm)
This was great stuff, and Gustavos comment about GetItemList() also helped me alot.
#33
12/03/2005 (2:57 am)
Could this also be modified to work as a sort of "checker" to see if you have the latest version of the game?

For example, in the clients files he has a var like, $Pref::Version = 2.0; and on a website it has latestversion.txt and inside it just has "2.1" so when the client starts his game, it can popup a gui if he doesnt have the latest version or something.

Oh yeah, sorry. If i edit the ::onLine function, and change it so if $line !$= $version { pushgui }; - it should work.

Awesome Resource.
#34
04/26/2006 (9:21 am)
would it be possible to use this to do a UDP "post" to an ip address/port? i have a special hardware system for sending commands to robots via a wifi access point and reciever on the robot. i have 10 robots, each with their own ip address/port. currently, i can use a terminal program to send characters to the ip addresses, each short string of ascii characters is sent to a robot, which interprets and executes a command. for example, sending "BARK" to 192.168.1.100 causes the robot dog on that address to bark, entirely wireless, using wifi (way better than bluetooth, way more range).

i'd like to enable this within a torque game, the point being the virtual world in-game mirrors the physical world the robots live in.

any ideas greatly appreciated!!

best,
j
#35
04/27/2006 (2:38 pm)
If we have a TCPobject, I don't see why there couldn't be a UDPObject. too bad I have no idea how to code it. :)

Is there data on how to use this through a proxy? Like the browsers do?
#36
05/23/2006 (1:39 am)
Worked out of the box basically for me... Just configured my mod_perl server to handle hfl files, slammed the examples in and "owned!"

I dynamically fed 10K elements into the list, and it handled them just fine btw...
#37
06/04/2006 (10:37 am)
This is great, thanks
#38
01/10/2007 (2:23 am)
Works great! my only question is, could it be adjusted to work inline without having to go the NewsGUI file?

Ideally im just after it to display the main news on the mainmenu.

Regards,
#39
12/06/2012 (3:43 pm)
The download link is broken.how can I get the "Download Code File"
Page«First 1 2 Next»