Dependency Injection (like pytest fixtures) with a Python decorator

If you’ve used Pytest, you’ll notice a neat little pattern. If you want a particular fixture, you just ask for it, seriously, check out the docs:

@pytest.fixture
def fruit_bowl():
    return [Fruit("apple"), Fruit("banana")]


def test_fruit_salad(fruit_bowl):
    # Act
    fruit_salad = FruitSalad(*fruit_bowl)

test_fruit_salad gets called when you run tests, and it will automatically pass the result of fruit bowl to test_fruit_salad. This pretty much blew my mind when I first saw it.

The following decorator helps you achieve something similar with your own functions. It lets you do something like this.

@opt_in_args
def request_a(foo: str, *, a: int):
    print(f"Foo is {foo}, a is {a}")

@opt_in_args
def request_b(*, b: str):
    print(f"b is: {b}")

@opt_in_args
def request_both(*, b: str, a: int):
    print(f"b is: {b}, a is: {a}")

request_a("Blarg")
request_b()
request_both()

Note that the * args just mean “everything after this is a keyword argument only”, it helps guard against accidentally passing in bad kwargs and you should always use it, but the above program will work the same without it. The output of the program looks like this:

Foo is Blarg, a is 123
b is: foobar
b is: foobar, a is: 123

First let’s look at the implementation of the decorator:

import inspect

def opt_in_args(func):
    def wrapper(*args, **kwargs):
        signature = inspect.signature(func)
        opted_in = {}
        optional_kwargs = {
            "a": 123,
            "b": "foobar",
        }
        for kwarg, value in optional_kwargs.items():
            if kwarg in signature.parameters:
                assert signature.parameters[kwarg].annotation == type(value)
                opted_in[kwarg] = value
        return func(*args, **kwargs, **opted_in)
    return wrapper

Let’s look at a few specific lines to illuminate what it’s doing:

def opt_in_args(func):
    def wrapper(*args, **kwargs):

This is standard decorator magic. The outer function has the function in-scope, the wrapper is (because we return it from the decorator) what actually gets called in place of the wrapped function, so we capture *args and *kwargs so we can pass them along.

signature = inspect.signature(func)

Note that we imported inspect at the top of the module. Inspect lets you introspect on python functions, and in this case we use it to grab the signature. signature.paremeters will now have a key for each parameter the function accepts; we can now write any code we like based on the params.

        optional_kwargs = {
            "a": 123,
            "b": "foobar",
        }
        for kwarg, value in optional_kwargs.items():
            if kwarg in signature.parameters:

This approach is totally optional. There are any number of ways you can enumerate the optional kwargs. You can make another decorator and supply functions which are only called if they’re requested (I think pytest fixtures must be doing something like this) or you can have a bunch of ifs to decide what to instantiate and put in.

                assert signature.parameters[kwarg].annotation == type(value)

This I just put in there to show one way you could enforce typing on the keyword arguments. This is of course also optional; you could write your decorator to only care about the name by removing this line.

                opted_in[kwarg] = value
        return func(*args, **kwargs, **opted_in)

We create a dictionary called opted_in and populate it with the additional kwargs we want to pass. The final line of the wrapper function calls the wrapped function with the args and kwargs the caller sent, unmodified, and finally with the opted_in args the function asked for in its signature.

For such a slick effect, this is a surprisingly easy decorator; decorator magic often is.

San Francisco

“Enjoying ‘walks’ is sort of a cliche. I consider myself an avid pedestrian, but while technically relaxing I also see walking an act of impatience. I like bloody-minded trudges from point A to point B when other means of transport would require waiting. So to experience the famous Golden Gate, I figured the most appropriate way was to walk from one end to the other.

Photograph of the Golden Gate Bridge from the San Francisco side. The bridge takes up about half of the frame, the right side is all bay. SF Viaduct visible in the foreground.

The bridge itself was massive. Better writers than I have described its grandeur. It’s probably the biggest single thing I’ve encountered. It felt as solid as stone gazing at its cable stays, the tension invisible, but you could feel the legendary elasticity of the steel structure underfoot when vibrations from traffic rippled across its surface.

Photo: Golden gate bridge tower and main cables, from the bridge.
Photo: San Fransisco skyline and bay, from the bridge

Do I recommend crossing it on foot? Well, it’s a bit loud. The views of the city, bay, and mountains are very nice. The constant reminders that people jump off the thing were a bit spooky. The traffic tended to stay below 80db but a bit louder as vehicles hit rough patches (joints?) in the road. I wouldn’t recommend earplugs, because you’re going to need your situational awareness to avoid blocking bikes.

Photo: Presidio from Golden Gate Bridge

About halfway across, I spied a lookout on a mountain high above the roadway. ‘I am gonna climb that‘ I said to myself. As I got further, my resolve strengthened; the view was bound to be amazing.

Photo: Hill with battery spencer from bridge

I didn’t spend much time at vista point-I was eager to get to whatever path lead up that hill, which turns out to be the former home of Battery Spencer. There was a nice shortcut to avoid the road and see some wildflowers.

Battery Spencer had some great views of the bridge and the headlands, but I couldn’t help but once again gaze up! Roads cut into the sides of these mountains invited me to climb higher. Once again, I elected to press on.

The views of the mountains sweeping down into Kirby Cove were breathtaking. I really lucked out on the weather. There was a rough path beside the road. The grade was merciful, but you couldn’t escape the feeling of being at the top of a very long fall. The roadcut had changed the erosion timeline for these hills, and every inch seemed to threaten imminent rockslide. Thrilling, to be sure.

I’d told myself ‘ah, I can make it to the observation deck’ but once I got there, again, I saw a higher peak: there was a great lookout (and more treacherous road) at what turned out to be Hawk Hill.

I was starting to feel the climb then; I regretted not taking any water with me, that would have been smart. But as unplanned hikes go, at least this one was done on a full stomach. I salute the bikers who were passing me on the way up-this must have been a tough climb. The reward on the way down, I imagine, is probably worth it.

Hawk Hill turns out to be not just one observation deck with views of the city, but also an unfinished battery ‘129’ with tunnels you can enter – fans of STALKER or Fallout will enjoy the ruins here.

The very top was only a short climb away, and the view was well worth the hike. Walking the headlands was a much more pleasant experience than the bridge with its noise. Somehow the actual danger of those sheer cliffs was more tolerable than the much safer bridge plastered with memento mori.

I will admit, dear reader, that when I reached the summit of Hawk Hill I felt ready to call it quits and take a Lyft back to civilization. It was not to be, however, so I descended back to Vista Point once again on my own steam.

After recovering in Sausalito and taking the ferry back (a trip I highly recommend even if you skip the hiking) and enjoying the ferry terminal, I took a slow (recovery?) stroll through the city (go to City Lights if you can) before one more time being seized by the desire to walk up a hill.

Telegraph hill turned out to be the toughest climb of the day. I went up Filbert Street, which attacks the hill head on. After a day of lazily winding roadcuts, it was brusque to say the least.

You’ll just have to take my word on the last bit, I’d burned out my phone battery so no pictures exist!

Fine, you got me Ars, I’ll rank the spaceships myself, properly this time

I’ll admit it: This list from Ars Technica got under my skin. Perhaps it was calculated to do so – I agree that the Enterprise C is one of the coolest Trek ship designs, but I recognize that it’s a dark horse pick. Nonetheless, a discord conversation lead me to this, ranking the Enterprises. I’m not going to include any I haven’t seen, and I’m going to include other federation starships at my discretion because ‘only classes with an enterprise’ is arbitrary.

I don’t usually blog pop culture nerd hot takes, but I do have a passion for fictional scifi starship design, so if you’d like to indulge me, read on.

13. Constitution

Black-and-white screenshot of the original Enterprise against a background of stars.

There’s no saving this misproportioned relic from the goofy raygun origins of Star Trek. It’s hopeless. It looks like it would have difficulty staying in one piece if it was a model, much less an enormous starship exceeding the speed of light. Somehow the disconnected nacelles of Discovery future ships are more credible than this toothpicky monstrosity.

Many attempts have been made to make it look good, but they have failed. At some point we need to let go of the past and stop rehashing it endlessly for nostalgia money.

Now excuse me while I write the rest of this list heavily biased by nostalgia.

12. Enterprise J

Kinda cool I guess. Or at least cool-adjacent. From that one angle. It’s a one off future that isn’t nearly as clever as the more fleshed out future in Discovery while still trying to communicate the same progression we see from Constitution (big nacelles, small saucer) to Galaxy (small nacelles, big saucer.)

When seen from other angles though, you realize it’s a silly twiggy thing that’s about as sleek as a caltrop.

11. NX-01

It’s trying to be an Akira, but also look like the Phoenix (the little rocket from First Contact) and also like the Constitution. It fails on most of those counts. Everyone inside is dressed like NASA astronauts but the ship looks like a flying saucer. Or a misshapen loaf of bread. In the opening credits we see something that looks like a Lockheed Venture Star with warp nacelles. That would have perfectly matched the vibe the show was going for, but they needed it to look like every other trek ship presumably due to branding. Product of compromise I say.

10. California

The Cali is jank, but of course it’s jank. It’s supposed to be jank. That’s the whole point. It fits the story role and theme of Lower Decks perfectly. It’s the Trek aesthetic taken to a silly extent. It’s unbalanced. It’s got a weird configuration. It looks like it’s about to tip over.

Still gets a low ranking, though, because its jank is somehow more severe than the other jank. Where is your center of mass, Cali?

9. Excelsior

Big long and stately like an ocean liner. Also good looking enough that I don’t hate that it’s the generic federation ship they always use when they need another ship to avoid confusion with the hero ship. Kinda funny that it’s introduced as an unreliable heap dismissed by Scotty and later it becomes the backbone of Starfleet!

It would probably be higher if it’s elbow pylons weren’t so out of place on the otherwise elegant flowing design.

8. Intrepid

Good design overall, but the proportions are very weird and the inline nacelles never looked right. Has some good angles, some weird angles. Don’t get me started on the articulated nacelles!

It definitely sells the premise of a small under-equipped ship far from home though, a muscular design like the Akira wouldn’t have fit the bill.

Would have been pretty sick if they’d visibly patched it with Delta Quadrant tech so that by the end it looks unrecognizable, but the budget certainly wasn’t there for that.

7. Defiant

Federation BOP. It looks and flies more like the Millennium Falcon than any Enterprise. In the grand scale of Trek ships it’s more like a fighter than anything else a Starfleet captain gets to play with. It’s a runabout with all the concentrated high tech rage the Federation can muster bolted on, and wrapped snug in a hull instead of revealing its extremities. How they got around the ‘nacelles need empty space between them’ is anyone’s guess, but this is the only ship on this list that looks like it could take a hard landing and ever fly again.

‘What if Starfleet but no more Mr Nice Guy’ is not only a perfect description of this ship, but also of it’s Captain, Benjamin “For The Uniform” Sisko. That’s right, Benjamin “In the pale Moonlight” Sisko. It has the rare distinction of being the only ship on this list (to my knowledge) employed to ruin a planet’s biosphere on purpose.

6. Sovereign

They blew up the Enterprise D because they thought they could design something that looked better in widescreen.

Let that sink in.

The Sovereign has pretty good proportions but it’s a bit long (widescreen!) and looks less impressive from below. On top and on the side, though, it looks tough. It’s got the benefit of the whole TNG era development of design language plus a special effects budget. It’s sleek and a bit mean, befitting the darker, edgier take on Piccard in it’s debut film, First Contact. After it’s one action sequence, it spends most of the movie getting taken over by aliens, which is the normal occupation for a TNG starship.

5. Crossfield

You have to admire the decision to go with something so different from other Federation ships-unique design elements like the multi ringed saucer and huge delta shaped engineering hull and (eventually) disconnecty nacelles that float around adorably during spore drive jumps. It’s a bold design that signaled that the show wasn’t going to be a rehash in the way that the movie series that preceded it was.

4. Nova

The Nova takes the aggression of the Sovereign, cranks it up, and packages it all into a cute little spaceship smaller than an Intrepid. It’s design wasted on a science vessel; it would have made a better design for the defiant if it had existed a few years earlier.

I will confess some bias here; it’s one of the ships you can fly early on in Flash Trek: Broken Mirror, and it made me feel like I’d made it as a starship captain.

They also gave Harry Kim one as a joke (it’s small and they named it the Rhode Island) which is hilarious.

3. Ambassador

Remember how this started as a response to Ars’s ranking of starships? This is the part where I pretty much agree.

The Ambassador somehow manages to nail the ideal proportions for a standard configuration starfleet vessel. The nacelles aren’t too big, the engineering section isn’t too flat, everything is just right. It’s like if you asked a kid to sketch a new starfleet vessel and didn’t nerd rage when they failed to perfectly match the jank of the Constitution and the Galaxy. It’s design fades into the background like a good soundtrack.

I will confess to bias here too, because I had the micro machines version of this (as well as others) but this is the one that no adult could recall from the show and thus impose some sort of story value on it; I was free to make up my own space adventures for this little guy.

As you can see, Galoob took liberties designing this model, it’s more detailed than the studio model in some places!

2. Akira

Another tough looking federation ship. This looks like starfleet took a nod from the Klingons. The downward angled arms give it a fierce bird-of-prey visage. It has a couple of weird angles, but overall it looks great and has solid proportions. It shows up in the beginning of First Contact to represent a starfleet ready to fight the Borg after the disaster of their last serious showdown, and has some great shots executing Piccard’s plan to blow up a Borg Cube. It looks sleek and mean but still weighty which is a rare mix for a Trek ship.

1. Galaxy

I don’t care if it looks jank or top-heavy. The biggest statement it makes is: this ain’t hard scifi. It’s carrying a whole civilization around in that giant saucer. A world that the audience will love to inhabit episode after episode. So of course it’s got a big silly saucer. It still somehow looks less likely to fall apart than the Constitution.

If the constitution says ‘this is schlocky space western stuff’ the Galaxy says ‘This is high concept science fiction that we are going to take extremely seriously, perhaps too seriously for a few seasons.’

If the Defiant is the Federation’s closed fist, this is the Federation’s welcoming wave. It says “look, we mastered physics completely, but we don’t want to fight about it, we just want to party on the holodeck while we explore the farthest reaches of the universe.” And that’s the kind of optimism that Trek can, on a good day, embody.

Small Stuff

Looking back at this list, it’s interesting what stuck with me. They’re all vehicles! I guess I just find vehicles appealing. Some vehicles toys are well documented, so I won’t bore you with a repetition of the hotwheels wiki. What i want to consider today are what you might call modern “Penny Toys” are the kind of thing you’d find in a gumball machine, or on the table at the end of a party, discarded. They’re of a sort of hard to find now: not tied (legally anyway) to a franchise or character. But there’s something alluring about the mystery of trying to track down who made them, so let’s do it.

Bruder Mini: Space

Bruder is a toy company that still exists, making die cast vehicles. They no longer support their line of “mini” plastic vehicles, though they mention it in their history. There was a space line in silver, white, and blue, and more realistic vehicles in bright colors.

In Unit 01 colors no less. I’ve seen a small number of other palettes online.

I don’t know if the zany colored ones came out before or after the more common blue/white/silver ones.

Saucer in classic colors

Bruder Mini: Trains

Though long lost, I definitely had an an engine and a couple of passenger cars. Managed to find a lot of them on Ebay. They’re still adorable. They’re a neat combination of bright colors, crisp detail, and functionality. Not perfect fit and finish by any means, but at this price point, who’s complaining?

Accoutrements/Archie McPhee

These designs seem familiar

Not everyone was content to use public domain designs like flying saucers.

The easy part of figuring these out is figuring out where the design comes from-they’re mostly vehicles from thunderbirds (ignore the Star Wars one for now.)

You can see that the mold has been altered-it used to say Hong Kong but that’s been scratched out and China has been added.

The holes made them perfect to mount on Micromachine star trek stands

I initially had a tough time finding any attestation of these neat little plastic ships online. I know that at one point Accouterments sold them in a big tub (probably a gross each) but I can’t find that product photo any longer. I know I discovered this during the google era, because the models on the left are ones I purchased online.

I sent an email to Archie-McPhee, who got back to me with a link to this archived page:

Never seen the aliens before

They were called ‘alien and spaceship invasion.’ No luck on the star wars ship. I do wonder if it came from the same factory, but I have very little to go on for it. It uses a different type of plastic, but I swear the overall sensibility is similar enough. It came in a grocery store blister pack with a cooler looking spaceship with the same ‘moulded top screwed into acrylic bottom’ design, and a short knock off lightsaber type thing.

Z-Cardz

These plasticard punchouts came in randomized packs. The ink has held up surprisingly well. Influences are sometimes clear-a couple look like they’re from Cowboy Bebop, and I think I see a Droid Fighter. Classic shmups seem to have influenced these heavily as well.

We had a lot of fun building these back in the day. I managed to get my hands on some un-punched ones, remind me to scan them so you can make your own copies out of plasticard. If that’s important to you for some reason.

This product line eventually evolved into much larger more detailed models, and apparently a tabletop game.

Shackman & Co Five Piece Train Set

Five to a pack

It was surprisingly easy to find these considering I had only a single one and no accompanying documentation. I think I just searched for “small plastic train 90s” and the like.

These seemed to have a random assortment of colors. They’re four parts: two sides, top, and chassis. Very neat little pieces. All identical. They shipped in a Christmas ornament which itself looked like a train. Something about the soft shape and tiny size made them super appealing to my kid self. Always wondered if there was a whole line of these, but it’s just the one mold.

Pretty close to N scale though.

I heard you like trains so I put a train in your train

Road Not Taken: Godot’s VehicleBody in Hovertank22

It’s no secret that I’ve been captivated by trying to make vehicle driving feel good for as long as I’ve been programming. Initially Hovertank 22 (formerly OWTD) used Kinematic movement as described here. But it wasn’t quite right. I have a strong memory of how much more fun World Of Tanks was after they introduced proper physics. I decided that if a third person perspective (as oppose to top down) was going to be used, I should probably use some sort of physics.

In Godot you have at least two options: the ‘easy’ one, using VehicleBody and the hard one, using a bunch of 6DOF joints. I elected to use the former, in this barn-burner of a PR. And it… well it sort of works, I guess.

As you can see, though wonky, the Tilter is able to navigate the terrain. It’s using a single visible steering wheel in front and the tracks are represented by two invisible wheels in the back. This movement model is, of course, built for car driving games, so the trike configuration cuts into the stability badly. The requirements of “Eamonn’s Ideal Vehicle Game” and thus Hovertank 22, however, call for tanks. Unfortunately, this has major disagreements with the movement model.

The basic idea, I figured, for implementing tank movement has been to treat each track as a series of wheels. To turn right, you drive the wheels on the left side and brake or reverse the wheels on the right side. In a real tracked vehicle, this causes it to turn. In Godot’s model, however, wheel slip seems to be very all-or-nothing: the vehicle stays in motion nicely but as soon as you cut the wheel and one track slips, the whole vehicle starts to drift uncontrollably. While some amount of drifting was desired, this turns out to be unplayable. And, worse, messing with wheel slip values didn’t really help.

Editor screenshot showing how the Cobra’s wheels are configured

Another problem with this movement style was that when the vehicle was in motion, differential steering worked far more effectively than from a dead stop (I assume that this has something to do with how overcoming friction is coded.) In order to turn from a stop you need to overcome the friction of all of the wheels, so turning while stopped was impractically slow. I implemented a fix which increased power when you weren’t moving but it was unsatisfactory and resulted in a vehicle that jerked around suddenly and violently.

I suspect that customizing the 6dof version might be able to overcome these limitations, but I don’t have the bandwidth to try it. Similarly, it might be very possible to implement this sort of thing as a custom integrator and bunch of rays, but again, that was more of a lift than I had time for.

Faced with basically a negative result from this experiment, I’ve decided that I’m going to roll back (ha) from the VehicleBody approach. I may switch back to a top-down perspective, and also may try switching out heighmapped terrain for tile terrain.

So what did I learn from this little excursion? You really need to validate your assumptions about how something is going to behave before you stake a project on it. I’m glad I didn’t fully do that (I still have a path forward for Hovertank ’22), though pulling it out is definitely going to be a setback.

The Lost Continent: Australia on Westfield’s old globe

The central feature of Westfield State University’s campus is a large globe sculpture. This has been true for a while, but not always the same globe. In 2015, during the excitement around the Patriots Superbowl win, enthusiastic students cleared the benches, rejoiced on the green, and climbed inside the globe. This wasn’t the first time the campus had hosted an impromptu outdoor party of this nature – I seem to recall a similar reaction to a Redsox championship in 2013 (but it could have been a playoff game – my memory is foggy. But this time, the globe sustained major damage. The overly enthusiastic students shook the globe until it strained against its joints, and ultimately failed in several places. Tectonic plates torn asunder like something out of a disaster film.

You may notice from these pictures that the entire continent of Australia is missing. However, this was a pre-existing condition – I’m pretty sure the absent continent left a hole which allowed the revelers access to the interior. So consider this excerpt press release that the school released about the incident:

The university inherited the Globe from Stanley Home Products and it is missing the continent of Australia because it was not within Stanley’s global business reach.

Contemporary statement from the WSU spokesperson

This is an incredibly weird statement. As you can see from the first image in this article, the globe used to feature Australia. The loss of Australia running joke on campus. Rumors abound about where it ended up (which I won’t relate to protect the innocent… or guilty.) The story was, however, that it up and fell off. To my knowledge, no great effort was made to replace it.

So why make up this absurd lie? It’s so easily verified to be false – campus promotional material (including the desktop background of campus PCs, the file photo above!) contained images of Australia on the globe. Anyone who’d attended the school during or before 2011 (latest possible year it could have fallen off.) It’s just a silly idea: nobody commissions a globe sculpture missing a continent. It’s not a thing people do. Nobody would accept a donation of an incomplete globe like that.

I guess I’d never imagined that level of brazen dishonesty from an institution before. I suppose that was a very naive, 2015 attitude to have.

The author of the statement was contacted for further insight, but there was no response.

The damaged globe was replaced by a much nicer sculpture which does feature Australia.

Name Collisions in EV Nova

EV Nova was a formative game for me. One thing I noticed about it, and wanted to document, was that there are a lot of what I’ll call name collisions: names that are almost the same but refer to different things. Did I miss any? Leave a comment, I’ll add it.

Temmin Shard / Shard (faction)

LPAD station, where Temmin Shard takes you

Temmin Shard is a character in a side quest. However, “Shard” is also used to describe a faction formed when you win the Fed campaign and everyone else comes after you.

Krane / Kane (incl. Port Kane, Kania, and the Kane band)

Port Kane
Earth, with Kane band, but also a place where you might encounter Krane

Omata Kane invented galaxy-spanning hypergates and a bunch of things are named Kane in her honor, including earth’s artificial ring, the Kane Band. There’s also a Port Kane in the Kania system. Krane is the sociopath leader of the secret fed faction that you work for in some campaigns. Very different people.

Glimmer / Gli-Tech / Gli-Tech-Nia

Home of the GLi-Tech corporation (formerly known as GLiMMER until the discovery of the Glimmer system)

Both are companies that make missiles. Huh? Gli Tech also owns an entire planet, called Gli-Tech-Nia. But wait, Glimmer is also the name of a star system. Surely this piece of fluff for Gli-Tech-Nia clears it up:

Associated Guild Of Free Traders / Free Traders

Pirate carrier used by both

Two opposing pirate factions that fly the same ships. One is hostile by default, the other isn’t. No idea which one though; and feds don’t care which one you blow up either. According to Word Of Atmos this is intentional.

Polaris / Polaron Cannon / Polaron Torpedo

Polaris are one of the game’s major factions. Polaron refers to a Federation weapon. But the weapon is pink… the color of Polaris technology. And the Polaris have a Polaron Torpedo which is pink but apparently unrelated. Maybe Polaron refers to some specific scifi gubbin, but then that’s still colliding with the Polaris.

Vella / Vell-os

Vell-os are a race of psychic transhumans and mostly extinct, Vella are a neighboring Arouran subfaction.

Wraiths / Wraith Cannon / Wrathii

A wraith
Wrathii fired from a Wraith cannon (no relation)

Wraiths are a race of sentient space-monsters, Wrathii are pink projectiles that the Polaris fire out of a Wraith Cannon. Also the Wraiths are right next to the Polaris.

TOWCB / TCTLIDS

The Ones Who Came Before are your standard ancient race of aliens trope, TCTLIDS are The Creature That Lives In Deep Space harvested for drugs, an abandoned plot hook that somehow remained in the timeline preamble.

Making a Hovertank level: Godot map editing

(Updated to reflect that this has been released! https://github.com/EamonnMR/hovertank-22/)

Hovertank is an honest attempt to bet big open 3d environments with AI agents running around working in Godot, using HTerrain and Godot Detour. I hope this is helpful for anyone who wants to make something similar in the future.

See also: https://hterrain-plugin.readthedocs.io/en/latest/

Set up terrain nodes

Create a new inherited scene from the “world” scene.

Add an HTerrain element to your level. Make sure it’s collision layers are 1 and 8.

Create a data directory in the levels folder

Apply a tileset to your HTerrain by dragging tileset.tres into the texture set slot, or making a new one from scratch.

Edit the terrain to your heart’s content using the generator and the tools.

Bake navmesh

You’ll need to repeat the next steps each time you edit the terrain mesh

From the “Terrain” menu up top, select “Generate mesh (heavy)” and select an LOD of 4. At least that’s what I’ve been using.

It will create a node called “HTerrain_fullmesh.” This is the node that the pathfinding library uses to actually determine where AIs can go. Hide this mesh; if you need to see the navmesh turn on “visible collision shapes” and you’ll see it (and it may lag real bad!)

Note that the flattened areas have nice clean navigation, but the more sloped areas don’t. You can use the flatten tool to cut paths across the map. Make sure you enable “pick” on it, it’s much nicer that way.

Place Entities

The prefabs folder has enemies with preconfigured weapons you can just drop right into the scene. You’ll want to drag them a bit closer to the ground though.

You can also place buildings this way. Careful not to accidentally parent stuff to random entities you’ve already placed – entities in Hovertank expect to be parented to the world.

You can set up objectives by adding the “ObjectiveMarker” component to an entity.

When all of the entities with objective markers are destroyed, the player has won the level. You can add the objective marker to any enemy or building.

The incursion spawner will spawn the entity you provide in “spawn” whenever there’s an incursion with the selected severity. Put one of the monsters in there by dragging its tscn file in to the spawn field (only monster at time of writing is our friend Kochab) (Incursions were removed, but you can see how it worked in older commits — Ed)

Add your level to the list

Add an entry to the big literal with all of the levels pointing to your level’s TSCN file, give it a name and a description, and it should show up in the dropdown in the main menu.

Cars of Paris

It’s been too long since we went to Paris (in 2021) for me to properly caption these cars. But hey, I did take pictures, so let me at least post them.

The “front is the same as the back” aesthetic
Lean your Citroen
not a jeep
Car disguised as a train
not a car
Cassette Futurism
Very old car, seen inside a castle
classic car
we saw these everywhere, and I love them
Majestic car befitting the obelisk it’s parked looking at
Someone took really good care of this classic vespa
Round Car
Saab

Practical Godot Networking: MPEVMVP technical discussion

Godot’s High Level Networking tutorial (and book chapter) do a great job of explaining a peer-to-peer networking setup. However, many games want to be server-authoritative, and to set up a multi-area game, you sort of need to. Luckily, you can use the same primitives to build a server/client game. This is just sort of a brain dump of my notes that may be helpful in navigating the MPEVMVP source. Feel free to post any questions you have about it; I love to talk about this stuff.

The technical requirements that deviate from the basic tutorial they hand out are as follows:

  • Server-authoritative client/server game
  • Multiple levels that players can switch between
  • Players are able to join a match in progress

In case you haven’t tried it, the project is here: https://github.com/eamonnmr/mpevmvp. The gameplay is similar to Asteroids (and, well, similar to Flythrough.Space): it uses RigidBodies to simulate movement, you can shoot other players to force them to respawn, and you can press “J” to initiate a hyperjump after you’ve pressed “m” to select a star system from the map.

Godot’s Networking Golden Rule

A remote call (rpc, rset) is going to be called on the remote node with the same node path. That includes name of the node, the name of the parent, etc, all the way to the root node. You can set a child node’s name with set_name but if a similarly named child already exists, an @number will be added to your node. This is a major source of bugs for networked projects, so be careful. You cannot set a node to a name with @ in it. So in effect, you cannot use Godot’s auto-incremented names (since they append @increment) to sync between the client and the server. For this reason, I used a uuid library for generating node names.

The need for the same structure on client and server despite the fact that the server held a whole universe while the client only cared about one system is a major source of complexity in the codebase.

Server Authoritative

I implemented the Client and Server as singletons that exist on both sides. The reason for this is that it makes it really readable; when the client needs to send something to the server you write Server.rpc and when the server needs to send something to the client, you use Client.rpc. Besides this line of communication, I’ve used rpc and rset within various nodes to update and alter the client versions of themselves. This always happens inside an is_network_master block, to ensure that it’s being called on the server version of the game.

The one thing we do need to gather from clients is input, and for that each client has a PlayerInput node, network_master’d to them. They rset_id input up to the server. The server copy of the player nodes looks at this remote copy of the player_input to determine it’s behavior, then pushes its state back down to all clients.

Multi Level

Suppose you want to have multiple different levels/worlds/rooms in your game. The trick is that you need to mesh the following two constraints:

  • Node paths need to be the same between client and server (see discussion above)
  • The server needs to have different node paths for each level

The trick, then, is to send the client to the new level by loading the appropriate level and making sure it’s named appropriately. There’s one wrinkle though: different 2d physics worlds need to use a Viewport class, but you don’t want to add additional viewports on the client for performance reasons (tried it, it was way too slow.) My solution was to add an extra layer of nodes called “universes” in the comments which are a Node2d on the client but a Viewport in the server. They are managed on the server by ServerMultiverse and on the client by ClientUniverse. Client Universe cares about a single “universe” child whereas ServerMultiverse handles multiple children.

Sending Entities/Switching Levels

In order to join a match in progress or switch to a level that already has stuff in it (or, indeed, switch a player into a level) we need a robust way for the server to move fully-formed nodes to the client. Godot does not provide a generic “send this node” method, so we need to write one for ourselves. The approach I took was:

  • Assume that the ent will be instanced from the same scene that the ent on the server is
  • Write a “serialize” and “deserialize” method that allows it to dump a dictionary with all of its important state and recreate itself from that dictionary.
  • Make sure the node on the client side is assigned the same name as the one on the server side.

So when a client’s level is switched, they dump the current level and recreate the new one by loading in the scene and then, node by node, deserializing the state sent from the server. As it turns out, this means that any state can be synced freely, and it enables us to dispense with the lobby entirely and let players join and leave at will.

Sync In Multiple Levels

Each level owns the process of syncing its state to clients in that level. Scenes within the level can declare a method that serializes their state for a net frame, and the level gathers all of those up and sends them. The client receives the frames from the server, and the individual scenes use the content of those frames to interpolate their position. To save bandwidth, I only do this for ships and guided projectiles, everything else moves deterministically. This whole process is derived from the teaching of (and better described by) this video.

Player Lifecycle

Because we’re using the player’s presence in a level to determine if we should update entities in that level for that player, when a player’s avatar is destroyed the world seems to stop for that player until they respawn. This might be desirable in some games, but I think most games at least want to show the player the immediate seconds after their own demise. So what we do is replace the player with a ghost.

Tooling & Workflow

GDScript is based on Python 3 and the most basic syntax resembles it. ‘func’ in place of ‘def’, no ‘self’ and no list or dict comprehensions or other advanced features. It feels like the python of basic python tutorials. However in exchange for this, you get one thing python 3 does not offer: true static typing. In Python 3 you can offer a type hint for a function argument but it is not truly enforced. GDscript enforces the types at compile time and boy does it ever catch a lot of bugs. You also get the ability to define classes with typed members, similar to what you get in Python with Pydantic. Overall I like gdscript and the things I miss aren’t dealbreakers.

The lack of a vi mode for the editor hurts. I know I could just use the godot plugin for vi, but I actually really like staying inside Godot’s editor. Despite the slightly crowded layout, it’s really very nice. The autocomplete to node paths is a killer feature that makes dealing with complicated trees less of a pain.

Conclusion

Building a multiplayer game in Godot is possible but by no means easy. The high level multiplayer API despite its gotchas works well, but you need to implement the sync logic yourself. This shouldn’t be too surprising as games have very different needs when it comes to net code. I hear that a similar mechanism for frame based sync and lerping is going to be more built-in in godot 4, which would be sweet. The puppet system (which I initially used; you can see a version in the tutorial) seems to be useful only for very low latency situations, so I regret that it’s a first-class feature because it may lead people down a rabbit hole of net code that will not work for most games.