Sandbox Logo
01 November 2021

October 2021

Lobbies, tools and shaders this month!

When you start the game you'll see a list of games with active games. 

When you open a game you'll see a list of lobbies. You can join these lobbies or create a new one. When you're in a lobby you can talk to other lobby members and join the game.

The lobby allows you to define the game settings before creating the game, and the other lobby members can see what those settings are. This is going to be expanded in the future with more game specific configs.

While this works like a regular transient lobby system right now, where games disappear when no-one is in them, the plan is to make them also work for dedicated servers.

This is about choice. It doesn't make sense to have a dedicated server for chess matches. It doesn't make sense to have lobby listen servers for multiplayer survival games. We should be giving the choice for games to have one, or the other, or both, or none. 
Max wanted to see the weights of each clip in animgraph blend nodes, so they now get slightly tinted so you can quickly see which clips are active.
Physics now get updated when surface assets hotload, that means no restarting the game to see surface property changes, yay
For the scoreboard we had a system called PlayerScore. This was necessary because not all players were networked to all other players. 

This whole system is no longer needed since we added the Pawn system. The player entities still exist, but they're just point entities representing the connection to the server. And they're always transmitted (they're represented now by the Client class). 

So we can use those to store kills and deaths and show them on the scoreboard.
When you hit delete on assets in the asset browser a window now pops up. This lets you configure exactly what you want to delete without finding all the content files yourself.
We now have a proper glass shader that has screen space refraction. It not only supports refractions but also blurring, masks and normals.
We have reworked how we are doing model skinning and other low level operations on our rendering pipeline this month.

This caused some problems initially on people with certain hardware configurations but forced us to refactor the code even further, this also helps us a lot to iron up our internal codebase to be easier to maintain in the future.

For players you will encounter significantly decreased compile times for shaders and skinned models should render faster, no input is needed to receive these changes other than recompiling your shaders.
We've been struggling with text shadows for a while.  At first we were doing them procedurally, taking the text texture and running it through a shader to blur it and render it the right colour. This worked, but because the shader was blurring every frame it was a bit of a performance problem.

So then we started rendering the shadows to their own texture, blurred using Skia. This also worked but we had problems with alpha fading to black and the code didn't feel very eloquent.

So this weekend I went in and tweaked our fork of RichTextKit so we can add a bunch of effects to the text during the original render. This has made the code much smaller and neater, and solved the issues I had.
I'm a bit of an extremist with our css styles, I don't like adding new arbitrary style properties that aren't part of the web. But even though text-stroke isn't actually totally legit, I added it anyway.
Adding this property makes sense to me. It means people won't have to add 4 shadows to create the same effect, so it's a performance win. Plus come on text-stroke is almost common use, even if the web one does do a dumb useless interior stroke instead.
In s&box I want all games to feel like games. They should all be able to have achievements, scoreboards, levelling, cloud storage and whatever else. It makes sense for us to do that heavy lifting instead of each game implementing their own.

The games we created so far are aimed at helping implement and test these implementations. This month I somewhat managed to implement ranking and leaderboards into facepunch.pool.
This is the first implementation of this. What I envision is that different games will use the system slightly different - so I am preparing to cater for that. 
Binding values in templates is nice and useful.
<text class="section-text" @text="GamePackage.Summary"></text>
But sometimes I found myself wanting to do it in code, and ending up doing stuff in Tick instead.. That sucked, so I added a couple of helpful functions.

So now BindClass lets you switch a class on a panel if a condition is met.
panel.BindClass( "active", () => CategoryId == "vr" );
And Bind can now accept a function which returns a value
TimeScaleLabel.Bind( "text", () => Global.TimeScale );
You can add games to your favourites on the game screen, which also shows the number of people that have favourited it.
Your favourited games show in a list on the main menu, for quick access.
I debated how to implement ratings for games. Should it just be a like button, should it be like and dislike, should it be stars, should it be multi-category stars?
In the end I think like and dislike are the way to go for a high level. This is easy to do and easy to read. 

There's debate on the discord among developers whether dislike should be included. Whether it's toxic and encourages drama. My attitude is that on a high level it works for players - which is the most important thing. 

In the future we will have full reviews and feedback, allowing players to give more useful feedback to help devs improve their experience.
Categories now show the number of games in each category. We also have the ability to filter games by VR, M+K and controller.
Games can now access the Lobby via Global.Lobby. What this enables could be interesting.

Right now when you start a game with your friends, you're creating a server and your friend is joining. When you quit the game, it ends for your friends too.

What you could potentially do though, is run the entire game through the lobby.. so there is no server. This would mean that when you leave the game the server doesn't die. Someone else just becomes the lobby owner. The game only dies when no-one is left in the lobby.
It became noticeable that the menu would freeze for up to half a second when switching to the games list. After some profiling I found that this was due to loading of the game thumbnails.

While the download of the images was asynchronous, the decoding of them wasn't. Decoding the images now runs in a worker thread, so there's no more noticeable hitching!
I added a bit more expected functionality to our scss parser. So now you can do all this stuff.
color: darken( red, 5% ); color: lighten( red, 5% ); color: mix( red, white, 0.5 ); color: lerp( red, white, 0.5 ); color: mix( red, lighten(red, 50%), 0.5 ); color: invert( green ); color: lighten( $yellow, 5% );
This stuff comes in very useful.

 As an added bonus, you can also do this stuff in c#.
var myColor = Color.Parse( "mix( red, lighten(red, 50%), 0.5 )" );
I spent a week in prediction hell. No matter what I did the client and server would get out of sync with a fakelag over 200.

I found and fixed multiple bugs that no-one noticed existed, but they didn't fix anything.

In the end I tracked down the problem to some code I'd changed a few days earlier. As an optimization I changed the network variables so they didn't actually get written to the entity straight away, instead queuing up pending changes so we didn't end up writing multiple times for no reason.

Well turns out I was calling the function to flush the network data at the wrong point - so all the network data that was being sent to the client was a tick old.
Sometimes you find yourself accessing a component a lot, so you end up creating a property to get it. People were getting this wrong.. adding [Net] to try to network it and stuff like that.
[BindComponent] public InventoryComponent Inventory { get; }
So now you have this [BindComponent] attribute, which will codegen the property to always return the component if it has one.
I spent some time texturing some of Tom's models.

Burger Bag
Following on from last months fast food items we've now got a paper bag.
A nice QOL feature to quickly filter shaders in the material editor shader list.

Apparently CJK language users were having a few issues with the IME window popping up every time they pressed a key, even if they were in game.

This is now solved.. and we can use IME input.

We had three programmers join the project this week. This has already paid off as they've hit the road running, pushing us forward in a bunch of ways.

We could really do with some artists now. We've got to a point where we can start building a world. I'd love to hire a bunch of people to work on world art, clothing, props and weapon models. If you're interested please apply here!

Not to be too condescending, but I wrote something about applying for an artist job a while back on my blog here. Please give it a quick read to make sure you're not making any of these mistakes.

So anyway, I feel like we're in a decent position now in terms of being able to find and play games. My 8 year old son managed to do it all by himself - which is probably the best test possible.

This month I'm going to work some more on the GameService stuff. More leaderboard stuff, maybe achievements, maybe reviews. I want to organise a weekly, or twice weekly event where we can all be online at the same time and test out each others games. It'd be nice to have a system of giving feedback for that.

I've got a load of todo's written down to knock all the sharp corners from the process of actually creating a new game. I'd like to make some progress on that this month too.