I didn’t end up keeping to my plan of releasing this month due to a few issues. The main issue it is took me a few tries to get through the build review process, one issue was a crash on steamOS that seemed to be caused by webrender and the other issues were all multiplayer related. I managed to get it approved in the end. The other issue was between all of this I was ill making working on the game hard. Given the event happening on steam soon I’ve decided its best to delay the launch until after that finishes. On the brightside I have more time to work on content now.

UniverCity is a university management game being programmed in the Rust programming language.

Gameplay

Extensions are now automatic

Joining buildings as always been a bit of pain point with trying to keep it usable and bug free at the same time. Its been a few iterations and hopefully this one is the last. Previously to join two buildings you had to edit both and place the extension object where you wanted the join to happen. This was a pain to do as it required two object placements and had to be repeated for every tile along the edge. Along with this it was possible to cause breakages with removing extensions or the other building whilst something was placed along the join.

The new system is now automatic using a new update script system that was implemented. Simply placing a building near to another one will cause it to join up. In order to handle this across the network I used serde_transcode to convert a lua table to CBOR bytes and back again, this may get used in a few more places later as its really useful.

Steam Multiplayer

Steam lobbies list

I was planning on implementing this later but I decided it may help me pass the multiplayer issues in the review (no port forwarding required). I took this time to redo the multiplayer user interface. In the multiplayer menu you’ll see a list of open lobbies hosted by your friends, from that screen you can either host your own lobby or connect to a dedicated server via an IP address. The lobby now shows players with their icons and gives you an option (in steam lobbies) to send invites. This should making playing with other easier.

New Objects and texture swapping

New plant pots with a variant A world map globe New door colour options

To ease creating variants of objects I’ve added a way to swap the texture of a model at runtime.

I also improved the handling of objects for professors, they will now randomly walk over and spin the globe every now and again.

Internal

Crash dumps

One issue I was having when having people test my game was trying to figure out crashes. As mentioned in a previous blog post I replaced all usages of unwrap with a assume! macro that included file and line number information as well as logging to a file. This didn’t always help due to the fact not all crashes were on unwrap or even in my code (e.g. a library) and on Windows it seems like the log from assume! didn’t always make it in to the log file.

So I set out to build a crash dump system that would save backtraces into a file that I could read and debug, this sadly required going back to panic=unwind however. Using the backtrace crate inside a panic hook made getting the backtrace pretty easy however without debug information the backtrace was mostly useless. I initially thought about just shipping with debug=true as I really don’t care about protecting the code that much however this wasn’t going to work due to the increase in binary size, on linux the binary went from 12MB to 170MB. To try and work around this I stripped the binaries before uploading them keeping a copy of the unstripped binary as well, due to the backtraces including pointers as well I was hoping to just pass them to addr2line and get the function name and line number back. The issue was that the pointers in backtrace didn’t match up to the pointers in the symbols due to them being based on their memory location that was randomized each run. Whilst I’m not sure if this is a good solution I created a function called base_anchor.

#[no_mangle]
#[inline(never)]
pub extern fn base_anchor() {

}

This function had its pointer included in the backtraces so that I could use the difference from its memory location and its symbol location (obtained with nm to find it via its unmangled name). This difference could be used to shift all other pointers in the backtrace into something that could be passed into addr2line.

For windows it was pretty much the same except instead of using command tools I had to use the Windows API to lookup the symbols from the .pdb files. I used winapi plus some custom bindings to functions that winapi was missing.

So far these crash dumps have been pretty useful, hopefully if I ever get the time to clean up the code I could try and make this into a crate that can used for other applications too.

Steamworks

As part of the multiplayer work I had to improve my Steamworks bindings where I encountered an issue with the way steamworks handles structs. They actually use packed structs but the packing depends on if its on linux or Windows. I’ve implemented a work around via proxy methods for now until the packed(val) attribute becomes stable.

Minor things

  • Staff variants now can have their own icons
  • The default resolution is no longer 800x480 and instead defaults to your desktop resolution
  • The show required button now includes the number of required objects left
  • Clicking the show required now scrolls up to fix being left with a blank list when scrolled down the list
  • Scripting clean ups and optimizations. Removed a large number of allocations converting from &str -> CString
  • The delta encoding of floats has been improved to reduce/remove the error build up that was happening over time. Should fix a lot of pathfinding issues.

Twitch

I haven’t been streaming my work on twitch here lately but sometimes I will pop up and stream for a bit. Feel free to stop by and watch if I’m streaming.

Subreddit

I’ve opened a subreddit for the game as per someones suggestion. It’s mostly empty currently but hopefully that’ll change once I get some time to put some work into it. Here