Toward a 1st Release

Thu, September 10, 2020
Engineering a release means writing documentation

One of the less glamorous parts of being a software engineer is writing documentation. Glamorous or not, though, it's critical for most software. And CodeSpells is no exception.

In fact, documentation is even more important in a project like CodeSpells than in a normal 3D game. The reason, of course, is that CodeSpells is reprogrammable. It's a piece of software that reads and runs your code.

For all its flashy 3D-ness, the fact that it is also a runtime environment for programs means that its next of kin include the likes of programming languages (like Java, Python, or Racket) every bit as much as 3D games (like Minecraft or Fortnite). CodeSpells is like what would happen if a programming language runtime and a 3D game had a baby.

Would you use a programming language with no documentation? I wouldn't.

And so, this blog post begins the long journey of creating those magical meta-texts we call documentation -- without which the magical texts we call spells would be impossible to write.

We begin (as all good documentation perhaps should) with some fundamental truths that would need to be understood by anyone contributing to the CodeSpells open source projects.

Truth #1: A World is a collection of Things

(technical detail)

Because my implementation of CodeSpells is written with the Unreal Engine, a World is roughly equivalent to what Unreal programmers would call a "level", and a Thing is roughly equivalent to what would be called an "Actor." If (one day) we the CodeSpells community want to target the Unity3D game engine, a Thing would be roughly equivalent to a "GameObject."

"So am I a Thing?" asked the young wizard.

"Yes," said the Arch Mage. "And so am I."

Truth #2: Things exist in the World. Spells exist in the Aether

"But aren't Spells in the world?" asked the young wizard.

"Not technically," said the Arch Mage. "Spells are outside of the World -- in a place we call the Aether. We do, however, view them through a special kind of Thing."

"Ah," said the young one, "you mean the surfaces through which we read and write Spells? Those are are Things, but the Spells aren't?"

"Precisely."

Truth #3: A Spell (when cast) can create, destroy, or change Things

"Hmmm," said the young wizard. "Why can't we just make Spells be Things? Seems like it would be simpler."

"Back in the ancient times, that's how it worked," said the Arch Mage. "Spells used to be constructed from physical Runes, which were Things. But today, the Runes you manipulate on your surfaces--"

"Which are Things," the young wizard chimed in.

"--are just virtual approximations of those old physical Runes. Back when our ancestors learned to create surfaces--"

"Which are Things," the young wizard mentioned again.

"You don't have to keep saying it," said the Arch Mage. "When our ancestors created surfaces, it allowed us to craft Spells out of any virtual material we wanted, anything that could be interacted with on a surface: Runes, written text, configurations of 'buttons' and 'switches' -- anything. Now, depending on what we want our Spells to do, we can select whatever interface best fits the task of writing and editing them."

(technical detail)

Because a World is equivalent to an Unreal level -- the Spells really do exist "elsewhere". They are viewable from inside Unreal through the Unreal WebBrowser. The Racket runtime runs a webserver and serves up user interfaces that you interact with from inside Unreal. Spells are executed inside of the Racket runtime -- but they can create Things in the Unreal runtime. The Unreal runtime embeds a JavaScript runtime (via Unreal.js). The Racket Runtime can create Things and also specify additional JavaScript code that should govern the behavior of such Things.

I made this architectural separation so that community members who wish to do so can create whatever outside-of-Unreal Spell-crafting technologies they wish. UIs for Spell-crafting can be written in any web technology (React, jQuery, etc.) and the Spells can execute in any backend technology (Ruby on Rails, Node.js, etc). These interfaces can be hosted locally or remotely (via a local proxy).

Latency between Unreal and the Spell server is not a large concern. For operations that need to happen often, e.g. on every frame, the Spell server should ship the appropriate JavaScript to Unreal.

Truth #4: A Spell can be thought of in two ways: Crafted and Casted. Magic is what happens after a Spell is Cast.

"So... when I've Crafted a Spell," said the young wizard, "what happens when I Cast it?"

"Magic," said the Arch Mage with a faint smile. "Magic begins life in the Aether and continues to live within the World. First, your Spell, as Crafted upon your surface, gets interpreted or transformed by whatever gods or machines or incomprehensible processes exist in the Aether. Those Aetherial Magical processes are transformed into Worldly Magical processes that continue to unfold here in our World."

Truth #5: Magic begins in the Aether and continues in the World. The event of Magic traveling between Aether and World is called Crossing.

"So my Spells live in the Aether..." said the young wizard, "...and I Craft them by using my surface (which is a Thing in the World). And when I Cast them, they turn into Magic. And the Magic then Crosses from the Aether to the World. And that's what makes Things appear, or move, or whatever?"

"Precisely."

"Why does magic have to be so complicated?" said the young wizard, rubbing his temples.

"Come back tomorrow," said the Arch Mage. "We'll work through some examples, and I think you'll see that it's not really as complicated as it seems."

Glossary (where we make magic boring and mundane)

- Stephen R. Foster


P.S. Please consider supporting us on Patreon. We can't do this without you!