Today, we're going to take the Oocly package we made last week and we're going to rearrange things. We're not going to add any new functionality - instead we're going to focus on organising it into a more sensible form (programmers call this refactoring
We're going to learn a basic framework for making packages that will make them significantly easier to write, modify, etc. Thus far we've been in that weird phase of learning where what we're doing technically works, but isn't actually how "the pros" do it. After this week, your packages will look basically like my packages. Edit: After the beginning of next week. We have one more thing to cover.
This is going to be a hard week. Take it step by step. This is where we hit the stuff that's going to be a little more tough to understand. Take it step by step.
Once we've gotten our hands dirty
with all of this, we'll be well-positioned to get our hands filthy
next week on a more substantive problem involving GMCP and some actual combat utility.
Before we start, make sure you've finished Part 2. Everything we're going to do today uses Part 2. You should have three aliases done for OOC tells, OOC replies, and OOC retells.
In Chrome, ctrl+shift+j will open the console (you may have to click the Console
We're going to start today by talking about variables.
There are a lot of analogies for variables. None of them are perfect. We'll start ours a little lower than usual though and I think that might make it a little less imperfect.
First, we need to talk about memory
. When we talk about memory, we're not talking about your hard drive, we're talking about your RAM. Your computer's memory is a lot like a post office with a million little slots (actually, it has about a billion
little slots per gigabyte of RAM in your computer!).
Every one of those slots has an address, exactly like a post office box. If you want to get at the stuff in that box, you tell the postal worker that address. If you're going to need to get at the stuff in the box later, you need to remember that address (How do you remember the address? Why you put it in a post office box of course!).
But we have some problems. All the boxes are pretty small and some of our stuff is going to take up more than one box. We really don't want to deal with that. We also don't want to have to type or remember the addresses since they're really long and not very meaningful. We don't want to deal with phone numbers, we want our phone to have a named contact so we never have to think about whatever the random number the phone actually uses to call them is.
That's where the concept of a variable comes in. When we use a variable, we'll ask the post office to store something for us, tell it the name we want to use, and they can get it for us if we give them that name.
The way we tell the post office we want them to get ready to store something is by declaring
and it looks like this:
The main restriction is that our labels can't have spaces in them. You can write it like myFirstVariable instead of my_first_variable (or almost any other way you want that doesn't use spaces), but almost everyone agrees the underscore is easier to read. Variable names shouldn't be capitalised - you can technically capitalise them, but every programmer reading your code will be confused because capitalised names are conventionally used for only one very special kind of variable that we'll probably never talk about.
We can do a few at a time too, we just stick commas between them:
let my_first_variable, my_second_variable;
Once we've got our variable declared, we can tell the post office what to store for us under that label. We do this with a normal equals sign. Let's store the number 5 under the label my_first_variable and the string "say Hello!" in my_second_variable.
my_first_variable = 5;
my_second_variable = "say Hello!";
We can change what we've got stored too. Let's add 1 to our 5:
my_first_variable = my_first_variable + 1;
That says: I want to store something under the label my_first_variable and the thing I want to store is whatever was in my_first_variable + 1. We only declare a variable once, but we can assign
my_first_variable += 1;
That means the same thing as my_first_variable = my_first_variable + 1;
Before we continue, let's get one thing straight: those words are instructions, they aren't the variable. If you run your script, then delete that line, that doesn't undo what you've done. You're handing the post office worker a scrap of paper that says what the post office worker should do. Tearing up the piece of paper after you've given it to the post office worker doesn't tear up the thing you had the post office worker do. That line of text in your script is not your variable, it's just an instruction for what to do with your variable - the actual variable is invisible and lives inside your computer and the only way you can interact with it is to ask the post office worker to do something with it for you. Don't get confused and confuse a recipe for an apple pie with the actual apple pie it makes.
But we can store more fancy stuff too. Remember our function send_command? Well "send_command" isn't actually the function. The function itself is a list of things to do. "send_command" is just the label
on that function that lets us ask the post office worker to go get it for us. Let's ask the post office worker to go get that function for us and to store it under a new label. To save ourself some typing, we can actually do the first assignment to a variable at the same time as we declare it (this is called initialising
let my_third_variable = send_command;
Now the function that was labelled "send_command" is also
labelled "my_third_variable". Don't get confused here, it's not a copy of the function, it's the same function! We just asked them to put a second label on the boxes where the function is stored.
And to show that there's no magic here, let's use this new variable just like we used send_command, and we'll use our other variable just like we've been using a regular string:
let my_third_variable(my_second_variable, true);
This is exactly the same thing as send_command("say Hello!", true);
Remember that we only ever use let
once to declare things. A common beginner mistake is confusing initialising variables and assigning to them. When we assign to them, we just use the variable name and an equals sign. We only use let
when we want to declare a variable for the first time (and initialising is just a shortcut for declaring and then immediately doing the first assignment).
Make sure this all makes sense before moving on.
Don't worry too much about this, but I want to forewarn you about some things you might run into in other people's code.
We're using let
in it instead. var does some really strange things and let is better and more intuitive in every way. There is absolutely no reason in your scripting to use var. Just don't do it. If you see a var in someone else's code, just think of it as let. If it doesn't make sense, either just accept it and move on or google the horrifying truth about how var actually works and pity the poor souls who wrote code before you.
You might also see
variables declared with const
. const is also new and it means the same thing as let
except you're only allowed to assign to it one time. It's a constant
. So you might do something like const PI = 3.14; because you know pi will never change. If you declare something with const and try to change it, Nexus will yell and you because you told it you weren't going to change it and then you tried to change it. This is yet another safety you can choose to use to protect yourself from yourself. It's a good habit to get into. Due to some old conventions, many people write the names of constants in all caps so they can remember they're constants, though you don't have to. If you get deeper into programming, you'll discover a whole world of people who think you should only ever
use constants (never normal variables) called functional programmers
(spoiler alert: these people are absolutely right - but you'll be writing simple enough things in Nexus that you don't need to worry about it).
Cleaning up Oocly Step 1
Let's use variables to make our Oocly functions more readable.
The ideal situation is to have each line of our program do one thing
. That makes it a lot easier to understand what the hell is going on when we come back to this a year from now or send it to someone else.
Our OOC tell looks like this right now:
send_command("tell " + args + " *achaean OOC: " + args.toUpperCase() + args.slice(1), true);
let recipient = args; // Now we don't have to remember that args is the recipient, we can just use a name that makes sense and remember that instead
let message = args; // Same for the message
let first_letter_of_message = message;
first_letter_of_message = first_letter_of_message.toUpperCase(); // There's no let here because we're just assigning, we already declared our variable (when we initialised it in the last line)
let rest_of_mesage = message.slice(1);
message = first_letter_of_message + rest_of_message; // These variables are strings, so the + between them concatenates them into one string
let to_send = "tell " + recipient + " *achaean OOC: " + message;
Make sure you understand this.
That's a little extreme, but it shows how we can use variables to break things up. How much you want to break things up like this is up to you, but doing this lets us focus on doing one thing at a time
. When we designed this script, we broke our problem down into progressively smaller pieces: first we figured out how to send a string, then we figured out how to glue our little strings together into the whole string, then we figured out how to split off the first letter of something, then we learned to uppercase it, then we learned to split the rest of the letters off, etc. Using variables like this lets us write our code (and read
our code) in a way that reflects that.
Don't fall into the trap of thinking that putting it all on one line is better. This is the classic newbie mistake. You might worry that all those extra variables are a "waste", but that's like Bill Gates worrying that he's wasting pennies. It isn't worth his time to avoid wasting pennies. It isn't worth your time to avoid making "extra" variables. You might think you're gaining efficiency, but the comically tiny gain in efficiency will never amount to even a single second
spent looking at your code all crammed into one line and trying to understand what it's doing.
You're also likely to see another, similar style to this where all of the variables for some function or script get declared together at the top instead of declaring them just before you actually need them. Our code would look like this:
let recipient, message, first_letter_of_message, rest_of_message, to_send;
recipient = args;
message = args;
first_letter_of_message = message;
first_letter_of_message = first_letter_of_message.toUpperCase();
rest_of_mesage = message.slice(1);
message = first_letter_of_message + rest_of_message;
to_send = "tell " + recipient + " *achaean OOC: " + message;
I'll leave it up to you which style you think is easier to read. Sometimes people do a combination where they declare and
initialise all their variables at the beginning, but always before doing anything with them. Any of these are totally valid options.
Do this same thing for OOC reply and OOC retell. Make them as easy to understand as you possibly can. Add some comments too - put them on any line where you think that six months from now you might not remember how it works.