Status update: 2026

Hey everyone! To reiterate my opening sentence from last time: It’s been a while since I last posted, but don’t worry, I’ve been keeping busy.

Normally, I’d dive into the technical details, but not this time. It’s been too long, there’d be too many of them, and even I don’t remember them all. I’d have to read through and summarize ~1200 commits, and if I wanted to spend my time doing that kind of thing, I’d get a job as an LLM.

Instead, how about we skip to the part everyone cares about? The Run 1 and Run 2 remakes are both close to completion, with all levels (plus Infinite Mode in Run 1) working. However, both games still have a list of issues.

Run 3 remains on the back burner until those first two are ready.

Run 1

I’ve already released an HTML5 remake of Run 1 (which I consider to have been a beta version), but since then I rewrote most of Runaway (the underlying engine), so I’ve had to redo most of Run 1 as well. It’s coming along well so far, and since I invested in building solid foundations, fixing the remaining problems should be relatively painless.

Adventure Mode is nearly done. The levels are unchanged, but I’ve been playing around with the physics, trying to make the game feel nicer but still close enough to the original. I’ve also done my best not to mess up game balance. I know people like Run 3’s physics, but those would make Run 1 too easy.
Side-by-side comparison of Level 1, near the end of the level. The images are similar, but the old one looks blockier and the Runner looks smaller, while the new one looks smoother and the Runner is closer to the center of the screen.

There’s still more to do for Adventure Mode. For one thing, it saves your progress but can’t load it, so you always restart from level 1. Also, there’s no ending, and the level transitions are missing something. At the moment I’m still using the “flying through space” level transition from the beta, but it’s less interesting without all the tiles zooming into place. Either I need to recreate that animation, add other scenery to look at, or go back to the original “endless tunnel” version.
Side-by-side comparison of a level transition. The old version features an endless tunnel with a text overlay instructing the player to "Press space to continue." The new version features the Runner flying through space, approaching the next level.

Infinite Mode is finally working! This one took a while.
Side-by-side comparison of Infinite Mode at 45% difficulty. The new version looks harder, but that's partially because the Runner happens to be starting on the wrong side of the tunnel.

I tried to adapt the original level generation code, but something went wrong along the way. The new generator makes levels that are both harder and less visually coherent. As for why it’s green, I haven’t gotten around to adding multiple colors yet.
Side-by-side comparison of Infinite Mode at 99% difficulty. The old version has several clumps of tiles and at least two viable routes, whereas the new version has tiles in groups of 1-3, and fewer tiles overall. There are no good routes in sight, even if it's technically possible.

In previous status updates, I talked about how Run 1’s Infinite Mode required an overhaul of how levels were loaded. At the time, my plan was to place the levels in 3D space, loading them as soon as two conditions were met: (1) the camera was almost close enough to see them, and (2) the player beat the previous level. The original version of Run 1 would only load a new level once the previous one was over, and it’d use the player’s performance to determine the difficulty of the next level. The more you fell, the less difficulty would increase (though it would always go up by a little).

Well, I did that. And then I did something else instead. Whoops!

Now, Infinite Mode levels load based on the camera’s position (1), without waiting for you to beat the previous level (2). The difficulty increases as you make progress, and the tiles update in real time, which I think makes for a cool effect. (Also, the difficulty decreases each time you fall.)

I like this concept, and it took a fair bit of work to make it happen, but I’m not sure I like how it feels in practice. Pros: if it generates an unfair level, things will get easier once you fall off a couple times. Cons: it feels less like you’re making progress if you can just lose it again. In the original version, any progress you made was locked in. I could go back to that, but I think (hope) this should be fixable while keeping the cool new real-time updates.

Finally for Run 1, there’s currently no Edit Mode or costumes. I’ve got a working editor in Run 2, and I should be able to import that without too much trouble. Not sure what I want to do about the costumes, though. Do I keep them as costumes, or is it worth the time to flesh them out into separate characters with unique abilities?

Run 2

For those who weren’t there, in late 2024 I rebuilt Run 2 in a series of livestreams, better than before. New UI icons, touched up levels, clearer indicators of where you can and can’t rotate gravity, higher-resolution backgrounds, and a new sci-fi font.
The Skater at the start of "Jigsaw Pieces." To his left is a gap in the floor; the wall of this gap is marked with diagonal slashes, indicating that if he can't catch on to that wall. The pause menu is open, showing a series of icons: a house, left and right arrows, a yellow circle, and a music note. These icons are drawn in one continuous stroke, except the note, which uses two strokes.
I’m sorry it’s taken so long to get this thing out. Many of us (me included) expected it to be out by now, but some of the remaining problems proved stubborn. At this point, I’m going to wait until I’m ready to release both remakes at once.

Here’s what was broken as of my last stream.

  • The player character stutters, as if updating at a low framerate. The rest of the game moves smoothly, so it’s not actually a performance issue. And Run 1, which is using the same engine, doesn’t have this issue. Still don’t know what’s up with this.
  • Sometimes when you deleted a cube in Edit Mode, it wouldn’t disappear, but you could fall through it. I’m happy to report that this is now fixed!
  • Sometimes when you added a new cube, nothing would show up but it would still be solid. Also fixed!
  • Often when you clicked and dragged to “paint” several cubes at once, it would place some in the wrong layer (usually one layer closer to the camera than expected). Fixed!
  • There’s no way to edit level properties (color, dimensions, title, etc.) other than manually editing the level data. I still haven’t done anything about this.
  • Though you could save levels, there was no way to load them. I’ve since added a basic text box to paste level data into, and levels do load successfully, but this promptly revealed a bunch more issues.
    • The UI isn’t built to deal with standalone levels like this, so the next/previous/bonus buttons do nothing and display incorrect data. They always indicate that there’s a previous level and that you haven’t beaten the current level or earned its bonus. When you do beat the level it says “press jump to continue,” but you just jump normally since there’s no next level to go to.
    • I didn’t program the levels to unload, so they just stay around until you quit to the main menu. This lets you load multiple levels on top of one another, though you can only interact with the most recent one.

In addition to all that, a new rendering issue popped up. If you leave a level and then navigate back to it using the pause menu, only the level’s outlines will appear. I distinctly remember having fixed this at one point, but no, it’s still here.
The Skater at the start of "3-Tuples." The cubes in the level are invisible, but the outlines are there.
This looks pretty neat in some cases, so I might add official support for it later. But I can’t keep the bug itself, as some levels lack outlines, and with neither fills nor outlines they end up being fully invisible. Good luck playing those!

As if all that wasn’t enough, I recently tried building for HTML5. It starts out in outline mode, and then the scene goes completely black if you ever move left or right. You can’t complete (or fail) the level in this state, but everything comes back if you reset, so it’s not like the game crashed. I suspect the Runner’s coordinates are getting divided by zero.
Two invisible levels. The first shows the Skater skating on nothing in "There Has to be an Easier Way." There are still background stars in that one. The second is the Runner playing "Left, Right, Space," but everything is gone: the Runner, the level, and even the background stars. Only the title bar remains.

What next?

I plan to fix everything mentioned above. When these games come out, I want you to be able to do everything you could do in the original. I’ll try to leave it at that, and not get distracted working on new features. Though it occurs to me as I write this that an “import save” feature would help a lot. Then you can pick up exactly where you left off.

I also want to do some marketing, to build interest. Keep an eye on this blog and my YouTube channel for updates.

Site upgrades

I’ve recently finished overhauling this site. If you’ve noticed anything different around here, this is why. (If you haven’t, sweet! That was my goal.)

What?

I migrated player03.com from shared hosting to a virtual private server (VPS).

Along the way, I improved the site’s security (both front- and backend), wrote a bare-bones privacy policy, and tidied up some old posts and images. I considered big changes like switching to a more recent theme, but most of them broke something or would require extra work, and might confuse visitors. So instead, I aimed to keep it as close to the old version as possible.

Why?

Because CryptCheck gave me an F.

D: Take security into account. Minimaly. This is the worst score a decent service must have today. E: Take security into account. A little. Or not. F: Just don't take security into account. G: Just don't take security into account at all. What the fuck you do, dude?

Two ranks below the bare minimum, ouch!

(Note: I have no evidence that anyone ever exploited these vulnerabilities in the wild.)

Who?

I don’t actually know who runs cryptcheck.fr, other than that they’re French and highly opinionated. The site was recommended by a security geek on social media, and as we all know, geeks on social media are infallible.

Whether or not I felt like trusting CryptCheck, Mozilla corroborated them. Their HTTP Observatory gave me a 40/100 (D-). Thankfully, unlike CryptCheck, Mozilla provided detailed descriptions of what was wrong, why it was wrong, and how to fix it.

What and why?

  • I was allowing unsafe inline scripts. This meant that if someone found a way to insert text into the page, they could run a script in another visitor’s browser, potentially stealing data or directing them to a virus. (WordPress sanitizes comments, but you never know when someone will find a way to bypass that.)
  • I was allowing other sites to embed mine in an iframe. In theory this can be used to steal user data, though in practice, what is there to steal?
  • I wasn’t implementing HTTP Strict Transport Security (HSTS), meaning http://player03.com didn’t redirect to https://player03.com early enough in the connection process. It did redirect eventually, but the initial connection was done over http, which would technically be enough for someone to intercept the data and redirect users to a fake site.

How?

The easiest one to fix was iframe embedding. I opened up the root .htaccess file and added two lines. The first line sets X-Frame-Options "SAMEORIGIN", telling browsers not to let other sites embed mine. The second line sets frame-ancestors 'self', telling browsers not to let other sites embed mine. I think the difference is that the former is for old browsers and the latter is for new ones.

Next, I had to disable inline scripts. This isn’t hard to do: just delete 'unsafe-inline' from .htaccess. The trick was, I wanted my site to continue working afterwards, and some of my fancier blog posts made heavy use of inline scripts. I’d have buttons that you click, each with its own onclick="do.unique.thing()" inline script.

To fix this, I went through all my blog posts and figured out a way to replace these scripts. Turns out, while onclick="xyz" is unsafe, you can just move xyz into a .js file, and then it’s safe. The site uses HTTPS, which means all the .js files are cryptographically signed, so there’s no tampering with them during transit. I also submitted a pull request to Lime to remove inline scripts from Lime apps.

WordPress uses its own inline scripts, and I couldn’t transfer those. Instead, I manually approved them using SHA-256 hashes. These scripts will run as long as they’re completely 100% identical to the versions I approved, but even adding or removing a space would make browsers reject them. This ALSO means that I can expect parts of the site to break when WordPress updates, and I’ll need to manually re-approve it. WordPress is working on clearing out inline scripts, but not quickly.

Finally, HSTS and redirection. HSTS is easy: add a single line in .htaccess, promising to keep using HTTPS for a year. As for redirection, it’s just a couple more lines of code… that didn’t work. Each time I tried, it broke the whole site. Digging deeper, I realized these lines could not go in .htaccess, and what’s more, I didn’t have access to the correct file.

Where?

I needed access to the Apache server configuration files. However, I was on shared hosting, and being able to mess with those files would mean I could mess with other people’s websites (and they could mess with mine). Understandably it wasn’t allowed.

To do this one last little thing, I needed to move my entire website over to a whole new server, one under my control. On the plus side, it turns out that virtual private servers are cheaper than shared hosting, at least when you get the self-managed option. Pros of self-managed: I’m in full control, and no longer need to ask permission to change settings. Cons of self-managed: I’m in full control, and with great power comes great responsibility.

Since I had already spent time configuring Apache settings, I picked a LAMP stack (the A stands for Apache) over LEMP (the E stands for Nginx). My hosting provider offered a one-click install, but that didn’t work so I installed it myself. I set up firewall rules, an https redirect, restricted accounts for each service, SSH access, SELinux, and various other security measures. After briefly confusing FTPS and SFTP, I bulk-uploaded the site’s contents.

Aside: either guides have gotten better since 2014, or I’ve gotten better at following them, because everything ended up working as described. I did run into snags, but I was either able to work through them quickly enough, or I’d discover that there was a good reason it wasn’t allowed. I ended up with an aggressively basic setup, and I’m happy with that: basic means easy to verify.

When?

This Tuesday, I updated my DNS records to point to the new site.

Several things immediately broke, most notably the CSS, due to URLs still pointing to the test version of the site. My Content Security Policy (CSP) specified that scripts and styles must be loaded from 'self', not some strange alternate-dimension version of 'self' at a different web address. (It was the same thing, but browsers couldn’t verify that, so didn’t trust it.) I updated the site link in the WordPress dashboard and Apache config files, and things went back to normal.

Then I encountered another issue: my hosting provider unexpectedly restored the site’s old DNS record, in addition to the new ones. This left visitors with a 4/5 chance of getting the correct site, but a 1/5 chance of being sent to the old one, which was now broken due to the same sort of URL issues described above.

The reason this broke? Their nameservers were for shared hosting, and I wasn’t supposed to use them anymore.

So I set up my own nameserver on the VPS. Now, when you connect to my site, your browser contacts my server for instructions on how to contact my server. Seems weird, but there are several guides for exactly this, so I suppose that’s just the world we live in.

Is that all?

First off, rude, this took over a week of research and work.

Second, no, it’s not all. I have a short list of things still to do, and I’m sure there will be user-reported issues. I’ve already received one such report: apparently Run3.swf no longer works in the standalone Flash Projector. (Not sure how to debug this, sadly. If anyone has solid information on how the Flash Projector loads files, let me know!)