<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
    <channel>
        <title>Dream Makers</title>
        <link>http://www.byond.com/members/DreamMakers</link>
        <description>The place for BYOND developers! RSS: http://www.byond.com/members/DreamMakers/rss</description>
        <lastBuildDate>Sun, 08 Nov 2009 01:06:14 GMT</lastBuildDate>
        <language>en-us</language>
    
                <item>
            <title>How to - Host a server using Slicehost</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=83474</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=83474</guid>
            <pubDate>Thu, 08 Oct 2009 10:19:27 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=83474#comments</comments>
            
            <description>I while back I wanted to setup a serve using Slicehost. However I failed to find a spot with a complete guide on how to do so. With some research most of this you can figure out on your won, however I took the liberty to put all the needed info together and create a basic guide.&lt;br&gt;
&lt;br&gt;
&lt;u&gt;How to:&lt;/u&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 1:&lt;/b&gt;&lt;br&gt;
Open your browser and head over to &lt;a href=&quot;http://www.slicehost.com&quot;&gt;Slicehost&lt;/a&gt; and select &quot;Sign up&quot;&lt;br&gt;
Sign up button&lt;br&gt;
&lt;br&gt;
&lt;a target=&quot;_blank&quot; href=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/Signup.jpg&quot;&gt;&lt;img width=&quot;160&quot; height=&quot;83&quot; src=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/Signup_thumb.jpg&quot;&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 2:&lt;/b&gt;&lt;br&gt;
Enter your personal information, feel free to refer to me in the referral field, I would appreciate it: marcel.clement@planet.nl&lt;br&gt;
Select your Slice size, chose the Ubuntu (hardy) version from the drop down menu and give your Slice a name.&lt;br&gt;
&lt;br&gt;
&lt;a target=&quot;_blank&quot; href=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/Info.jpg&quot; rel=&quot;thumbnail&quot;&gt;&lt;img width=&quot;160&quot; height=&quot;149&quot; src=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/Info_thumb.jpg&quot;&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 3:&lt;/b&gt;&lt;br&gt;
Install the following software&lt;br&gt;
PuTTy: &lt;a href=&quot;http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html&quot;&gt;Link&lt;/a&gt;&lt;br&gt;
WinSCP: &lt;a href=&quot;http://winscp.net&quot;&gt;Link&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 4:&lt;/b&gt;&lt;br&gt;
By now you should have received a mail from Slicehost notifying your Slice was created.&lt;br&gt;
This mail should include and IP address and info about the user and password.&lt;br&gt;
This info is needed to access your Slice, keep it safe!&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 5:&lt;/b&gt;&lt;br&gt;
Start PuTTy, enter the IP address provided by Slicehost and click [Open] to connect to your Slice&lt;br&gt;
&lt;br&gt;
&lt;a target=&quot;_blank&quot; href=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/PuTTy%20login.jpg&quot; rel=&quot;thumbnail&quot;&gt;&lt;img width=&quot;129&quot; height=&quot;160&quot; src=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/PuTTy%20login_thumb.jpg&quot;&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
A black screen will appear saying &quot;login as:&quot;, enter the user provided by Slicehost and press [Enter]&lt;br&gt;
You will then be asked to enter your password, enter the password provided by Slicehost and press [Enter]&lt;br&gt;
&lt;br&gt;
&lt;i&gt;Note: For security reasons the password you enter will not show up when you start typing, this is normal.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Now you are connected to your Slice and we are able to setup the Slice so it's able to host your world.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 6:&lt;/b&gt;&lt;br&gt;
Change your password. To do so enter &quot;passwd&quot; and press [Enter], the system will ask you to enter a new password twice after which the password is changed.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 7:&lt;/b&gt;&lt;br&gt;
We now need to install all the needed software for running your world. Below you will see an overview of what you need to type to setup your Slice. Press [Enter] after each line and wait for the process to be done before moving to the next line. The last line will update everything you just installed, this is to make sure your software is complete and up to date.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
apt-get install make 
apt-get install gcc
apt-get install unzip
apt-get install ia32-libs
apt-get install screen 
apt-get update
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 8:&lt;/b&gt;&lt;br&gt;
Now we need to install BYOND, go &lt;a href=&quot;http://www.byond.com/download&quot;&gt;here&lt;/a&gt; and right click the link of the Linux version of BYOND and copy the direct download link.&lt;br&gt;
&lt;br&gt;
&lt;i&gt;Example: When this article was written the link was: &lt;a href=&quot;http://www.byond.com/download/build/453.1035_byond_linux.zip&quot;&gt;http://www.byond.com/download/build/453.1035_byond_linux.zip&lt;/a&gt;&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 9:&lt;/b&gt;&lt;br&gt;
Go back to PuTTy and enter the following lines and press [Enter] after each, make sure you update the link with the direct link you found at step number 8&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
wget http:&lt;span class=&quot;dmcomment&quot;&gt;//www.byond.com/download/build/453.1035_byond_linux.zip&lt;/span&gt;
unzip 453.1035_byond_linux.zip
cd byond
sudo make install
DreamDaemon --version
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 10:&lt;/b&gt;&lt;br&gt;
The version of DreamDaemon should now be displayed. The only thing left to do is upload the hostfiles and start hosting. To do so, start WinSCP and click [New]&lt;br&gt;
Enter the Slice IP at &quot;Host name:&quot;&lt;br&gt;
Enter your user under &quot;User name:&quot;&lt;br&gt;
Enter your new password under &quot;Password:&quot;&lt;br&gt;
Click [Login]&lt;br&gt;
&lt;br&gt;
&lt;a target=&quot;_blank&quot; href=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/WinSCP.jpg&quot; rel=&quot;thumbnail&quot;&gt;&lt;img width=&quot;160&quot; height=&quot;146&quot; src=&quot;http://www.byond.com/members/Fint/files/2009%2D10/Fint%2D0001/WinSCP_thumb.jpg&quot;&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;i&gt;Note: You can also save this info by clicking [Save], WinSCP will ask for a session name after which it will appear in the list. You can double click it to login.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 11:&lt;/b&gt;&lt;br&gt;
You will now see the files of your PC on the left, and the files of your Slice on the right. You can basically drag &amp;amp; drop any files from left to right and vice-versa.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 12:&lt;/b&gt;&lt;br&gt;
Create your &quot;World executable files&quot; using the Dreammaker. This will create a zip containing the files needed to host your game. Unpack the zip on your PC. Use WinSCP to transfer the files to your Slice. Make sure they are in a map which is called similar to your world.dmb file. So if your game is called &quot;MyWorld&quot; make sure the &quot;MyWorld.src&quot; and &quot;MyWorld.dmb&quot; file are in a folder called &quot;MyWorld&quot;, in the following steps we will assume the game is called &quot;MyWorld&quot;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 13:&lt;/b&gt;&lt;br&gt;
Log back in with PuTTy and type &quot;screen&quot; and press [Enter]. A message will appear, press [Spacebar].&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 14:&lt;/b&gt;&lt;br&gt;
Enter the following lines each followed by pressing [Enter]&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
cd MyWorld
DreamDaemon MyWorld.dmb 8000 -logself
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Step 15:&lt;/b&gt;&lt;br&gt;
The game is now being host, all we have left to do is detach the screen and close PuTTy. To do so hold [Ctrl] and press [A], then press [D].The process will now keep running and you can close PuTTy.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;&lt;u&gt;Congratulations, your game is now being host 24/7 on a Slice!&lt;/u&gt;&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
&lt;u&gt;Additional info:&lt;/u&gt;&lt;br&gt;
I'd like to take a moment to explain how screen works. If you would host your game without using screen the hosting would stop as soon as you close PuTTy.&lt;br&gt;
&lt;br&gt;
Here is a good guide on how to use Screen: &lt;a href=&quot;http://www.howtoforge.com/linux_screen&quot;&gt;Link&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Some quick commands for screen:&lt;br&gt;
screen -ls (displays a list of screens)&lt;br&gt;
screen -r screenname (allows you to reattach to a screen)&lt;br&gt;
screen -x screenname (kills that specific screen)&lt;br&gt;
And keep in mind you can detach a screen as described in step 15.&lt;br&gt;</description>
        </item>
                <item>
            <title>Functional Specifications</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=83278</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=83278</guid>
            <pubDate>Mon, 05 Oct 2009 06:20:31 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=83278#comments</comments>
            
            <description>Imagine a group of runners who have set out to run a marathon. They train for months to get ready, and come the big day they gather at the starting line wearing their Nike's, tank-tops, and running shorts. They're hydrated and ready to go.&lt;br&gt;
&lt;br&gt;
The starting gun fires and off they run. Some are determined to run the fastest, others want to pace themselves and run efficiently, while others are going to pull themselves through on shear willpower. The problem is that no one knows where the finish line is. In fact, no one thought far enough ahead to make an actual finish line. The guy in charge of the route figured that everyone would simply stop once they had run &quot;a marathon&quot;, because everyone would be able to tell when that had happened.&lt;br&gt;
&lt;br&gt;
Some people turned back at around 5 miles, right when word reached them that there was no exact finishing line. Others turned back after about 10 miles when the road split and no one knew which way they were supposed to go. At around 20 miles hardly anyone could see each other or knew where the race was, and they became despondent and gave up. At 30 miles people were too tired to continue, and just didn't care. Some people, determined not to give up, continued to run until they saw the sign for Wichita, Kansas. How long have we been running, anyway?&lt;br&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
Starting to write the code for a program, without first completing its design, is like running a marathon without a finish line. How will you know which roads to avoid? How will you know when you're finished? How will everyone know when to get together, fill their glasses, and toast your success?&lt;br&gt;
&lt;br&gt;
It's easy to make mistakes when planning, though. So how will we know what to plan?&lt;br&gt;
&lt;br&gt;
A program, at its core, is just input and output. If a program can accept input from the user and then output the correct results, then the program is working properly. So to plan our program, what we need to determine is the input and output.&lt;br&gt;
&lt;br&gt;
&quot;But what about our Jutsus! What about our class structure, and storyline!&quot; Yes, those things are important, but not at the moment. The sorts of things that we need to plan are &quot;The user will enter a combination of key strokes to execute a jutsu&quot;, or &quot;A user will be able to select his class&quot;, or &quot;When the player finishes entering his character's name, the opening movie will begin to play and introduce the story&quot;. These statements tell us exactly how the user will interact with our program, and they give us concrete systems that need to be programmed. If we were to write a list of such statements, then all we'd need to do to finish our game would be to go down the list checking off items until they were all gone. Then our game would be finished, Cheers!&lt;br&gt;
&lt;br&gt;
All we need to know now is what to put on that list. The answer: Everything. Everything that a user can do needs to be on that list, in every combination. Here's an example illustrating why:&lt;br&gt;
&lt;br&gt;
Let's say our list had these two entries: 1) players can double click another player to start a turn based battle; 2) players may not leave battle until one or the other is dead or runs away. Now consider that a malicious user joins your game, double clicks one of your players, waits until it's his turn in battle, and then logs out. Now your regular player is stuck in battle unable to do anything. We forgot that when the program is in the state where two players are battling, each player still has the ability to input a window closing command. So we need to write another line: 3) if a player becomes disconnected while in battle, he has one minute to reconnect, after which the other player wins. Once we take into consideration &lt;em&gt;all input&lt;/em&gt; available to the player at &lt;em&gt;every state&lt;/em&gt; in the program, then our programming job will be much easier, and we won't be sabotaging ourselves in the future.&lt;br&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
This list of actions that the player can take is what's known as a Functional Specification, or Func Spec for short. Func Specs come in many different forms, and most of them don't look anything like the one I'm going to show you. Think of this as an introduction for the BYOND developer. (Here's more in-depth article on &lt;a href=&quot;http://www.joelonsoftware.com/articles/fog0000000036.html&quot;&gt;Functional Specs&lt;/a&gt;).&lt;br&gt;
&lt;br&gt;
When planning this article, I started writing a spec for a simple program with which I could illustrate the concept. My first attempt was the &lt;a href=&quot;http://www.byond.com/members/IainPeregrine?command=view_post&amp;amp;post=67598&quot;&gt;Snow Monkey Simulator&lt;/a&gt; (which illustrated a different concept). The concept that I finally came up with was a 'Game Chat' environment. The current spec, which may someday become an actual BYOND program, is version 12 (I think) and &lt;a href=&quot;http://www.byond.com/members/DreamMakers/files/game_chat_specification.txt&quot;&gt;can be found here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
Notice how this spec has several categories. At the top is the name of the project, and a brief description of its purpose and Core Functionality. This is the statement of why the project exists in the first place. Everything else flows from and supports this functionality.&lt;br&gt;
&lt;br&gt;
Next is the main body of the spec (simply titled &quot;Specification&quot;). Notice how most of the statements start by mentioning that this is something initiated by &lt;em&gt;the user&lt;/em&gt;. The specification describes what the user can do, and how our program will respond. (I will admit the first several entries are not very good. In my quest to document EVERYTHING, I forgot to write in understandable English. Future versions may remedy this.)&lt;br&gt;
&lt;br&gt;
After the main body, you'll notice three other sections. Ever got a great idea for a cool feature? Ever put that feature into your game, only to see your original project bloated by hundreds of non-essential features, while your saving system &lt;em&gt;still&lt;/em&gt; doesn't work? Programmers will never give up on a feature, so we need to put them somewhere where we know they'll be safe. The ideas under consideration, for future versions, and even the section on forbidden ideas, will do just that.&lt;br&gt;
&lt;br&gt;
The ideas under consideration are features I feel would support the core functionality, but either are not needed or not yet concrete. Some of these features, like the filters, will definitely be added to the spec; all they're waiting on is a statement of &lt;em&gt;exactly how&lt;/em&gt; the user will interact with them.&lt;br&gt;
&lt;br&gt;
Ideas for future versions are really good ideas that would support the core functionality, but are not essential. These are put on hold until future versions, so we can get a 1.0 release out the door.&lt;br&gt;
&lt;br&gt;
Finally, there are the ideas which WILL NOT be put into the product. These are ideas which are really cool, and we don't want to forget, but detract from the core gameplay, or would sink the project. This category is also for ideas other people think are cool and will try and lobby to be added to the spec, yet you think are detrimental to the project.&lt;br&gt;
&lt;br&gt;
These three sections are a must have.&lt;br&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
To wrap up, let me say this: You need a functional spec, because it is your game. Before any code has been written, before any art has been drawn, before any sound has been recorded, you need to take the nebulous ideas floating around in your head and translate them into concrete rules. Once you have this document you have a much better chance of completing your game.&lt;br&gt;
&lt;br&gt;
As an added bonus, you also have a much better chance of getting people to help you! Imagine if you could go to the forums, and instead of saying &quot;I need an experienced coder and iconner and mapper&quot;, you could post a link to your document and say &quot;This is what I need done&quot;. A programmer will be a lot more willing to work with you if they know, up front, exactly what needs to be done and how much time it should take.&lt;br&gt;
&lt;br&gt;
So next time you're tempted to open Dream Maker, even if you're going to work on a project you've already started, take the time, instead, to sit down and start a functional spec. The half hour you spend writing in a human language will save you months of writing computer code.</description>
        </item>
                <item>
            <title>Get a hold of your target audience.</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=82099</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=82099</guid>
            <pubDate>Thu, 17 Sep 2009 00:39:21 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=82099#comments</comments>
            
            <description>The primary concern for most developers is that no one really desires to play their games. This is a pretty big drag, you spend a lot of time and effort making a game, and get nothing in return.&lt;br&gt;
&lt;br&gt;
The common response is to simply blame BYOND Anime. Those monsters, infesting our BYOND with their filth. Unfortunately, that's just incorrect, BYOND Anime simply has a much easier time because their audience is vast and collected in &lt;a href='http://www.byond.com/members/BYONDAnime'&gt;BYOND Anime&lt;/a&gt;. Believe it or not, there are people interested in playing your games (which is evident in the constant barrage of &quot;there's no good games!&quot; forum and blog posts we see day in and day out), you just have to find them, lure them in and trap them. Just like dating... or Pokemon.&lt;br&gt;
&lt;br&gt;
&lt;a href='http://www.byond.com/members/airjoe'&gt;Airjoe&lt;/a&gt; has already posted about &lt;a href='http://www.byond.com/members/BYONDRPG?command=view_post&amp;amp;post=70467'&gt;finding audiences outside of BYOND&lt;/a&gt;, asking if people would be interested in the classic SNES games being multiplayer, the response was fairly well received, so we know there's people interested outside of BYOND, that's all well and dandy, but who's going to come play an empty game? We need the audiences already in BYOND first, and yes, they are there.&lt;br&gt;
&lt;br&gt;
There are several methods one can employ to gain interest in their game pre-release. The simple and most effective I've found is to simply blog about it, a lot. Every day you've made progress on the game, tell the people of BYOND what that progress was. People who see active development tend to stick around.&lt;br&gt;
&lt;br&gt;
The second method that's shown positive results, is to release small demos of how the game-play will work. If you're using a modular programming method, it shouldn't take long to setup a test scenario, zip it up and ship it out. People who can interact with the game prior to it's release will get a feel for it's game-play and be more inclined to play the game if they enjoy it. Anyone who purchases PC Power Play and other such magazines are more than familiar with the concept of trying games before you buy them. Granted you wont actually be buying a game on BYOND, but lets face it, the idea of clicking on a download link and waiting the time for the game to download, psh, you might as well be charging two million dollars, I want to know it's &lt;i&gt;worth my time&lt;/i&gt;!&lt;br&gt;
&lt;br&gt;
Screenshots and game-play videos. Need I say more? Oh, okay, I will. Previews to the game mechanics are good, but they're not the game itself. I want to see the game, I want to feel the game, hell, I want to be the game. The only way I can do that, short of playing it, is observing it. &lt;a href='http://www.byond.com/members/silkgames'&gt;Silkgames&lt;/a&gt; has been releasing many screenshots on their upcoming RPG &lt;a href='http://www.byond.com/members/SilkGames?command=view_keyword_posts&amp;amp;keyword=nestalgia'&gt;NEStalgia&lt;/a&gt;. They also released &lt;a href='http://www.byond.com/members/SilkGames?command=view_post&amp;amp;post=67278'&gt;a video&lt;/a&gt; of the game. I don't know about you guys, but all of this has me wanting to play it. And no doubt, it has sparked the interest of several others around BYOND.&lt;br&gt;
&lt;br&gt;
Making a video about your game isn't difficult really. Whether you're doing lone development or in a closed alpha/beta test. All you need is the right &lt;a href='http://download.cnet.com/Camtasia-Studio/3000-13633_4-10665109.html'&gt;tools for the job&lt;/a&gt;, and a &lt;a href='http://www.youtube.com'&gt;YouTube&lt;/a&gt; account. The added benefit here is, any casual YouTube goer who isn't a BYOND user, might just register a BYOND account to try your game, so be sure to put a link to your games hub at the end of the video. Remember, BYOND has a &lt;a href='http://www.youtube.com/group/BYONDtube'&gt;YouTube Group&lt;/a&gt;, be sure to submit your video to it.&lt;br&gt;
&lt;br&gt;
Another thing not many people (if any) don't think of doing is simply to release the game manual prior to the release of your game. Game manuals, if written correctly, will have tips, tricks, screenshots and provide detailed information on how your game works. People who are interested in your game will then learn to play your game prior to it's release. The bonus is, people will give your game a shot, rather than jump in, die and leave 'cause they don't know what they're doing. Unfortunately, you can lead a horse to water, but you can't make him drink (you can drown him, but that wouldn't be good publicity for your game), so there is no guarantee that they'll read the manual if it's released. But every little bit helps.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Use your target guild to it's full advantage&lt;/b&gt;. I can't stress this enough, if I tired to, my head would explode and pieces of my brain would end up in your morning cereal, I don't want that, and I'm fairly sure you don't either. The guilds aren't there to be ignored, they're there to generate interest in your game (preferably post-release, but pre-release works too). The guild masters are nice guys, just be sure your post is well written, spell checked and shows an attempt to use good grammar (it only servers to benefit you anyway. People are going to take you more seriously if you put in effort in your posts appearance). And to counter the general argument &quot;the guilds are inactive&quot;, well, they're only inactive because no one bothers to use them, it's a double edged sword.&lt;br&gt;
&lt;br&gt;
It should be noted, that all of this stuff should (and mostly can) only be done when the better most of your development is finished and in a crunch, you have something to release. This is in accordance with &lt;i&gt;The BYOND Theorem&lt;/i&gt;: &quot;Never announce something you have not yet done. Try, and you will be instantly robbed of the determination to do it. 100% guaranteed!&quot;&lt;br&gt;
&lt;br&gt;
Remember, the players are there, you just have to work for them. Once your game is out, you should continue to do things like this as more updates to the games are made. &lt;a href='http://www.byond.com/members/BYOND?command=view_post&amp;amp;post=81776'&gt;Sneak Peeks&lt;/a&gt; are always good!</description>
        </item>
                <item>
            <title>Game in a Day 2009</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=81617</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=81617</guid>
            <pubDate>Tue, 08 Sep 2009 23:17:43 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=81617#comments</comments>
            
            <description>IainPeregrine has announced that the &lt;a href=&quot;http://www.byond.com/members/IainPeregrine?command=view_post&amp;amp;post=81293&quot;&gt;2009 Game in a Day event&lt;/a&gt; shall be held this weekend. Inspired by &lt;a href=&quot;http://www.nanowrimo.org/&quot;&gt;National Writing Month&lt;/a&gt;, the GiaD challenges participants to create a relatively complete game within 24 hours. Refer to &lt;a href=&quot;http://www.byond.com/members/IainPeregrine?command=view_post&amp;amp;post=81293&quot;&gt;IainPeregrine's post&lt;/a&gt; for the rules and methods used by the judges. Note that, unlike previous GiaD events, those who enter can state whether or not they want their source released to the public.&lt;br&gt;
&lt;br&gt;
This is the 4th year that IainPeregrine has held the GiaD.
&lt;ul&gt;
&lt;li&gt;In 2006, the theme was &quot;Talk Like a Pirate Day&quot;. Airjoe won first place with his game, Ninja's Reprise. All 20 entries can be found on the &lt;a href=&quot;http://files.byondhome.com/iainperegrine/giad_results.html&quot;&gt;results page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In 2007, the theme was &quot;Frost and Flame&quot;. Ranks were dropped. &lt;a href=&quot;http://files.byondhome.com/IainPeregrine/giad_2007/results.html&quot;&gt;12 games were judged on their level of completeness.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In 2008, those who entered were able to choose &quot;Noir&quot;, &quot;Communication&quot; or &quot;Sandwich&quot; as their theme. &lt;a href=&quot;http://files.byondhome.com/IainPeregrine/giad_2008/results.html&quot;&gt;7 games were judged.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
Participants will have to wait until this weekend to find out this year's theme. Keep an eye on &lt;a href=&quot;http://www.byond.com/members/IainPeregrine&quot;&gt;IainPeregrine's blog&lt;/a&gt;. Meanwhile, those interested in entering may also wish to read Acebloke's recent &lt;a href=&quot;http://www.byond.com/members/Acebloke?command=view_post&amp;amp;post=81585&quot;&gt;postmortem of two GiaD entries&lt;/a&gt; in which he focuses on documentation.</description>
        </item>
                <item>
            <title>Nadrew's How To: Looking up and down the type tree</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=80233</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=80233</guid>
            <pubDate>Mon, 31 Aug 2009 11:58:54 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=80233#comments</comments>
            
            <description>Something I noticed the last time I was scanning through my Blue Book was some funky type tree operators I had never seen used before. After investigating and realizing that part is in the online guide too (whoops, didn't notice!) I decided to enlighten the rest of the world who skipped that part.&lt;br&gt;
&lt;br&gt;
When you're writing out some long code for parent and children types you've probably said to yourself 'man there's got to be an easier way to handle this' at least once, this article will show you the way.&lt;br&gt;
&lt;br&gt;
There are two operators you can use the . look-up operator and the : look-down operator.&lt;br&gt;
&lt;br&gt;
Lets take a look at . first.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
obj
    myobj
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/my_var
        one
            my_var = .myobj
        two
            my_var = .one
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This example basically defines a few types and a variable, what the . does here is it'll look up the type tree for matches, if it doesn't find one in the first parent up it'll continue to look until it runs out of places to look. So what we're doing is really setting one's my_var to /obj/myobj and two's my_var to /obj/myobj/one. Still with me? Good.&lt;br&gt;
&lt;br&gt;
This can even be done outside of the parent type like so:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
obj
    otherobj
    myobj
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/my_var
        one
            my_var = .myobj
        two
            my_var = .otherobj
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This example sets my_var of the two object to /obj/otherobj -- saves a bit of typing.&lt;br&gt;
&lt;br&gt;
This next example shows how the look-up operator works for variable definition (proc and verb definition too!)&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
obj
    otherobj
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/some_var = 1
    myobj
        one
        .otherobj
            &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/other_var = 2
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This basically creates a new variable for /obj/otherobj under /obj/myobj -- this is very helpful for defining variables close to where they're being used and under the types they're being used on. You'll be able to use the 'other_var' variable from any /obj/otherobj instance.&lt;br&gt;
&lt;br&gt;
The look-down operator functions similarly except it works downwards through the type list and not upwards. So anything defined after the object in question will be found by the search.&lt;br&gt;
&lt;br&gt;
This makes for an excellent method of organizing your code, you can define things in ways that preserve the code tree while letting you work outside of it.&lt;br&gt;
&lt;br&gt;
I imagine there's still plenty to do with these operators that I haven't thought of yet, but this is a start. Good luck on making use of this technique and finding better ways to utilize it to its fullest.&lt;br&gt;
&lt;br&gt;
Until next time, keep on programmin'.</description>
        </item>
                <item>
            <title>Nadrew's How To: Dynamically named verbs</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=80230</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=80230</guid>
            <pubDate>Thu, 27 Aug 2009 16:32:26 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=80230#comments</comments>
            
            <description>One thing a lot of people don't know about is dynamic verb naming. This feature is very helpful if you want to do something like let objects of one type to have a single proc for actions but have that proc named differently for each object type when added as a verb.&lt;br&gt;
&lt;br&gt;
Creating a dynamically named verb is rather simple, simply add the verb like you would a new object, supplying the name as an argument of new().&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
obj
    myobjs
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;Activate&quot;&lt;/span&gt;
        object_one
            verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Activate()
        &lt;span class=&quot;dmkeyword&quot;&gt;set&lt;/span&gt; src &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; usr
        usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;You activated &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[src.name]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;!&quot;&lt;/span&gt;

mob
    &lt;span class=&quot;dmkeyword&quot;&gt;verb&lt;/span&gt;
        Test()
            &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/obj/myobjs/object_one/O = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(usr)
            O.verbs += &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Activate(src,O.verb_name)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Now instead of the verb being named 'Activate' it will be called 'One' but it'll still execute Activate() when used. Pretty handy, huh?&lt;br&gt;
&lt;br&gt;
The new() proc for verbs can take three arguments, the first is the atom you're giving the verb to, the second is the name of the verb, and the third is the description of the verb.&lt;br&gt;
&lt;br&gt;
Unfortunately things like dynamic settings for categories and other 'set' stuff isn't avaliable. Maybe some day!&lt;br&gt;
&lt;br&gt;
Lets take a look at a more open-ended example of the above that'll make use of the third argument of new().&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
obj
    myobjs
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;Activate&quot;&lt;/span&gt;
        one
            desc = &lt;span class=&quot;dmstring&quot;&gt;&quot;I'm the first object&quot;&lt;/span&gt;
            verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;
        two
            desc = &lt;span class=&quot;dmstring&quot;&gt;&quot;I'm the second object&quot;&lt;/span&gt;
            verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;Two&quot;&lt;/span&gt;
        three
            desc = &lt;span class=&quot;dmstring&quot;&gt;&quot;I'm not even right in the head&quot;&lt;/span&gt;
            verb_name = &lt;span class=&quot;dmstring&quot;&gt;&quot;Ugly&quot;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;
        Activate()
            &lt;span class=&quot;dmkeyword&quot;&gt;set&lt;/span&gt; src &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; usr
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;You have activated &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[src.name]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;!&quot;&lt;/span&gt;
    New()
        ..()
        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(istype(src.loc,/mob))
            verbs += &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Activate(src.loc,src.verb_name,src.desc)

mob
    &lt;span class=&quot;dmkeyword&quot;&gt;verb&lt;/span&gt;
        Test()
            &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/one(usr)
            &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/two(usr)
            &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/three(usr)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will handle all of the verb naming and addition inside of the object's New() proc so that you only have to create the object to gain access to the verbs. You'll end up with a unique verb for each object, each with its own verb description.&lt;br&gt;
&lt;br&gt;
Using this method you'll make it easier for people to create macros and keep their stuff organized, as opposed to having a long odd-looking command input when you need to provide which object to use the Activate() verb on.&lt;br&gt;
&lt;br&gt;
Removing verbs can be done in a similar fashion, you wouldn't think new() would be used for deleting something; but it is!&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
verbs -= &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/obj/myobjs/&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Activate(usr,&lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Will remove the command named 'One' from the list.&lt;br&gt;
&lt;br&gt;
That's about all there is to dynamic verbs, I'm sure you guys can find new and creative ways of using them. I'd love to hear about them, so don't hesitate to page me :).&lt;br&gt;
&lt;br&gt;
Next time, look-up and look-down type operators, what are they for and why doesn't anybody use them?</description>
        </item>
                <item>
            <title>Nadrew's How To: All about savefiles</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=80125</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=80125</guid>
            <pubDate>Sun, 23 Aug 2009 21:44:29 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=80125#comments</comments>
            
            <description>As any person who has done much more than a board game probably knows is that BYOND offers a very friendly and powerful data management system known as savefiles.&lt;br&gt;
&lt;br&gt;
Most people just make use of the Read() and Write() atom procs to handle saving player data. This method allows direct saving of an entire atom. While this system is usually robust enough to handle most of your saving needs it can sometimes be &lt;em&gt;too&lt;/em&gt; robust.&lt;br&gt;
&lt;br&gt;
A rather common problem that sprouts up on BYOND is what we've grown to call the 'rollback bug' -- this bug causes one player to be loaded back to a previous instance of themself when another player loads their own file. The cause of this is what's known as reference saving, when a player has a non-tmp variable that can contain a reference to another atom you end up saving an instance of that atom when you save that variable.&lt;br&gt;
&lt;br&gt;
This of course causes that atom be loaded back to the point where the variable was saved to the file. The best way to solve the problem is simply not letting any references get saved if they shouldn't. It's also a good idea to override the Write() function of specific atoms to prevent them from being saved at all. This is especially useful when saving areas if you want to move things off of the area before the contents variable is saved.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
mob
    nosave
        Write(savefile/F) &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Simple as that, no matter what variable is a reference to /mob/nosave it won't be saved when the parent Write() is called.&lt;br&gt;
&lt;br&gt;
That handles the automated saving system in place, now it's time to get into the stuff you'll want to know if you wish to save data manually.&lt;br&gt;
&lt;br&gt;
The savefile datum works like a file tree, it has directories and paths. There are a few variables that allow making use of these paths.&lt;br&gt;
&lt;br&gt;
Say you want to save the 'test' variable in the savefile under the virtual directory 'mydir', first you have to create a directory if it doesn't exist already, then you have to navigate to that directory before saving, unless you want to manually enter path information.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!F.dir.Find(&lt;span class=&quot;dmstring&quot;&gt;&quot;mydir&quot;&lt;/span&gt;)) F.dir += &lt;span class=&quot;dmstring&quot;&gt;&quot;mydir&quot;&lt;/span&gt;
F.cd = &lt;span class=&quot;dmstring&quot;&gt;&quot;mydir&quot;&lt;/span&gt;
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;test&quot;&lt;/span&gt;] &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;test!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will access the savefile located in 'mysave.sav', or it will create a new file it one doesn't already exist. Next we check the savefile's 'dir' list which contains all of the directories of the current savefile path, in the absence of a proper value we simply add a new one.&lt;br&gt;
&lt;br&gt;
Now we use the 'cd' variable to tell the system that we want to add data to a specific directory. Then we simply output a variable to the savefile using the &amp;lt;&amp;lt; operator and tada we have our own structured savefile. It will look something like:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
mydir
    test = &lt;span class=&quot;dmstring&quot;&gt;&quot;test!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Now after this you'll usually want to return to the top-most directory of the savefile; simply set the 'cd' variable to &quot;/&quot; and you're good to continue with the structuring.&lt;br&gt;
&lt;br&gt;
You can also used nested directories and variables.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
F.cd = &lt;span class=&quot;dmstring&quot;&gt;&quot;mydir&quot;&lt;/span&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!F.dir.Find(&lt;span class=&quot;dmstring&quot;&gt;&quot;subdir&quot;&lt;/span&gt;)) F.dir += &lt;span class=&quot;dmstring&quot;&gt;&quot;subdir&quot;&lt;/span&gt;
F.cd = &lt;span class=&quot;dmstring&quot;&gt;&quot;subdir&quot;&lt;/span&gt;
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;another_test&quot;&lt;/span&gt;] &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Another test!&quot;&lt;/span&gt;
F.cd = &lt;span class=&quot;dmstring&quot;&gt;&quot;/&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Pretty self-explanatory after the previous example, this simply just creates a new directory after navigating to 'mydir' so you'll end up with something like:&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
mydir
    subdir
        another_test = &lt;span class=&quot;dmstring&quot;&gt;&quot;Another test!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Easy as pie. (The kind you buy, not the kind you make, that's not always easy at all!)&lt;br&gt;
&lt;br&gt;
The next handy savefile trick allows you to save data to a temporary or random file, to do this you simply don't provide a file name to the new() call when making the savefile datum. This is where the 'name' variable comes in handy. It'll let you view what the file's name is, even if it has been randomly generated.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(F) &lt;span class=&quot;dmcomment&quot;&gt;// Just in case&lt;/span&gt;
    src &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;File is named: &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[F.name]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Most useful for making your own dynamic data storage system or savefiles that aren't based on a key or ckey.&lt;br&gt;
&lt;br&gt;
Sometimes you'll need to prevent other worlds or programs from accessing a savefile at the same time as you are, luckily the savefile datum provides procs allowing to lock and unlock the file. When locked the savefile can't be accessed by any other programs.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
F.Lock(-1)
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;test&quot;&lt;/span&gt;] &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;test&quot;&lt;/span&gt;
F.Unlock()
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This example will lock the file while it saves the data to it, the argument for Lock() is a timeout, it is measured in seconds; -1 means no timeout. This lets you lock the file without having to worry about unlocking it, simply set a timeout and it'll automatically unlock when the timer expires.&lt;br&gt;
&lt;br&gt;
Now you're probably wondering 'how do I edit these files manually?' -- the answer is simple and of course provided in the form of a couple of savefile procs. The ImportText() and ExportText() procs allow you to dump the savefile into readable text and then to dump it back into savefile format.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/output_file = file(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.txt&quot;&lt;/span&gt;)
fdel(output_file) &lt;span class=&quot;dmcomment&quot;&gt;// So you don't get overlaping values.&lt;/span&gt;
F.ExportText(&lt;span class=&quot;dmstring&quot;&gt;&quot;/&quot;&lt;/span&gt;,output_file)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This example will dump the contents of mysave.sav into mysave.txt. Now once you're done editing the file you'll want to convert it back, of course.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/input_file = file(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.txt&quot;&lt;/span&gt;)
F.ImportText(&lt;span class=&quot;dmstring&quot;&gt;&quot;/&quot;&lt;/span&gt;,input_file)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Simple as that. You'll notice that the first argument of both procs was set to &quot;/&quot;, this is just telling the system to export/import everything under the / directory. You can set this value to any directory in the file to make only that data get dumped.&lt;br&gt;
&lt;br&gt;
Now you're probably thinking 'Wait! That means anyone with access to the files can edit them!', sure does. The most common and easiest method to stop people from editing their files is a simple hash check. You store a hash in the savefile that equals some value that can only be reached using valid data from that save, then you check that hash against the same process to make sure nothing has been altered.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;test&quot;&lt;/span&gt;] &amp;lt;&amp;lt; test
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;other_test&quot;&lt;/span&gt;] &amp;lt;&amp;lt; other_test
F[&lt;span class=&quot;dmstring&quot;&gt;&quot;hash&quot;&lt;/span&gt;] &amp;lt;&amp;lt; md5(&lt;span class=&quot;dmstring&quot;&gt;&quot;myhash_&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[test]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;_blah_&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[other_test]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will create a hash that makes use of some plain-text and the values of the two variables being stored. Now we check to make sure the data is valid when the file is loaded.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/savefile/F = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;mysave.sav&quot;&lt;/span&gt;)
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    test_loaded = F[&lt;span class=&quot;dmstring&quot;&gt;&quot;test&quot;&lt;/span&gt;]
    other_loaded = F[&lt;span class=&quot;dmstring&quot;&gt;&quot;other_test&quot;&lt;/span&gt;]
    hash_loaded = F[&lt;span class=&quot;dmstring&quot;&gt;&quot;hash&quot;&lt;/span&gt;]
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(md5(&lt;span class=&quot;dmstring&quot;&gt;&quot;myhash_&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[test_loaded]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;_blah_&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[other_loaded]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;) != hash_loaded)
    src &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Savefile tampering detected!&quot;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;del&lt;/span&gt;(src)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
From reading you probably realized exactly what this is doing, it's just checking the loaded values against the same combination that was used to create the hash. This should produce an identical hash to the one being stored if no data has been altered.&lt;br&gt;
&lt;br&gt;
Some people have even taken to encrypting the contents of the savefile completely. Unfortunately this method has had little good success, the most well-known instance of this method going wrong was from Leftley's Lode Wars game, where after so much saving and loading was done the data would corrupt itself and become impossible to use.&lt;br&gt;
&lt;br&gt;
So remember, savefiles aren't just for saving players, they can be used as entirely self-contained data structures.&lt;br&gt;
&lt;br&gt;
Until next time!</description>
        </item>
                <item>
            <title>MySQL and BYOND</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=79592</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=79592</guid>
            <pubDate>Thu, 20 Aug 2009 12:43:39 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=79592#comments</comments>
            
            <description>Recently the usage of MySQL with BYOND has taken a step forward and is no longer limited to people running their games on Linux. This has opened the door for many new advancements in data management.&lt;br&gt;
&lt;br&gt;
Unfortunately not many people know how to use the library yet, this article will hopefully shed some light on it for them.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;The DBConnection datum&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
The DBConnection datum is what handles the entire connection and authentication process, using the Connect() proc associated with the datum.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Setting some variables up for use later&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
A good way to keep from having to type too much when using MySQL with BYOND is to define a few global variables for usage later in the code. The most common of these are the DBI string, the username, and the password.&lt;br&gt;
&lt;br&gt;
The DBI (database independent interface) is a string you pass through the MySQL library to tell your server you're connecting to a MySQL database and not another type of database. The stucture of the DBI is very important.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/DBI = &lt;span class=&quot;dmstring&quot;&gt;&quot;dbi:mysql:&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[my_database]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[my_server]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[server_port]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Lets take this apart, 'dbi:mysql:' is what tells the server to access the MySQL daemon running on it, [my_database] would be the database you want to connect to, [my_server] would be the server, which is usually 'localhost'; and the [server_port] would be the port MySQL is running on, usually 3306.&lt;br&gt;
&lt;br&gt;
Next you'll want to make a variable for your username and your password.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    username = &lt;span class=&quot;dmstring&quot;&gt;&quot;Myuser&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Now wait, before you store your password as a plain-text variable you need to remember that these values can be accessed by anyone with the dmb file, that's not good! So lets not store it as plain text, we'll generate it at runtime.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/GeneratePassword()
    &lt;span class=&quot;dmcomment&quot;&gt;// Lets say your password is 'mypassword'&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dmstring&quot;&gt;&quot;my&quot;&lt;/span&gt; + &lt;span class=&quot;dmstring&quot;&gt;&quot;p&quot;&lt;/span&gt; + &lt;span class=&quot;dmstring&quot;&gt;&quot;assw&quot;&lt;/span&gt; + &lt;span class=&quot;dmstring&quot;&gt;&quot;ord&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
That should stop most would-be password thieves but not all of them. To take it to the next level you'd want to make use of ascii2text() to really throw them off.&lt;br&gt;
&lt;br&gt;
Now just store the result of the proc in a variable or even use it within Connect() (like I'm going to do)&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Using Connect() to make a connection to your database&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
The first part of any MySQL operation is of course connecting to your database.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    DBConnection/my_connection = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()

    connected = my_connection.Connect(DBI,username,GeneratePassword())
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Now the value of 'connected' will be null of the connection fails, otherwise it means the connection was a success.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!connected)
    usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Oh no! The database connection failed!&quot;&lt;/span&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt;
    usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;The database connection was a success!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Now you have an error message, but no real details. This brings me to my next proc example...&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Using ErrorMsg() to find out what's wrong&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
All of the datums of the DB library have an ErrorMsg() proc, this proc will return an error string if a connection or query goes wrong. This is very helpful for debugging your application.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!connected)
    usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Connection failed: &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[my_connection.ErrorMsg()]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will give you any details as to why the connection failed.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Disconnect() and IsConnected()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
These two functions do exactly what they say they do, Disconnect() will disconnect you from your database. IsConnected() will return true if a connection is already established, false otherwise.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Quote(string)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This function is used to sanitize strings you intend to pass through a MySQL query, this will prevent things like injection attacks and malformed queries.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/mystring = my_connection.Quote(&lt;span class=&quot;dmstring&quot;&gt;&quot;How's everybody?&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This example will cause 'mystring' to equal &quot;How\'s everybody?&quot; which keeps MySQL from assuming the usage of ' is a query terminator.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Using NewQuery() for quick queries&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
The NewQuery() proc is used for quick database queries without having to manually create a DBQuery datum and all of that. It's a shortcut, that's all.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/DBQuery/qry = my_connection.NewQuery(&lt;span class=&quot;dmstring&quot;&gt;&quot;SELECT * FROM `my_table`&quot;&lt;/span&gt;)
qry.Execute()
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Which is the same as:&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/DBQuery/qry = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;&quot;SELECT * FROM `my_table`&quot;&lt;/span&gt;)
qry.Execute()

&lt;span class=&quot;dmcomment&quot;&gt;// And...&lt;/span&gt;

&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/DBQuery/qry = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()
qry.Execute(&lt;span class=&quot;dmstring&quot;&gt;&quot;SELECT * FROM `my_table`&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
We'll get into how to use the DBQuery object next.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;The DBQuery datum, talkin' to the database&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
This is where you actually work with the database, the DBQuery datum is used to execute MySQL queries on the active MySQL connection.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Getting data from the database&lt;/b&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/DBQuery/qry = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()
qry.Execute(&lt;span class=&quot;dmstring&quot;&gt;&quot;SELECT * FROM `my_table`&quot;&lt;/span&gt;)
&lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(qry.RowCount() &amp;gt; 0)
    &lt;span class=&quot;dmkeyword&quot;&gt;while&lt;/span&gt;(qry.NextRow())
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/list/row_data = qry.GetRowData()
        &lt;span class=&quot;dmkeyword&quot;&gt;for&lt;/span&gt;(&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/D &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; row_data)
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[D]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[row_data[D]]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This example will grab every value from the 'my_table' table and display it.&lt;br&gt;
&lt;br&gt;
There are a few procs I used in here, how about I explain what they do?&lt;br&gt;
&lt;br&gt;
&lt;b&gt;RowCount()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc simply returns the amount of rows the query picked up.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;NextRow()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc will fetch the next row of the database and return the values in a number-based list.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;GetRowData()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc takes the number-based list returned by NextRow() and gives you a nice friendly value-based list like list(&quot;mycolumn&quot;=&quot;myvalue&quot;).&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;The other DBQuery procs&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Columns&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc will return the Columns your query has affected, it is used to build the GetRowData() proc's information. It will return a DBColumn datum, which I will explain more later.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Connect(DBConnection)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc allows you to alter which DBConnection the DBQuery datum is associated with, simply pass a new DBConnection datum through it.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Execute(sql,cursor)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
You probably noticed I used this proc earlier, this is a very important function. The Execute() proc is what tells the query to, well, execute. Nothing will happen until this proc is called. When called without any arguments it will execute the query stored in the datum's 'sql' variable. The second argument is only important for advanced users, as most cursor-related stuff is. If you don't know what a cursor is you probably shouldn't be using them.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;RowsAffected()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
When using UPDATE or INSERT queries this proc will return the amount of rows altered or added by the query.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Close()&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc will close out the query, making it impossible to continue to use the datum for any future action.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Quote(string)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Works exactly like DBConnection.Quote()&lt;br&gt;
&lt;br&gt;
&lt;b&gt;SetConversion(column,conversion)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
This proc will convert a column from one data type to another.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;&lt;font size=&quot;+1&quot;&gt;Adding and removing data&lt;/font&gt;&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Another major part of MySQL usage is the ability to add and remove new data, this is done by simply executing an INSERT or DELETE query. Check the MySQL manual on how to form these queries.&lt;br&gt;
&lt;br&gt;
When adding or removing data the use of RowsAffected() is good for making sure the process was a success.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;&lt;font size=&quot;+1&quot;&gt;The DBColumn datum&lt;/font&gt;&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
The DBColumn datum is used to store information relating to a data column retrieved from your database. It can be created by calling the Columns() proc during a query.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;The variables&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
name -- This is the name of the column.&lt;br&gt;
&lt;br&gt;
table -- This is the table that contains the column.&lt;br&gt;
&lt;br&gt;
position -- This is the (1-based) position of the column in the table.&lt;br&gt;
&lt;br&gt;
sql_type -- This is the type of data the column contains, such as INT, TEXT, BIGINT, etc...&lt;br&gt;
&lt;br&gt;
length -- This is how much data the column contains.&lt;br&gt;
&lt;br&gt;
max_length -- This is the most data the column can contain.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;The SqlTypeName(type) proc&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
The SqlTypeName() proc is used to convert the library-defined data type constants into text for easy reading.&lt;br&gt;
&lt;br&gt;
That's about it, folks. There's not much else to using MySQL, all you need to learn now is the SQL syntax, which can be learned from the &lt;a href=&quot;http://mysql.com&quot;&gt;MySQL website&lt;/a&gt; -- and as always, the &lt;a href=&quot;http://byond.com/members/DMCGI&quot;&gt;DMCGI Guild&lt;/a&gt; is a good place to ask for help in matters relating to web-type DM usage (which MySQL falls under).</description>
        </item>
                <item>
            <title>Easy forms with htmllib</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=79585</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=79585</guid>
            <pubDate>Tue, 18 Aug 2009 21:54:19 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=79585#comments</comments>
            
            <description>In my last review I mentioned the htmllib library by Dantom. This library makes it easy to use HTML forms in your game and on your DMCGI website.&lt;br&gt;
&lt;br&gt;
The library functions using a /Form datum, this datum contains various procs and vars that make your life using forms much, much easier.&lt;br&gt;
&lt;br&gt;
First lets take a look at the form datum's variables.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;/Form variables&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;submit&lt;/b&gt; (Default: &quot;Submit&quot;)&lt;br&gt;
This variable will contain the text to be displayed on the form's submit button.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;reset&lt;/b&gt; (Default: &quot;Reset&quot;)&lt;br&gt;
This variable will contain the text to be displayed on the form's reset button.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_url&lt;/b&gt; (Default: null)&lt;br&gt;
This variable tells the form where to send its data when submitted (the form's action parameter).&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_sub_path&lt;/b&gt; (Default: null)&lt;br&gt;
This variable contains any extra path information that is to be passed through the form, any text in this variable will be appended to the end of the form_url.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_title&lt;/b&gt; (Default: null)&lt;br&gt;
This variable contains any text you wish to pass to the 'title' parameter of your form.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_window&lt;/b&gt; (Default: null)&lt;br&gt;
If you have any extra browse() data you wish to pass this is how you do it, this variable is basically the same as the second argument of browse().&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_reusable&lt;/b&gt; (Default: null)&lt;br&gt;
When set this variable will allow the user to submit the same form more than once, otherwise the form will expire and cannot be sent again.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_cgi_mode&lt;/b&gt; (Default: null)&lt;br&gt;
This variable tells the form whether it should be processed by client.CGI or not. This is automatically set when used in CGI mode.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_method&lt;/b&gt; (Default: &quot;get&quot;)&lt;br&gt;
This variable sets the 'method' parameter of your form, the most common values are 'get' and 'post'. When using forms in Dream Seeker the method MUST be 'get' otherwise the form won't submit.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;form_extra&lt;/b&gt; (Default: null)&lt;br&gt;
This variable contains any text you wish to include into the form tag of your page. Useful for things like javascript calls and parameter settings.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;The procs and how to use them&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;DisplayForm(mob)&lt;/b&gt;&lt;br&gt;
Calling this proc with a mob argument will cause your form to be displayed to that mob.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/Form/my_form/frm = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()
frm.DisplayForm(usr)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;SubmitForm(href,mob)&lt;/b&gt;&lt;br&gt;
Calling this function will force the Form datum to submit its data with. The 'href' parameter contains any extra data you want to pass through.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/Form/my_form/frm = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()
frm.SubmitForm(null,usr)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;GetSelfUrl(params,mob)&lt;/b&gt;&lt;br&gt;
Calling this will return a friendly URL with all of your form parameters intact. (eg: http://myurl.com/mypage.dmb?form=/Form/ my_form&amp;amp;param=somevalue)&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;Initialize()&lt;/b&gt;&lt;br&gt;
This proc is called when DisplayForm() is called, it is most useful for detecting when a certain form has been loaded.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
Form
    my_form
        Initialize()
            world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;My form has been displayed!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;ProcessForm()&lt;/b&gt;&lt;br&gt;
This proc is called when the form is finished processing. Useful for detecting when data has been successfully passed.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
Form
    my_form
        ProcessForm()
            world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;My form has finished processing!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;HtmlLayout()&lt;/b&gt;&lt;br&gt;
This proc is used to determine the HTML layout of the form.&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
Form
    my_form
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/some_input
        HtmlLayout()
            &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dmstring&quot;&gt;{&quot;
            Please submit this value: &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[some_input]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&amp;lt;br&amp;gt;
            &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[submit]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[reset]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This example shows how to display an input box with your own text, as well as the submit and reset buttons.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;Input types&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
As anyone who's ever used a HTML form before knows, there are many input types, not just text fields. This section will explain how to make use of the _interface setting for form variables.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
Form
    my_form
        &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
            text_input
            password_input
            password_input_interface = PASSWORD
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
Notice how I used the variable password_input_interface, this tells the system to check for a variable called password_input and change the input type of it to 'password'. This works for many different types of inputs.&lt;br&gt;
&lt;br&gt;
Here is a list of all of the valid _interface types avaliable:&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
TEXT -- This is the default value, a simple text input.&lt;br&gt;
&lt;br&gt;
PASSWORD -- A masked input for passwords.&lt;br&gt;
&lt;br&gt;
TEXTAREA -- A multi-line text input, you can also set the _size of a variable to use this type.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    big_input
    big_input_size = &lt;span class=&quot;dmstring&quot;&gt;&quot;10x10&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This will make big_input a 10x10 textarea.&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
SELECT -- A simple single selection input. Any variable with _values will be set to this type.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    select_input
    select_input_values = list(&lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;Two&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;Three&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This will create a selection box with the three values included.&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
MULTI_SELECT -- This is the same as SELECT except it allows the user to select more than a single item.&lt;br&gt;
&lt;br&gt;
CHECKBOX -- This creates a checkbox. When checked the variable will be true (1), if not it'll be false (null/0)&lt;br&gt;
&lt;br&gt;
CHECKLIST -- This allows you to group checkboxes together so that their values are passed back as a _values list.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    checklist_input
    checklist_input_interface = CHECKLIST
    checklist_input_values = (&lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;Two&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;Three&quot;&lt;/span&gt;)
ProcessForm()
    &lt;span class=&quot;dmkeyword&quot;&gt;for&lt;/span&gt;(&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/V &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; checklist_input_values)
        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[V]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[checklist_input_values[V]]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This will output something similar to 'One = 1' 'Two = 0' and so on, depending on the checked value of the boxes in the list.&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
RADIO -- This creates a radio box, this interface isn't meant to be used on its own, a few variable control types are included to allow for its use.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    radio_input
    radio_input_interface = RADIO
    radio_input_1 = &lt;span class=&quot;dmstring&quot;&gt;&quot;One&quot;&lt;/span&gt;
    radio_input_2 = &lt;span class=&quot;dmstring&quot;&gt;&quot;Two&quot;&lt;/span&gt;
    radio_input_3 = &lt;span class=&quot;dmstring&quot;&gt;&quot;Three&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
This will create three radio boxes in the same group, only one of the three can be selected at any time.&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
RADIO_LIST -- This works exactly like CHECKLIST except with radio inputs.&lt;br&gt;
&lt;br&gt;
HIDDEN -- This allows you to make a hidden form element, this element won't be displayed on the form.&lt;br&gt;
&lt;br&gt;
BUTTON -- This allows you to create a custom button. To interact you simply define a proc like varClick().&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    button_input = &lt;span class=&quot;dmstring&quot;&gt;&quot;My Button&quot;&lt;/span&gt;
    button_input_interface = BUTTON
&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;
    button_inputClick()
        usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;You clicked the button!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;tt&gt;&lt;br&gt;
PROMPT -- This works just like BUTTON except the return value of whatever you prompt the user for (file, icon, whatever) is returned by the Click() call instead of it just being called.&lt;br&gt;
&lt;br&gt;
PROMPT_FOR_(SOUND/ICON/FILE) -- The same as PROMPT except all of the dialog input is handled for you.&lt;br&gt;
&lt;br&gt;
SUB_FORM -- This allows you to include another /Form datum to be processed along with the parent form.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;
    sub_form = /Form/other_form
    sub_form_interface = SUB_FORM
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;Special variable amendments&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
As I noted in the previous section there are special amendments to variables you can use such as _interface and _size. This section will go over the ones I haven't mentioned yet.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;_maxlen&lt;/b&gt; When used on a text input this will control the maximum length the user can input into said control.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;_validate&lt;/b&gt; This controls whether variables using the _values system will validate their values before processing and return an error if a value is considered incorrect. It is on by default.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;_hidden&lt;/b&gt; This works a lot like the HIDDEN interface except that variables with _hidden are automatically placed even if you override HtmlLayout().&lt;br&gt;
&lt;br&gt;
&lt;b&gt;_wrap&lt;/b&gt; This controls the wrapping behavior of the TEXTAREA input control, it has three possible values. NO_WRAP for no wrapping, SOFT_WRAP for simple wrapping with no newlines, and HARD_WRAP for simple wrapping with newlines.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;br&gt;
More information about the usage and special tricks of the htmllib can be found inside of the library's documentation. And as always the &lt;a href=&quot;http://byond.com/members/DMCGI&quot;&gt;DMCGI Guild&lt;/a&gt; is always happy to answer questions and help you out.</description>
        </item>
                <item>
            <title>Websites with DM</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=79114</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=79114</guid>
            <pubDate>Mon, 17 Aug 2009 16:51:53 GMT</pubDate>
            
            <comments>http://www.byond.com/members/DreamMakers?command=view_comments&amp;post=79114#comments</comments>
            
            <description>Not many people know that you can use DM to make a website, all you need is a server with BYOND installed and you're set. (You'll need to configure your web server if you want to use the dmb extension, though).&lt;br&gt;
&lt;br&gt;
The CGI library by Dantom provides the interface for creating powerful dynamic websites using DM.&lt;br&gt;
&lt;br&gt;
Using the CGI/Topic() proc or the &lt;a href=&quot;http://byond.com/hub/Dantom/htmllib&quot;&gt;htmllib&lt;/a&gt; library by Dantom you'll be able to do everything from a simple page with dynamic content to a powerful forum. You're only limited by what you can output using DM.&lt;br&gt;
&lt;br&gt;
The most popular method of using Dantom.CGI (DMCGI from here on) is to include the htmllib library along side with it. The htmllib provides a datum-based page handler system that allows you to use forms and process various data. I'll detail the usage of the htmllib in my review of it; for now lets move on to the more powerful method...&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;CGI/Topic()&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
The Topic() proc is the function that BYOND uses to handle incoming data and internal links. CGI/Topic() is no different, it allows your world to interact with links and incoming data; the difference is that CGI/Topic() spits the resulting data back out in a way a browser can read and display.&lt;br&gt;
&lt;br&gt;
The proc takes two arguments, the first is most commonly called 'href' this variable will contain all of the parameters passed to your world in text format (eg: &quot;action=test&amp;amp;other=something&quot;). The second argument is commonly called 'href_list' or 'prms' this is generated by passing the first argument through params2list().&lt;br&gt;
&lt;br&gt;
Usage of the href argument is generally for checking if any parameters are passed or not, since it's easier to make use of href_list to read and use the parameters.&lt;br&gt;
&lt;br&gt;
Here are a few examples of how to use CGI/Topic()&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
CGI/Topic()
    usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will display a simple 'Hello world' message to the person viewing the page.&lt;br&gt;
&lt;br&gt;
In CGI/Topic() usr will always be the person accessing the page. Anything output will be displayed on the page, you can also use browse() which will act identical to simple output when the world is running in CGI mode.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
CGI/Topic(href)
    &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!href)
        usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;&amp;lt;a href=\&quot;?clickhere\&quot;&amp;gt;Click here&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href == &lt;span class=&quot;dmstring&quot;&gt;&quot;clickhere&quot;&lt;/span&gt;)
        usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Thanks for clicking!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will present the user with a link, and upon clicking that link it will display a thank you message.&lt;br&gt;
&lt;br&gt;
When only using a single parameter with no value it's easy enough to just use href alone.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
CGI/Topic(href,href_list[])
    &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!href)
        usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;&amp;lt;a href=\&quot;?page=one\&quot;&amp;gt;Page one&amp;lt;/a&amp;gt; or &amp;lt;a href=\&quot;?page=two\&quot;&amp;gt;Page two&amp;lt;/a&amp;gt;?&quot;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href_list[&lt;span class=&quot;dmstring&quot;&gt;&quot;page&quot;&lt;/span&gt;])
        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href_list[&lt;span class=&quot;dmstring&quot;&gt;&quot;page&quot;&lt;/span&gt;] == &lt;span class=&quot;dmstring&quot;&gt;&quot;one&quot;&lt;/span&gt;)
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;This is page one!&quot;&lt;/span&gt;
        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href_list[&lt;span class=&quot;dmstring&quot;&gt;&quot;page&quot;&lt;/span&gt;] == &lt;span class=&quot;dmstring&quot;&gt;&quot;two&quot;&lt;/span&gt;)
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;This is page two!&quot;&lt;/span&gt;
        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt;
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Whoops! This isn't a page at all!&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will present the viewer with two links, both leading to different output.&lt;br&gt;
&lt;br&gt;
Since the URL parameters contain a parameter with a value the href_list will contain a list element named after the parameter with an associated value equal to the value of the passed parameter.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;BYOND Key Support&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
One of the best features of DMCGI is the ability to make use of the key variable to see the viewer's BYOND key. The library provides a Login() and Logout() proc which will lead the user to the BYOND login page. Both procs take a string as an argument, this argument is used to redirect the user back to a certain page after a successful login or logout.&lt;br&gt;
&lt;br&gt;
The library also provides a variable called 'authenticate' which when set to true will force the viewer to login before being able to access the page.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
CGI/Topic(href)
    &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!href)
        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(usr.ckey == &lt;span class=&quot;dmstring&quot;&gt;&quot;guest&quot;&lt;/span&gt;)
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;You need to &amp;lt;a href=\&quot;?login\&quot;&amp;gt;login&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt;
            usr &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&quot;Welcome &lt;/span&gt;&lt;span class=&quot;dmbrace&quot;&gt;[usr.key]&lt;/span&gt;&lt;span class=&quot;dmstring&quot;&gt;! (&amp;lt;a href=\&quot;logout\&quot;&amp;gt;logout&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href == &lt;span class=&quot;dmstring&quot;&gt;&quot;login&quot;&lt;/span&gt;) 
            src.Login(&lt;span class=&quot;dmstring&quot;&gt;&quot;http://myurl.com&quot;&lt;/span&gt;)
        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(href == &lt;span class=&quot;dmstring&quot;&gt;&quot;logout&quot;&lt;/span&gt;)
            src.Logout(&lt;span class=&quot;dmstring&quot;&gt;&quot;http://myurl.com&quot;&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will show the viewer a message informing them that they need to be logged in if they're not already logged in (their key will be 'Guest' if not logged in) and a welcome message if they are.&lt;br&gt;
&lt;br&gt;
Calling src.Login() will direct the viewer to the login page, the argument will redirect them back to &quot;http://myurl.com&quot; after they've logged in. Logout() works the same, except it logs them out.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;Other /CGI procs&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;GetEnv(name)&lt;/b&gt;&lt;br&gt;
The GetEnv() proc allows you to grab system environment variable values, which is helpful for things like telling what kind of system the world is running on.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;SetCookie(name,value,expires,domain,path,secure)&lt;/b&gt;&lt;br&gt;
The SetCookie() proc allows you to set HTTP cookies for the viewer, just like any web language does.&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
SetCookie(&lt;span class=&quot;dmstring&quot;&gt;&quot;mycookie&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;rocks&quot;&lt;/span&gt;,world.realtime+36000,&lt;span class=&quot;dmstring&quot;&gt;&quot;myurl.com&quot;&lt;/span&gt;,&lt;span class=&quot;dmstring&quot;&gt;&quot;/&quot;&lt;/span&gt;,0)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
This will set a cookie known as 'mycookie' with the value 'rocks' that expires roughly 360 minutes after it is set. The domain argument tells the browser what domains/subdomains to accept the cookie from, and the path tells it what file path to accept it from. The secure setting will make the cookie secure, which will prevent it from being edited.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;WebifyByondUrl(url)&lt;/b&gt;&lt;br&gt;
This proc is depreciated, it used to change a URL into an old-style dms.cgi URL for usage in joining BYOND worlds.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;Reroute(url)&lt;/b&gt;&lt;br&gt;
This proc will send the proper browser headers to cause the page to redirect to the URL specified. You can't output any text to the page before using this proc.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;HttpHeader()&lt;/b&gt;&lt;br&gt;
This proc is automatically called and you should never need to manually call it. It sends the required HTTP headers to the page output so that the browser will recognize it as something valid to display.&lt;br&gt;
&lt;br&gt;
&lt;font size=&quot;+1&quot;&gt;&lt;b&gt;The /CGI variables&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;content_type&lt;/b&gt; (Default: &quot;text/html&quot;)&lt;br&gt;
The content_type variable allows you to change what content header is sent to the browser, this will let you do things like displaying the page as plain text or even generating images.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;expires&lt;/b&gt; (Default: 0)&lt;br&gt;
The expires variable tells the browser how long to cache the data on the page, the default 0 prevents any caching from being done, since most CGI content is dynamic.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;http_headers&lt;/b&gt; (Default: null)&lt;br&gt;
The http_headers variable will contain newline-separated headers that are sent by the page, this is useful if you're debugging the entire output of your CGI.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;default_form, waiting_form&lt;/b&gt; (Default: null)&lt;br&gt;
These are used in conjunction with htmllib, I'll explain them in the review for that library.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;authenticate&lt;/b&gt; (Default: 0)&lt;br&gt;
Then set to 1 (true) the authenticate variable will force the viewer to login before CGI/Topic() is even called.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;cookies&lt;/b&gt; (Default: empty list)&lt;br&gt;
The cookies variable contains all of the cookies avaliable to the CGI application. Cookies are only avaliable if set on the same domain and path as the application.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;params&lt;/b&gt; (Default: empty list)&lt;br&gt;
The params variable is a list of params passed to the world, this is later translated to the first argument of CGI/Topic().&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;header_done&lt;/b&gt; (Default: null)&lt;br&gt;
The header_done variable is set to true when any non-header output is sent to the browser. This is useful for telling if you can send new headers manually or not.&lt;br&gt;
&lt;hr&gt;
&lt;br&gt;
&lt;b&gt;byond_mode&lt;/b&gt; (Default: 0)&lt;br&gt;
The byond_mode variable is automatically set to 1 if the application is running in Dream Seeker and not the browser. Useful for altering behavior between the two.
&lt;hr&gt;
&lt;br&gt;
&lt;br&gt;
That's about it, that should be all you need to know to get started with DMCGI. If you have any questions or need any help be sure to check out the &lt;a href=&quot;http://byond.com/members/DMCGI&quot;&gt;DMCGI Guild&lt;/a&gt;. You can find more information on advanced DMCGI techniques and setting up a server to use DMCGI there.&lt;br&gt;
&lt;br&gt;
And remember, there may be more information avaliable in the included documentation of the library, be sure to read it over before you get started!</description>
        </item>
            
    </channel>
</rss>

