Sandbox Logo
31 October 2022

October 2022

Addons, Razor, New Menu, Hammer API, More Cloud Assets
Being able to easily live-edit geometry would open up a ton of possibilities when making games. To that end, I've built a simple toolset based around constructive solid geometry.
You can add and subtract brush shapes with arbitrary materials like this:
var world = new CsgSolid(); world.Add( CubeBrush, DefaultMaterial, position: Vector3.Up * 512f, scale: new Vector3( 8192f, 8192f, 1024f ) ); world.Subtract( DodecahedronBrush, position: Vector3.Up * 1024f, scale: new Vector3( 1024f, 1024f, 512f ), rotation: Rotation.FromYaw( 45f ) );
Check out CSG Demo in-game to play around with what we have so far. My CSG library is available on GitHub if you already want to start integrating it into your own games, although be aware that it's still pretty experimental.
We removed hitgroups in favour of tags, similar to how we use them for collisions. Here's how they work.

MODELDOC

When editing a hitbox from ModelDoc, you'll see Hitbox Tags. Populate them with some useful keywords like so:

C# API

When running traces, you'll see TraceResult.Hitbox. That'll hold all the info you'll need when interacting with hitboxes. We also pass it with DamageInfo.

Before, it didn't make much sense:
var isHeadshot = GetHitboxBone( dmg.HitboxIndex ) == 1;
With tags, it's way easier to understand at a glance:
var isHeadshot = damageInfo.Hitbox.HasTag( "head" ); if ( isHeadshot ) { // Multiply headshot damage by 2 damageInfo.Damage *= 2f; }
I added addons this month. Previously we kind of had addons, but only one could exist at a time, and they were games. 

General Addons


You can create general addons. These will work with any game. An example of a general addon is one that makes everyone's head a pumpkin, or one that spawns grass everywhere.

TARGETED Addons


A targeted addon targets a specific game. For example, to add a gun to a specific game, or to add an entity/npc/tool to sandbox mode.

GMod Differences


Because Garry's Mod uses Lua, it's not hard typed. The code doesn't need to know what other code exists. It gets loaded and then it can feel around to see what exists.

S&box uses c#. It's hard typed. The code for the most part needs to know what's there before it can load. Over the past 20 years coders have realised that this is probably a good thing. It allows you to see if the code works when you compile it - instead of when you run it. Look up typescript for a good example.

This puts restrictions of what we can do in a few ways but ultimately it's a much better development experience.. because you get things like intellisense and compile errors.

Workshop


We don't use workshop. You don't need to subscribe/pre-install addons. You choose the addons you want to use and play, everything else is taken care for you in the background.

Next Steps


This was the first step, there's still plenty to explore here. Ideally you won't have to choose the addons before you start the game.. they should really just download and spawn in your game like the cloud models.
I opened photoshop just to use its color picker, then realized how wrong that was.  So, I added our own color picker to the editor.  It can be opened by clicking on any color property in the inspector, and changes can be seen in real-time.

Histograms are a great way to get a sense of how your score compares to
everyone else's, and are more meaningful for players outside the top 10. You can now see periodically updated graphs showing the score distribution of any
leaderboard using the new API.
James has been adding some 2D sprite functionality at my request, and a simple project to test it out has now ballooned into one of those action roguelites that are so hot right now. 

Not really a genre that makes much sense for s&box, and having hundreds of networked enemy entities seems to be causing issues with player prediction, but hopefully we can work it out.

We used to have a prototype called Arcade, I spent some time porting the API to s&box so we can preserve it and as an example of the possibilities of making 2D games.

This month I've been developing a new system to streamline the creation of Unicycle Frenzy maps so that maps can be made at a much faster pace. Up until this point, every map started from scratch which gave us a lot of flexibility to make each map look and feel unique but because of the amount of time and effort to properly polish these maps, only a few have actually been finished.

So I shifted my thinking about how the maps should be made and instead of building each map from scratch we can use premade modular pieces and Hammer's tilesets to quickly build out a track while also having it look good.

Some early concepts
It didn't take long to get something up and going and I slowly started to add more elements over time to help ground everything.
I wanted to give things a little more flare than just a track surrounded by canvas towers so we started developing some scenery with help from Louie.
And finally, we added some signage with help from Lewis to fill in some empty spaces and give it a greater feeling of authenticity. Here's a video of a nearly complete track with how everything looks together.
I'm very happy with how the modular/tileset method is working so far, I think we've been able to get a lot of diversity with how each track feels and there are still a lot of ways we can expand things in the future. Instead of it taking a month plus to finish one map now they can be made in a matter of days. The maps lose some visual uniqueness with this method but I think the trade-off is in our favor, being able to quickly make maps will allow us to create way more content than we otherwise could.

I got sick of working on Hammer in C++, so over the last couple of months I've been working on a C# API for tool addons to extend the functionality of Hammer.

You can do a lot with this already: create procedural meshes, place entities, get selected nodes, add new menus - and all from C# with hot loading.

I've made a wiki page on most the things you can do and you can also check our API docs for Tools.MapDoc and Tools.MapEditor namespaces.
I updated the old addon manager and combined it with the UI and Entity inspectors to become a centralized explorer panel.
The UI explorer itself got a lot of work too. It lists the UI panels out like html tags now, and you can see where each element was defined in the razor file (if it uses one). You can even jump straight to that element definition in the source code.

Our asset browser is now usable in Hammer, it was there before for cloud models but now I've hooked everything up - selecting materials, drag data, Hammer specific asset context menus.

Once everyone is happy with it we'll switch the default over to this instead of legacy, so if there's something it can't do (that you need) please let us know.

Asset pickers

I've also swapped a bunch of the asset pickers from the various native implementations to a unified one of our asset browser.

I won't show you another picture of the asset browser, but this basically lets you choose cloud assets through this in Hammer too.
I've added materials, sound events, and soundscapes as available cloud assets.
Just like cloud models these can be dragged straight into your Hammer map.
Surprisingly the only thing you could drag onto maps before was only models and materials. Adding support for anything else was a pain in the ass so I made a quick way to do it with the Hammer API.

With this API I've made it so you can now drag sound events and soundscapes into maps straight from the asset browser.

And as a bonus this works in tool addons, meaning you can easily create your own drop targets for custom asset types. Here's how to implement your own.
It's a bit of a joke that everything  I do ends up turning into a revamp of a UI system. So here's how this came about.

The addons needed main menu ui changes. So I started doing that and I realised that it'd be a bunch easier if our HTML-like template system could have some basic logic blocks. So I started coding that, basic if blocks etc.

So about a day in I realised that this was fucking stupid. I was basically making a stupid way to make Razor templates.

At this point I have two options. Carry on down this path, knowing that I'd likely throw all this code away, just to hack it all in so I can carry on coding the addon stuff.. or I could spend a week seeing if it's feasible to use Razor. 

How this works


Our UI isn't a html renderer. It's panels, like vgui or derma. But we can parse html/razor templates and build those panels.

So your razor code might look like this..
<root class="player-row"> <div class="title">@Player.Name</div> <div class="score">@Player.Score</div> @if ( Player.IsAdmin ) { <div>ADMIN</div> } </root> @code { public PlayerEntity Player { get; set; } }
The Razor system converts that to c# code. The c# code basically builds the actual UI panels. This is called building the render tree. Any time any of the contents are changed in this component, we'll rebuild the tree.

Rebuilding the tree doesn't mean creating new panels every time. It's smart about it. It'll only create a panel if it's missing, or delete one if it's no longer in the tree.

The nicest thing is it's component based. So you might have another Razor file that looks like this

<root> @foreach ( var player in Entity.All.OfType<PlayerEntity>() ) { <PlayerRow Player=@player></PlayerRow> } </root>
And that'll create the PlayerRow panel that was defined above, for each player. This is simple stuff that was so frustrating to do in the old system.

Why does this work?


This is the perfect fit for s&box because of our hotloading. You can save your code and in half a second it's updated. It's the exact same with these razor files. 

This wouldn't really work in other engines, because they can't hotload like we do. Even the actual Razor/Blazor doesn't work as good as this does in terms of iteration.

What sucks?


Intellisense doesn't work great. It works well enough, but it could definitely be better. This is really a visual studio thing. For some reason they ship all of the tooling with Visual Studio, so you can't just grab it and make your own version as far as I can see.

I tried a few things to make it better, like mocking up all the classes that their internal tooling looks for in the assemblies, but in the end it was no good. 

On the bright side this is only something that can get better.

More Information


I made a page on the wiki about Razor and how to use it. I have for the most part kept as faithful to the Blazor component syntax as possible, so it's a transferable skill.
This month I worked on getting my 3D Platformer Super Tumble polished with new UI and Art. As primary a level designer I've had help with code from the team, but also learned a bunch myself from just messing around and using other games as examples on how to tackle certain problems.

I asked Lewis for some UI concepts that me and Tony then implemented.
I also spent some time arting up the main map, giving it a cute/ fun look as if it was made out of toy construction set. Ending up with a unique looking enviroment that is clean for gameplay and also fun to look at.

Here is a quick little video of it all together.
Getting addons working was one of the big tent poles we needed to do before release.. so it's nice to have that done. It's put a lot of runway under our feet.

The forced menu rewrite was unfortunate and has left a few things in disarray, but it had to happen sooner or later.

I'm going to spend the next month polishing and finishing those two things and working on some stability issues, then the next step will be to rewrite the Sandbox mode to take advantage of it all. At that point we're ready to think about release 😍