A BYONDscape Classic! Yes, I know we just posted two big articles about the browser, but that just makes the time all the more opportune to post this. As your junior-high teachers told you: "Compare and contrast." --Gughunter
Dream Tutor: What Good is the Browser?
If you've spent a little time in BYOND, by now you're probably wondering what that "Browser" button in Dream Seeker is good for. A few games use it to show the game's official Web site, or you could check out the hub, but that's not so useful to you, is it?
Well, I didn't quite get it either until I played Gazoot's Bunniflip. Items, rules, score tallies, and just about everything else are shown in the mini-browser, and the results look darn good. Then I tried Foomer's graphical chat Ensya, which uses a browser interface for reading and writing scrolls--which means you can get interactive with this thing and make browser actions affect the game. Clearly, the browser has some powerful capabilities that are underexploited by most games. Reading a bit more into BYOND's reference, I got to know what some of those capabilities are.
Since the beginning of BYOND, the power of the mini-browser has increased significantly. It's time to see just what it can do for you.
Mini-Browser Basics
There are 3 procs that rule the world of the mini-browser, and they're all pretty easy to use. They are:
- browse()
- browse_rsc()
- link()
The key proc is browse(). You can give this a URL in single quotes like browse('help.html') or the actual text as browse("Hello, world!"). With it you can generate HTML pages on the fly and send them to the user. That means you can create dynamic pages that respond to conditions in your game and report on what's going on.
Another helpful proc is browse_rsc(). What does this do? Well, it sends over a file to the user's cache so the browser can read it. This is good for graphics, style sheets, sounds, you name it. browse_rsc() takes one or two arguments: Either you can give it a file in single quotes, as in browse_rsc('background.gif'), or you can give it a var followed by a filename to use, like this:
usr << browse_rsc("body {font-family: 'Verdana', \
sans-serif}","style.css")
Notice the usr << part? That's used for all these procs. You send browse() just like normal text; you can send it to src, world, a list, or anything else that could see text.
Now for the last proc: link(). Notice browse() can take a local file name? Well, link() can use a regular URL just as if you'd clicked on a link. Calling world << link("http://www.byondscape.com") will put BYONDscape in your mini-browser. It could also be used to take players to your game's official site.
Putting Together A Page
So now what? Well, let's just try a small example page to go with a "who" verb to show the players in your game.
mob |
Notice how the page is built from scratch. We fill in the table using the list of players in the world. The most important thing to notice, however, is how browse_rsc() is being used here. If you include mygame.css and background.jpg in your project, the mini-browser needs them cached before it can use them. If you take a look at the HTML page, you'll notice there's no reference to background.jpg, but there is one to the style sheet. That style sheet can be as simple as this:
body {color: black; font-family: sans-serif; |
That's a pink background; not everyone's first choice, naturally, but let's pretend it's appropriate. Whatever you do, you should always pick a background color that closely matches the image you use.
Want to know another trick? You can put together a style sheet at runtime just like you did with your HTML page.
var/txt = "body {" |
Links That Work
Well this is great, but how do you make a link actually interact with the game? Now we get to the meat of it. There's this wonderful proc in the client called Topic() that does everything we need.
client/Topic(href, href_list[], hsrc)
|
Warning!
Text links and dynamically-generated HTML can use links with just ?, but when you use browse('file.html') or link('file.html'), you should use byond://? for your links instead. If you're not sure which to use, use the longer one. |
So what's all that for? Well, it happens that whenever a link is clicked with byond://? as the first part of the URL, that link is diverted to this proc. BYOND's profiling feature even uses this proc. You can use it too--not just for links in the browser, but for anything in text output.
The href argument is everything following ? in the URL. (HTML gurus call this the query string.) The list href_list is a parsed version of that, so the URL ?name=Bob&value=10 is separated into an associative list where href_list["name"]=="Bob". (If this is confusing, don't worry. It's easier than it looks.) Finally, hsrc will point to any object referenced in the src= part of the URL, if there is one.
Let's try this out with a "private" verb, for speaking privately to another player. Suppose when you send a message to someone, you want them to be able to click your name to reply.
mob |
Now, when you click on a name in a private message, it'll prompt you for another message to send to that player.
When you use href_list, remember that the items in it are all text. If you get an object reference in anything other than hsrc, you need to use locate() to translate it back into an object (which could be a mob, obj, turf, icon, datum, etc.). If you have a number and want to change it from text to a number, use text2num():
var/mob/giveto = locate(href_list["giveto"]) |
The Mini-Browser Returns
That last section had nothing to do with the mini-browser, did it? Fair enough; let's talk about the browser again. Suppose, going back to that "who" verb example, we wanted to refresh the list every minute. (This is actually a bad idea if the player clicks away from the browser, because another call to browse() is going to pull it back up. It's just an example.) A little HTML research will tell you that in the
section, you'll need this:<meta http-equiv="Refresh" content="60; url=myfile.html">
So that page will load myfile.html after 60 seconds. But wait! If we generated that HTML on the fly, we have no URL to put in there, do we? Ah, but we can put in a byond:// URL to take care of that. So, add this right after
:<meta http-equiv='Refresh' content='60; url=byond://?who'>
Now, to go to the client:
client |
Now the page generated by the who verb will refresh itself any minute. But woe to the user who clicks back to their info panel or the pager, because when the page refreshes they'll end up staring at it again. You should find a better way to do this. One way is just to put a simple text link in your HTML output and let users refresh the list themselves:
<A HREF="byond://?who">Refresh</A>
You can use links for just about anything. But don't forget, you can also use forms. The HTML