Introduction
Welcome to the green book! The point of this book is to provide insight to BYOND players looking towards contributing on the game they play on, or who decide to start their own BYOND project. The objective of this guide is to teach coders the Dream Maker programming language and its lesser-known details. If you find an error or you want to contribute, you can go check our GitHub. You can also join the coderbus discord if you need help with code or this guide itself
Be sure to choose the codebase you're using from the Change codebase
option top-left, so that this guide will show you the examples relative to it. Select BYOND raw
if you're not using any codebase (aka you're starting from scratch, an empty project).
Getting Started
This is where your journey with BYOND starts. The guide will not assume any sort of prior knowledge, such as how operators work. In this chapter, we'll discuss:
- Installing BYOND and starting a new DM project
- Writing a program that prints
Hello World
in the server's console
Installation
If you're reading this, you probably have BYOND installed already. When you install it to play games, you also install some other programs:
- Dream Maker
- Dream Daemon
- Dream Seeker
Dream Maker
The first is what you'll use to code. It's the IDE which you use to write code, compile and eventually run for testing purposes (although, for large projects, it's suggested to use Dream Daemon to run the code, since it's how you'd run it in a production environment).
By default, it is located in BYOND bin folder, accessible from wherever you installed byond (normally, Program Files(x86) ). You can also open it with the CTRL+M macro from BYOND itself.
Once opened, you will see a window separated in three parts, normally.
The file tree
The rectangle on the left with a white background is the file tree. It basically shows the files of your project the IDE cares about. This means, all DM related files (.dm, .dmi, .dme, dmf, dms, dmm), images and sounds. In particular, .dm and .dmm files will have a small box on the left of the filename, which you can mark. If there is a checkmark in said box, then the file is included in the .dme, which means it will be compiled when the .dme is compiled, otherwise it will be ignored. If you doubleclick a file, the IDE will attempt to open it in...
The working area
Aka the big gray area on the right, when you open a file it'll display it in this area. For .dm files, it'll show the file (text) contents, with syntax highlighting and the ability to also display indentation and line number, based on preferences. After writing some code, you'll have to compile it to be able to run it. You can do it from the Build
tab top left, or with the CTRL+K
hotkey. Compiling will lead to some text being displayed in...
The compiler output window
Aka the white rectangle on the bottom. When compiling code, info will be outputted in this part, in particular compile errors. If an error happens, you can doubleclick the line to automatically open the file containing the line, with said line highlighted. If no errors show up, the output will ultimately save a special .dmb file, which is basically the executable. Once you get this, you can proceed to run your code and see how it behaves.
Dream Daemon
When you build the .dmb executable, you can either simply run your code directly from Dream Maker from the Build
tab, or host a server through Dream Daemon. This is usually used for production stage, when you want to host a game for other people to be able to join. The interface is pretty simple, you feed it the .dmb file, eventually set a Port if you port forwarded one, choose whether your server should be visible to anyone or not, and specify the security level. Security level is for certain procs able to access system commands, such as shell()
. Some games may require you to allow those commands, such as Space Station 13, to work properly. To do so, set it to Trusted. Otherwise, if you want to block said calls, use Safe. More about this will be discussed in future.
Dream Seeker
This is simply the program you use to connect to servers. If you've ever played a game on BYOND, this is what you're running to play it.
Now that you know the basics, you can proceed to your first Hello World program.
Hello World
Open Dream Maker and let's write your first DM program. To do so, you must create a new environment or open an already existing one (the .dme file), from the File
tab top-left. If you're creating a new environment, select the project directory and its name, and the IDE will prompt you to create your first .dm file. Simply press OK, and the file will automatically open with some code already in it. Feel free to delete all of it, you won't need this yet.
Instead, if you're opening your codebase's .dme file, simply go to File
, create a new file (Location doesn't matter for this code) and go to the next step.
Printing Hello World
Try to compile this snippet and run it as we said in the previous chapter (CTRL+K, Build
and Run
):
/mob/Login()
world << "Hello world"
/mob/Login()
..()
to_chat(world, "Hello world")
Once ran, Dream Seeker will open and you will see Hello World printed on the top left of the window. Congratulations!
Anatomy of a DM program
So, what exactly happened? Basically, you're making something special happen when a mob
, which in this example is a player aka you, logs in. The special behaviour is outputting the string Hello World
to the whole world, which is basically only you in our example. Notice the indentation after the first line, it isn't an error, it's actually vital in DM programs. If you mess up the indentation, your program will fail to compile at best, or have undefined behaviour at worst. How you indent code is up to you, you can use spaces or tabs, as long as you're coherent in your whole project. Mixing indentation types up will cause your project to fail compiling.
Basic Concepts
This chapter covers concepts that are shares by nearly all programming languages, such as conditional statements, loops, variables, operators and the such. If DM is your first programming language, you have to read this. If not, quickly skimming over it may be useful to see DM's syntax for basic concepts.
Keywords used for the concept above and others cannot be used as names of variables, functions or such, or a conflict would happen. If you try to, a compiler error will warn you.
Variables
Variables are data containers, which, as the name implies, can get their data changed through assignment operations. If you want to store some data, you will use a variable. The basic syntax is:
var myVariable = initialValue
where var
is the keyword telling the compiler we're defining a new variable, myVariable
is the variable's name, which cannot be a reserved word like var
as we said previously. = initialValue
is used to assign an initial value to the variable. This is optional, and if omitted, the variable's value will be null
, a special value that means the variable holds nothing.
A key difference in other languages like C is that primitive variables don't need the user to define their type, you can do
var myVar = "Hello World"
myVar = 1
Without any sort of error. Even though this will work with any sort of var type, we will see futher on that it can cause issues when our variables hold objects and we try to access its methods or such, but we will expand on this later.
Type casting
As we said previously, variables can hold primitive data such as numbers, letters, booleans, but they can also hold objects, which is fundamental for an Object Oriented language like DM. Say you have an /obj/honk
object, you're fully able to assign it to a type-less var as we did before with our string and number, but you won't be able to actually access any of the object's data. For now, just remember that the syntax for typecasting is:
var/your/type/varname = initialValue
Data Types
Even though variables do not need to have their types defined for primitive data, different types still exist, and variables need their type defined if you are going to assign them an object and you plan to use the variable to access some of the object's properties.
Primitive types
Primitive types are types that do not need variables to be typecasted anyhow. This includes:
- Numeric values
1, 24.3, 3.14
- Strings
"a", "abc"
- Booleans
TRUE, FALSE
(which aren't anything different than the numeric value1
and0
) - Null
null
You can simply assign them to your variable, and access the variable content. In particular, notice how lists aren't considered a primitive type. Even though assigning a list to a var won't cause an error normally, it's bad practice to not typecast it, since a list is essentially an object, and you won't be able to access list methods and properties on a non-typecasted list. Null is considered a primitive type because it can be assigned to any var, and since null means basically no value, you aren't going to access any of its properties since it has none.
Object types
Object types are the core of any object oriented programming language, like Dream Maker. Since it is such an important project, it will be explained futher on in its own chapter.