What Is Typescript?

2018 Oct 27

You may have heard this in the past, but JavaScript is a loosely-typed language.

What does this mean? You can set things to arbitrary values, and the language will convert some things automatically, and try to infer what you mean– in an attempt at being flexible.

    var a = 1234; // Okay, a number.

    var b = "Hello" - a; // Uhh, what?

    console.log((b > a || b < a || b === a) ? "Yep." : "Nope");

    // Outputs "Nope." but won’t cause any errors, because it got converted
    // to a special type of Number called NaN (Not A Number)

Some cool features have made their way into the language over the years to offer keywords like const to give you the ability to make variable references immutable.

Note: that doesn’t quite apply to Arrays and Objects, because the initial reference to them is immutable, but the contents are mutable. Go figure, something else that’s complicated in the language!

You may have heard me talk about something called TypeScript, which is a superset of JavaScript that Microsoft created that gets compiled down to vanilla JS, and allows you to add type annotations to your code.

Type annotations look like this:

    // Define a type here..
    interface IProduct {
        id: string;
        name: string;
    }

    // Use it to guard the function here..
    function logProductField(providedProduct: IProduct, field: keyof IProduct): void {
        console.log(providedProduct[field]);
    }

    // Use it to guard properties/values here..
    const product: IProduct = { id: "abc123", name: "Example Product" };

    // Function call infers it here..
    logProductField(product, "name");

If you wanted to write defensive JavaScript, you might validate..

  • Provided product variable has a name,
  • Generally has the correct shape,
  • Maybe even provide thorough documentation for other developers to prevent them from making mistakes when using this function,

… but really, that’s all optional, because a developer could still make a typo or choose to do the wrong thing.

If however, you screw up in TypeScript, there’s a compiler that will catch it:

    logProductField(product, "banana");
    // Results in a compiler error:
    // [ts] Argument of type '"banana"' is not assignable to parameter of type '"id" | "name"'. [2345]

It’s pretty smart, and can infer a lot of things based on the types you’re moving around. You can even get a little more complicated, and make some flexible things called generics which can be applied to all kinds of types of things.

    // Require that what’s provided is at least an object that maps from strings to strings.
    function logObjectField<T extends Record<string, string>>(
        obj: T, field: keyof T
    ): void {
        console.log(obj[field]);
    }

The let you specify a flexible type that can be used throughout the function/code/logic, and make your code usable with many types of different object types, without needing to write a bunch of different functions for each specific type… hence the name: generics.

If you’re still reading, then you probably think this is interesting enough, here are some helpful links to learn from:

JavaScript Callbacks, Promises, and Async/Await

2018 Oct 20

In many places in our codebase, I see we use a lot of callbacks. This is common in a lot of places, especially coming from the jQuery world, for example:

callSomeFunction(12345, (result) => { ... });

By structuring a function this way, you will often hear some people refer to this as causing ‘callback hell’, because each function you want to call will nest..

callOneFunction(arg1, (result1) => {
    callSecondFunction(arg2, 12345, (result2) => {
        callThirdFunction("banana", (result3) => {
            // Will it ever end?
        }, () => {
            // Oh man, an error too?
        });
    });
});

A few issues can arise from this:

  1. You might easily forget how many arguments a function has, which one’s the callback, as you’re mixing incoming and outgoing data
  2. What if you forget the error handler?
  3. What if there’s an exception?

Enter.. The Promise – a standard for encapsulating asynchronous requests, by providing an API for chaining the results once they arrive. It’s very similar to the above, but is standardized.

function yourPromiseFunction(arg) {
    return new Promise((resolve, reject) => {
        // Perform some actions and resolve..
        resolve(arg * 2);
    })
}

Now don’t get be wrong, it looks a lot like the previous callback way of doing things; however, we’ve now encapsulated the results in a standardized way.. which you can ALWAYS call then on. You can also call catch and finally on it, in case of errors. And that’s not all! You can wait for multiple parallel Promises to resolve before continuing.

Say you wanted to wait for two API requests to complete and come back before proceeding..

function callRandomApi() {
    return new Promise((accept, reject) => {
        // .. do the work then accept(response)
    });
}

const allTheApiCalls = Promise.all([
    callRandomApi(),
    callRandomApi(),
    callRandomApi(),
    callRandomApi(),
]);

allTheApiCalls.then(([r1, r2, r3, r4]) => {
    console.log("API Results:", r1, r2, r3, r4);
});

And finally, there’s one more thing that they’ve recently added to JavaScript which removes the complications of nesting and callback hell a bit: async/await.

Make sure you understand the above examples, because this one gets a little tricky. Async/await is just a fancy new way of wrapping and unwrapping things in Promises for you, so that it becomes a little more seamless for you. There are also some superpowers it lets you do that you would otherwise have had to write some insane logic for in the past. But essentially it lets you:

// Go from this..
function yourNormalFunction() {
    firstCall(12345).then((result) => {
        secondCall(result * 2).then((nextResult) => {
            finalCall(nextResult);
        }, handleError);
    }, handleError);
}

// To this..
async function yourAsyncFunction() {
    try {
        const result = await firstCall(12345);
        const nextResult = await secondCall(result * 2);
        finalCall(nextResult);
    } except (e) {
        handleError(e);
    }
}

… but inside, it’s all just Promises.

I hope this helps explain something that I’ve started to love about JavaScript’s new features. Let me know if you have any questions or want a deeper explanation and I’ll be glad to walk through it!

For more reference, check out: Mozilla Developer - Promises

The Road to Undermountain

2018 Jan 15

So now we run a game. *gulp*

We run a game that’s been around since 1997, had many features added to it, and has managed to survive the many things that have been thrown at it. But a few things stuck out as issues:

  • staff activity had dwindled in the coding and building areas,
  • many bugs still exist that have been around for years,
  • few activities for players to do, most of which the veterans have a huge advantage at,
  • everything requires a code change, and C is terrifying for people to learn

These were all items that have plagued most MUDs that have been around for this long, with two possible options: fix the problems or eventually dwindle into non-existence. So we’d need to combat this problem with a few phases.

Hire Some People

And after hiring some new coding and building staff, I believed we had the team that would be able to achieve this:

  • Kelemvor (me!) - Coder and Delegator
  • Jergal - Everything from Coding to Roleplay
  • Torog - Events and Roleplay
  • Mielikki - Roleplay
  • Bahamut - Building
  • Sune - Enforcer and Justice

As well as the various staff members and owners who had been around forever and showed up from time to time: Kord, Nisstyre, Meathe, Epsilon, Bane, Malar, Mask, Vorcet, and Sharess.

I had a team I could trust to be honest, caring, and get some work done. I could delegate the work to be done and trust that it would be handled.

Fresh Start

For a game that’s been running 20 years, you’ll find with that kind of longevity comes a few interesting problems. Many of which show up in interesting ways, not all of them are necessarily code-related. The economy was in shambles, players felt they had been owed for past hardships, feuds between community groups had gone on for years.

We started by fixing the various bugs in the codebase that we could find, especially the low-hanging fruit that was causing obvious crashes; but funny enough, it turns out that the game wasn’t exactly coded over the years to be able to handle a long uptime.

It was a bit of a rat’s nest.

Revamp the Engine

It’s at this point we decided that we’d start a two-pronged approach for Waterdeep’s future: stem the bleeding of the current game with fixes, events, and duct tape in a few places, while we work on creating our own engine upon which to run the game: Undermountain.

The goals of this project would be fairly straightforward, but also quite flexible:

  • Easy to Learn - Programmed in Python, be fairly easy to learn and get started with contributing to,
  • Batteries Included - Designed to be used as a framework for creating MUDs (and potentially other games) with reusable tools to handle the various tasks,
  • Flexible - Be modular so that portions of the logic could be replaced or implemented in other ways,
  • Powerful - Support scripting for the world, rather than in the codebase– giving more powers to the builders
  • Stable - Trading a bit of performance that raw C would afford, memory safety and asynchronus task management would be easier to implement

With this codebase behind our project, we would be able to re-implement what Waterdeep provided, as well as support other universes and worlds.

Goals and Future

With the engine updated to support many new functionalities, our goal will be to migrate Waterdeep over to it and start expanding the game (and underlying engine) to support anything we can think of.

Alongside this progress, we plan to start a network of a few MUDs that implement different universes, functionalities, organizations, vehicles, and more.

Where Are We Today?

Waterdeep is running, available at telnet://waterdeep.org:4200 or via our web-based client: https://client.waterdeep.info/ and being supported primarily by Jergal on the coding side of things, as we try to gear up for the new codebase.

Undermountain is slowly progressing, with features being added daily. The codebase is open-sourced and coming along quite nicely at: https://github.com/gvanderest/undermountain

Progress is being made daily to get an example of the game available for connecting with a telnet client to beta.waterdeep.info on port 4200. A web client will be getting developed in the near future for this instance.

We really appreciate the support we’ve gotten so far, and we’ll keep everyone posted as we reach milestones in the project.

Contributing to Open Source

2018 Jan 4

Contributing to Open Source feels like it’s something you’re not good enough to do. And even though I’m very new to the concept, I firmly believe that you can do it.

What does contributing mean? Almost anything:

  • Fixing a typo in some comments of someone else’s code
  • Translation of help pages into another language
  • Adding some very basic functionality to a codebase
  • Updating some documentation that’s out of date or unclear
  • Making something new that people may use and sharing it with the world
  • Finding and fixing a bug in someone else’s work

Note: I listed the bug-related item last, because while that might be the top of your list for contributions in terms of feeling “important,” that might be the hardest item to accomplish– which is basically setting yourself up for failure.

My small steps into this arena followed this path:

  1. I have started getting into TypeScript and React development quite a bit lately
  2. Webpack is a common tool to use, but the configuration is typically painful
  3. I have a set of configurations I like to start with, maybe others would like it too

So I started a repository on GitHub and just started coding some generic and helpful scripts to get a project started.

And what made it an Open Source project? I went to GitHub’s Licensing a Repository Help Article and started following the instructions, opting for an MIT license because it seemed easy to implement and fairly open for usage.

There might be a lot of options already out there, or much more complex tools than what I’ve created, but there may still be someone out there that could use it. It may be that I’m the only person who ever uses it, or it might be that some people start to integrate it into their future projects.

Either way, I’m hopeful that someone will use it, and I’m also hopeful that if you find something difficult inside, that you might be able to create a pull request against it to help improve the instructions or functionality.

Update: While showing this article to my friend Mielikki, she pointed out some horrible spelling in my writing and provided some feedback to help with improvement. This is also a way to contribute, it can be as easy or as difficult as you want it to be!

Waterdeep

2017 Dec 12

In grade six, I remember we had dial-up internet at home, which was shoddy at best. So while some of my friends were on NewGrounds checking out the cool flash games, I was working at a slightly slower baud rate.

I had been dialing up Bulletin Board Systems (BBSes) in the past, and I was looking for something similar to door games and stumbled upon Multi-User Dungeons (MUDs).. telnet protocol games that let you connect and talk/interact/fight with and alongside other players.

The first one that I tried was a Star Trek-themed game, whose name I can no longer remember.. and I’ve tried to do a little digging, and have had no luck finding. But during this time, I’d been reading a lot of Dragonlance and Forgotten Realms books, so my tastes had shifted a bit into more of a Dungeons and Dragons-y direction.. leading me to the login screen of Waterdeep: City of Splendors..

> telnet waterdeep.org 4200
Trying 173.255.199.200...
Connected to waterdeep.org.
Escape character is '^]'.


            ;::::;                             Original DIKUMUD by Hans
           ;::::; :;                         Staerfeldt, Katja Nyboe, Tom
         ;:::::'   :;                        Madsen, Michael Seirfert and
        ;:::::;     ;.                       Sebastiand Hammer. (c) 1991
       ,:::::'       ;           OOO\
       ::::::;       ;          OOOOO\         MERC 2.1 Code by Hatchet,
       ;:::::;       ;         OOOOOOOO      Furey and Kahn. (c) 1993
      ,;::::::;     ;'         / OOOOOOO
    ;:::::::::`. ,,,;.        /  / DOOOOOO     RoM 2.4 Code by Russ Taylor.
  .';:::::::::::::::::;,     /  /    DOOOO   (c) 1996
 ,::::::;::::::;;;;::::;,   /  /       DOOO
;`::::::`'::::::;;;::::: ,#/  /        DOOO    RoT 1.4 Code by Russ Welsh.
:`:::::::`;::::::;;::: ;::#  /          DOOO (c) 1997
::`:::::::`;:::::::: ;::::# /            DOO
`:`:::::::`;:::::: ;::::::#/             DOO   WDM 2.0 Code by Waterdeep
 :::`:::::::`;; ;:::::::::##              OO MUD Entertainmant. (c) 2007
 ::::`:::::::`;::::::::;:::#              OO
 `:::::`::::::::::::;'`:;::#              O  Owned & Operated by Nisstyre
  `:::::`::::::::;' /  / `:#                 E-Mail:  wdmudimms@gmail.com
   ::::::`:::::;'  /  /   `#
           ##    ##  ####  ###### ######  ####  ######  ###### ###### #####
           ##    ## ##  ##   ##   ##     ##  ##  ##  ## ##     ##     ##  ##
           ## ## ## ######   ##   ####   ##  ##  ##  ## ####   ####   #####
           ## ## ## ##  ##   ##   ##     #####   ##  ## ##     ##     ##
            ##  ##  ##  ##   ##   ###### ##  ## ######  ###### ###### ##
                          C I T Y  O F  S P L E N D O R S
                                   [ Est 1997 ]

Why have you come....go away or choose a name:

This was what I wanted, starting as a level 1 human mage, and slowly growing in power and creating many characters to defeat the many dungeon bosses, survive (and die) to the player-killing, leading clans, and all-around having fun.

Run by Nisstyre, his brother Cyric, and a few of their friends, it was a crazy place.. and sort of buggy. A crash might occur, and take a bunch of peoples’ gear with it, or cause duping of data to happen. But it was home and it felt right.

By this point though, the players knew almost all of the intricacies of the game. The bosses were old hat and all of the gear that could be collected had been.

And that’s when the itch started to get me.. I needed to create.

Building

I applied to become a builder, and learned the basics of creating rooms and describing them. I created creatures and objects to pepper the areas with, storylines and intricate details to add flavour and depth– and most importantly, I learned “mobprogs”.

say Hello there, $n.  Would you like to buy anything?
grin $n
say We've got some new items in the back you might be interested in.
emote tosses an apply in the air and catches it.

Mobprogs are named after the terms “mob”ile (the creatures that walk around the game) and “prog”grams, which were essentially fairly rudimentary scripts that the game could interpret.. but they let you control the actions, speech, attacks, etc. that a creature could perform. This was the defining moment, the gateway drug, that led to me becoming the programmer than I am today.

I built and built, created some wonderful areas and met some amazing people whom I teamed up with to create some of the content that is still being played today.

The Lull

It was after this that I got a little bored of the game, likely paired with an upgrade to our internet connection, and more graphical games of the moment (Counter-Strike, Ragnarok Online, World of Warcraft, etc.) but Waterdeep always had a place in my heart.

Fast-forward a few years, many of them learning web development in PHP, and I think to myself, “I wonder if Waterdeep’s still going.” The same login splash screen greets me, and I feel a comfort that I haven’t felt in years. My characters have long-since been given away or deleted or forgotten entirely, and I start up a new character, saying hello to the few people who are still online.

The game was run by Kord and Bane at this point and some new features had appeared. By this point, I had some actual coding experience under by belt, and applied to join the team.. and surprisingly enough, was accepted. I helped get the codebase stored in git (yay, version control) and crushed some of the bugs that were lingering since the days when I had past played.

Running The Joint

But things had grown a little stale again. Bane was fairly inactive, after having completed most of the planned projects, he likely found his other projects to be more important and sort of disappered. Kord’s activity had been dwindling for weeks, and while he had a lot of great ideas, he rarely had the time to put them into play.

So I decided, “okay, let’s get this thing going.” I got promoted to owner of the game, hired some staff (builders, roleplayers, coders) and now I try to keep the place moving forward and running smoothly– which as of writing, it seems to be!

It’s an old codebase, running on heavily modified ROT (circa 1997), and we’ve got a web client going for it now if you’d like to try it out: https://client.waterdeep.info/

The Future

One of the next posts I’ll be writing will be what the future plans for the game include, and how we’ll be going about implementing them.

Stay tuned!

Hello World

2017 Dec 1

It starts when we received our first personal computer around the age of seven. It was a 386 DX 33MHz machine, and one of my dad’s friends at the school board was a well-known electrical engineer who loved to tinker, which led to him overlocking our machine to 50MHz when you hit the turbo button.

The first thing I remember asking him was, “How do I make games?”

A few milestones stick out in my mind as I progressed through elementary and high school:

  • learning programming languages like QBasic and Pascal from library books,
  • Dungeons and Dragons with my friends,
  • dial-up bulletin board systems,
  • Legend of the Red Dragon (LORD) doorgame,
  • dial-up internet,
  • website development and the world of HTML,
  • Multi-User Dungeons (MUDs),
  • DSL and cable internet,
  • way too much Counter-Strike,
  • Ragnarok Online MMORPG,

A few years passed, creating many applications for many clients and working for a local website development company, and I figured to myself, “hey, I could run a company myself,” and tried it out, Exodus Media Inc, out of the Kamloops Innovation Centre.

It turns out that running a business is a lot harder than I’d imagined, and finding clients is a difficult game in itself! I was nearly bankrupt by this point, ignoring all of the red flags that started appearing. And it was then that I realized, “I need to change this before I drown,” which landed me with my current employer, who happened to be in the same shared offices.

Now, I’m working at an amazing company, Open Gaming Solutions Inc, and I’m learning a whole bunch of new technologies and processes.. and I’m trying to evolve into more than just a programmer, which is very exciting.

Much like the games that I used to play, sometimes it’s a little scary, you need to get into the groove of things with your adventuring party, and grind your way through the dungeon before you can succeed.

So let’s go adventure!

Typescript Timer Number

2017 Aug 23

It appears that in a recent updates to either type definitions in my project, or some library, that a few of my timeouts and intervals might be causing issues:

ERROR in [at-loader] ./src/pages/ExamplePage.tsx:41:23
    TS2345: Argument of type '{ intervalId: Timer; }' is not assignable to parameter of type 'Pick<IState, "intervalId">'.
  Types of property 'intervalId' are incompatible.
    Type 'Timer' is not assignable to type 'number'.

After a little digging, I was able to find that using window.setTimout or window.setInterval should return the correct type of number – it looks like NodeJS uses Timer.

Hope this helps!

SublimeText Multiple Cursors or Carets

2017 Aug 12

I’ve been using MacVim forever, and finally switched to using SublimeText with the vintage mode enabled. It’s scratching many of the itches I’ve had, but one of the main things I liked to do in vim was stuff like prepending content to multiple lines by selecting multiple lines and then typing:

:norm!Iprefix content

After a little digging, I found that you can add the following keybindings:

[
    { "keys": ["super+up"], "command": "select_lines", "args": {"forward": false} },
    { "keys": ["super+down"], "command": "select_lines", "args": {"forward": true} }
]

Now you can hit your command key and an up/down arrow to get multiple cursors, and then perform the insert to all the lines.

React State-Transform Pattern

2017 Aug 11

The Problem

When working with React, one issue I’ve run into is the reusability of certain functionalities in my React Components, but I’ve found that something feels a little weird to be:

class StateMicroChangeComponent extends React.Component {
    ...
    handleSelectCategory(selectedCategory) {
        let allResults = this.state.allResults;

        let filteredResults = this.filterResults(allResults, selectedCategory);
        filteredResults = this.sortResults(filteredResults);

        this.setState({
            filteredResults,
            selectedCategory,
        });
    }
    ...
}

In the above example, I’m happy if there’s only one instance where we perform the filtering/sorting, but if our Component performs these tasks multiple times, it might be difficult to maintain. If the implementation of the filter and sort change, we would need to update all the instances.

What I’ve Started Doing

With the amount of Redux I’ve been using recently, I’ve gotten used to the idea of transforming state as a whole, and applying reducers to it, resulting in more of a state-as-a-whole approach:

class StateTransformComponent extends React.Component {
    ...
    handleSelectCategory(selectedCategory) {
        let state = { ...this.state, selectedCategory };

        state = this.applyResultFilter(state);
        state = this.applyResultSort(state);

        this.setState(state);
    }
    ...
}

Now, if filtering or sorting need a tweak, the applyResultFilter and applyResultSort can contain the specifics, while the components interfaces with the transform function.

This has helped me a few times to simplify my code’s logic, even to the point of defining further functions that I would reuse like applyResultFilterAndSort which does both, for added reusability.