Andrew Smith
← Journal
Aug 8, 2023

Destiny Status Postmortem

What's Destiny Status?

This project is a straightforward, one-page glance at a set of Destiny 2 characters. It's inspired by a previous version of the website www.destinystatus.com, originally developed by redditor mofrodo. That user handed over development to the Tracker Network team back in 2016 and those folks maintained it for several years, but it eventually went offline for good sometime during 2021 or 2022. Since then, it's been replaced with a different offering unrelated to the original app. I was quite fond of Destiny Status and sad to see it gone, so I wanted to create something similar to fill the niche it left behind.

Why Make This?

Bungie's API provides a ton of awesome data and there are already numerous webapps doing cool things with it, including places where you can look at character equipment and stats. Why make another one? Well, there are a couple reasons. First and foremost, many of the popular Destiny 2 webapps make use of the firehose of information provided by the API to generate a ton of game information for their users. When using those apps, I often find the user experience a little overwhelming (and this is not a knock against those apps, many of which I like very much and use religiously). What I loved most about Destiny Status is articulated really well by some of the comments on the reddit post announcing that TRN would continue maintaining it:

The major thing people liked about DestinyStatus.com was its lack of features and extremely high level view of what was going on with your character.

-- u/funkmon

It is so fast, simple, clean yet provides compelling info. A lot of the other sites are stats obsessed, slow loading and provide way too much info you don't always need.

-- u/Joseph421

There are lots of great Destiny apps available that are extremely feature-rich and data-rich. I wanted to create an alternative that is feature-light and data-light -- for the times when all you really want is a quick glance at someone's loadout, or to make sure someone's got a reasonable power level for the activity you're going to do, or to see whether your friend cleared RoN yet this week on her Titan...etc, etc.

There's Already an App for This!

Around the time that I noticed destinystatus.com was no longer online, I had been studying web development and was looking for good project ideas. It seemed like making a Destiny Status of my own could be a good way to get my feet wet with a project that would take a lot of work, but still be an attainable goal. This being the case, I didn't spend a ton of time seeking out alternatives. Point being: my goal is not to step on anyone's toes or assert that there isn't an app for this already -- perhaps there is! But, having discovered that my favorite one was gone, I wanted to build one that I personally would be delighted to use.

It's also worth mentioning that this is my first project of this size. Bugs and improvable code are both likely to be present. If you notice anything that needs improvement, either as a user of the site or as someone peeking under the hood, please feel free to submit an issue or contribute to the project.

Challenges

One interesting issue I ran into on this one: unexpected edge cases. I think many developers learn early on how important it is to anticipate edge cases (what if this field is blank? what if I get a string instead of an int?), but it takes experience to really build the skill of imagining what contrary input can look like in the real world.

On Destiny Status, I recognized early in the process that some characters I looked up might be missing some of the 11 equippable items a character can have -- specifically, they might not have a ship. A ship is the last item in the API's item list. So, I implemented a very naive fix:

 // character should contain 11 items: 3 weapons, 5 armor pieces, ghost, sparrow, ship
  while (itemComponents.length < 11) {
    itemComponents.push(<MissingItem />);
  }

Problem solved! Characters that didn't have a ship had this new <MissingItem/ > component as a placeholder. And it turned out to be extensible when I discovered that some characters were missing a ship and a sparrow. And this is definitely where alarm bells should have gone off and I should have asked myself, "What else is it possible for a character to be missing?"

And then, a few months later, after I had already launched, I learned something very unexpected: there were some characters out there who didn't have guns equipped. For a Destiny character, this is really strange! Within the first 10 minutes of the tutorial, the game outfits you with some basic gear. I'd failed to interrogate my assumption that every character would of course have equipment in these slots, and it caught me totally flat-footed.

Fixing this was tricky but satisfying. I started with a lookup table for the ids that correspond with different item slots, and a baseline assumption that it was false that the character had that item equipped:

    // the tuples in this array are composed of an equipmentSlotTypeHash, a boolean representing the presence of an item in that slot in the current user's inventory, and a string identifying the name of the item slot.  note that order is important here: this array is ordered to match the order in which Bungie's API returns equipped item results
    [1498876634, false, 'primary weapon'],
    [2465295065, false, 'energy weapon'],
    [953998645, false, 'heavy weapon'],
    [3448274439, false, 'helmet armor'],
    [3551918588, false, 'chest armor'],
    [14239492, false, 'gloves'],
    [20886954, false, 'leg armor'],
    [1585787867, false, 'class item'],
    [4023194814, false, 'ghost'],
    [2025709351, false, 'sparrow'],
    [284967655, false, 'ship'],
  ];

Then I added a function to check the slot id for each piece of equipment I saw on a character and change its equipped status from false -> true:

    if (item.equippingBlock) {
      itemSlots.forEach((itemSlot) => {
        if (itemSlot[0] === item.equippingBlock?.equipmentSlotTypeHash) {
          itemSlot[1] = true;
        }
      });
    }

And finally, I still needed some <MissingItem /> components, but I couldn't just shove them onto the end of the array -- so I spliced them into the correct positions.

  itemSlots.forEach((itemSlot, i) => {
    if (itemSlot[1] === false) {
      itemComponents.splice(
        i,
        0,
        <MissingItem itemSlot={itemSlot[2]} key={i} />
      );
    }
  });

This bug was a great illustration of how cautious we need to be about our assumptions and how easily a bug can slip in if we don't ask "but what if?" about all of the things that we believe must be true.