Nov - Diagnostics, Website & Notifications

I talk about getting the main website, and a diagnostic server online. I also talk about context menus, global context, files, and file systems in the OS.

Note: This months post is still being worked on, make sure to check back at the end of the month for to see the additions!

Nov 1st - Build Server Part 2


I’ve spent the past day reconfiguring the build system. I’ve set it up to where release builds insert the commit hash that was used to trigger the build. In my previous games, I would just hardcode the version number as a constant. Then whenever a new release build happened, I would manually increase the build number. I used that same system for this game, but I always knew there are alternative ways, some which might be better.

This means I’ll be eventually able to phase out patch versioning - which I’ve planned to be Major[.]Minor[.]Patch[.]Sub Patch

The ideas is, I could just do Major[.]Minor/BuildNumber

Something like 0.1/d7e3a323

Nov 2nd - Diagnostics Server


I’ve been working on various non-game specific things, prepping for the game to go public - and one of them has been analytics. After my build server died, I rebuilt it. And I’ve been working on implementing automation to help alert the community of an update or change. For example, I could have all of my commit messages be shared publicly. Users would that be able to see what changes I’m working on, before I even announce them. But then I had an idea - what about alerting myself.

This is when I had the idea to automatically upload the stack trace. - When my game encounters an error, or an unexpected state. It will do what’s called “Throwing a stack trace”. This essentially means it prints information, made for me, so I can understand what happened - hopefully. That’s the idea at least.

So this lead me to try working on a small website API, that allows my game to upload the stack traces automatically.

This ties into my build system, because now I have the ability, in code, to reference the exact commit that was used to build the binary. This is useful, because now my diagnostic error report contains the exact commit that reported it. This will help me track down where the bug was introduced.

Instead of just referencing Sometime in version 0.6.0.1. I can now reference which build of 0.6.0.1 broke it. Rather than manually rolling the version number, every single time.

This also means I can probably drop the entire patch concept, and just have version 2.1, 2.0, etc.

Or even version 1, 2, 3. And reference the first 6 characters of the build identifier.

I’m going to keep diagnostic analytics entirely optional, so users can turn it off. But this data is useful for figuring out what updates broke what, so I encourage keeping it on. It’s entirely anonymous, not even your IP is considered when aggregated into the database. But I respect user privacy. So I do my best to walk that middle ground where I can figure out what broke - while respect everyone’s privacy towards that.

chrome_5youpGfjKM

Nov 4th - MySQL


I’ve moved the entire dashboard over to MySQL. I experimented with having the web server and discord bot in the same process, I decided against it for the sake of simplicity. Keeping things simple in this early stage is crucial.

With that in mind, the MySQL transfer was a pain. Originally the dashboard was on SQLite, which worked well until I realized the process has to run mutliple instances, and that is something SQLite does not support.

So I started the move to converting the database over to DuckDB, then after a few hours of tinkering, I decided to move everything over to MySQL, since I’m more familiar with that. Long term maintenance will be much easier this way.

This dashboard is basically everything I need for error logging. Compact in a way where I don’t get excess information, instead I only get exactly what I need. So the database won’t grow out of control. I hash everything I can, and deduplicate instances. First seen and last seen - combined with an hourly counter allows the system to get fairly accurate tracking, while using minimal storage.

20251108032725

Nov 5th - Minimalization


I was in the middle of extending the metrics to include user session data. (Essentially, how long some one uses the app for, and what point they exit on) - When I realized I don’t actually need, or want that. I was just doing it for the sake of extending the capabilities of the system I was designing. I went into this with a clear goal, and decided to see if I could improve it. Without thinking if my improvements actually took away from what I created originally.

After some thought, I realized I would be better off removing the diagnostic analytics, so that’s what I did. I’ve decided to minimize the amount of diagnostic data to only be error specific. Basically, all I really want is to know where the game broke, so I can fix it.

The diagnostic errors have performance metrics that get sent, FPS, Memory Usage & Thread Count. This helps me judge any memory leaks, look at frame rate impact, and see if any threads are running out of control.

I’ve also minimized the amount of errors to be one unique error per game run. So if the game counters 100 of the same error, it will only report this to us once. If you reboot the game, the list clears, as it’s in memory, and the same error will then send back to us.

This means, critical errors where you encounter a crash, then restart, encounter a crash - will always spam the dashboard. Which means I will know what to fix next, as it would be very apparent it’s an urgent issue.

20251108032602

Nov 6th - Deployment


I am going to deploy the dashboard today. I’ve been developing it offline hosting it locally in the test environment and it looks ready. I’ve capped the offline error logs to be 10, and I don’t bother trying to prune them or anything. Most error logs are between 1kb to 10kb on the high end, so it shouldn’t impact anyone with this limit. As always you can turn off diagnostic data in the settings - but these errors do help me catch issues. It also helps me judge frequency which helps speed up the priority of these specific issues being fixed.

This also leads me into naming, I’ve decided I’m going to use the STG name as mine. I don’t have a name for this project yet, I’ll probably come up with that in the new year. I’m busy enough right now with practical code and other design choices for a long term platform. My goal for this has always been something more than just the base game. I want a platform people can extend and write their own mods, games, tools, stories, etc. I just want to provide the platform.

20251108033217

Nov 7th - Dev Logs & Diagnostics Online


I spent yesterday editing the past years worth of blog posts. I decided to merge them into monthly posts, which makes reading, and editing them much easier. I removed a large majority of technical only discussions, and anything related to the storylines I was working on. Instead, I want this to be more of a general discussion about my design choices from a higher level. December, January and April are missing, I need to track down where I put my notes for those months. I’ll probably do that one day, but no promises.

I plan to release the more technical documents eventually, I just want to package it in a format that isn’t mixing my personal thoughts with documents I want to share in a technical sense. There are a lot of things I’m proud of, and choices I’ve made that I’d like to share my understanding and reasoning for.

I’ve decided to skip the Internal Launcher. Keeping up with the effort of minimizing my website building shenanigans, I’ve decided to keep it simple. As it stands right now, I can just share the binary manually, and manage with per-version builds.

In other news, I’ve got the diagnostic API linked up to the game completely now (Minus FPS Tracking, I’ll add that later) - this was a pain in the ass to get going, but it’s done. I’ve also spun up a newsletter service to help keep readers in the loop. Technically the service is online right now, so feel free to sign up to the news letter: https://stg.stealthisgame.com/newsletter - I built it myself, so please report any issues you encounter.

20251108032930

Nov 8th - Right Click Menu Interactions & Editing


This entire time, I have yet to fully design the right-click interaction API. I have a loose idea for what would work, but I haven’t had the need for it. As I’ve been able to use my host PC to interact with the OS this entire time. I’ve also been pushing it off to the side, as I have yet to be inspired with an API like I thought I would have. Most of the APIs I’ve designed, I’ve had them come to me, after several days of thinking. I’ve spent over a year on the right-click menu design, and the best I can come up with, is literally just a HashMap with extension, action name, and action lambda.

Not very intuitive, I don’t know what I was thinking. Maybe something programmable? Some Lua function that would execute, every single time you right-click on an interface, to build the list. It would be slow, obviously, but it would be expansive.

Nope. For the life of me, I just can’t think why that would be better over a simple HashMap. What functionality would the Lua do that this HashMap can’t? Realistically, we want the menu to change, depending on file extension, and state. State being (is anything selected, what application are you on, desktop vs explorer, etc).

Now, I’m not saying we don’t currently have a right-click menu:

20251108161748

Here’s the current implementation, it works well, but it lacks the dynamic expressiveness I would expect from an operating system. Mainly, being able to create new context menus on demand - depending on the situation and state.

In other news, I’ve decided to update the adblock file. Essentially it’s just one big host file. If a root domain is included, all subdomains are blocked as well. If it’s a subdomain, only that subdomain is blocked, along with any other subdomains related to it. I curate a very small adblock host list. Then I merge it with StevenBlack’s Hosts. I cannot recommend his lists enough.

Nov 9th - Context Menu Planning


Today has mostly just been integrating the right-click context menu with the rest of the OS. Right now I’m focusing on interaction between the Desktop, and the Explorer application. Right now I’ve got state sharing properly between the two. There is no file extension specific actions, I want to add some support for loading from Lua. But for now I’ve just been hardcoding everything, getting it setup. Then I can add expansions to it later on.

One of the things I’ve added are icons to the context menu actions. The context menu is static currently, but I want it to be loaded via Lua eventually.

20251110235422 Some assets used are not created by me, and will not be in the final game, this is developer footage only

Nov 10th - Copy Files Integration


Like usual, while finishing up the context menus, I thought about how I could make them better. The way windows handles copy/paste actions, is it stores the data in the clipboard. So any application, if given the support, can freely detect the clipboard data, and then use those paths.

I figured I could simply integrate the cut, copy, and paste actions for the context menu to use the same concept. I was in the middle of writing it, when I had the thought - maybe I shouldn’t.

My argument against it, is essentially. I don’t think enough people realistically even know about that feature. And if they did, I don’t think they would assume it would be integrated like that. The thought - I assume, is that this OS should be it’s own isolated thing. Simple text data could transfer over, complex copy/paste data shouldn’t be shared - direct images, files, etc. I don’t want to over complicate, an already complicated project.

My argument for it, is integration. It should work this way, in my opinion. And I would like to add some kind of global switch. I almost wrote that in when I was finishing the API. But I decided to keep everything isolated. If you want this feature, just let me know and I’ll gladly add it back in as an opt-in toggle.

Here’s an example of the API I’ve made:

setFilesToClipboard(file[], COPY); // CUT to move files instead of copy
getFilesFromClipboard(); // Returns file[]
doesClipboardContainFiles(); // Used to control 'Paste' being active

My idea is I could integrate this API with the Lua os library. Or maybe create some kind of IPC calls for it. For now it’s an internal API.

Nov 12th - File System Talk


I’ve been working on the command line API today. I’m finally putting the parts of the internal OS into visual components for users to edit. So I’ve been making some changes to how the API works behind the scenes. Early in on the project, I only allowed 3 specific directories to be accessible by users:

  • /packs
  • /themes
  • /wallpapers

Then all of the resources would be relative to whatever your installed packs are.

In my OS, the root / directory is the root directory for multiple folders. This makes sense from the host OS perspective. When I’m editing D:/game/resources/packs/default/scripts/text/dialogue/demo.lua my OS will see it as /scripts/text/dialogue/demo.lua. So you can have multiple packs installed, and the relative directory will stay absolute. Collisions happen but that is part of the power, packs can be stacked in a specific order to allow file overriding without limitation for packs. So one pack released, could be maintained and updated by another pack.

The same concept works for wallpapers and themes, but it’s slightly more locked down. You can have an unlimited amount of backup themes, and a main theme. You can only have one wallpaper active at once though. There is no limit for packs, since I made them by design to help encourage modding.

Of course, this means anything added into the root directory of a pack, now becomes part of the root directory of the OS. This leads to cluttering of the root directory, since themes also effect this root directory. Unique naming for root files is critical. Collisions must be on purpose, so the root name has to be unique enough to help prevent this. Not a major issue but something to keep in mind during development.

Today I’ve introduced the concept of system files. These are files in the root resources directory that are not part of the 3 previously approved folders. Any files in here are essentially ignored by my OS. These are not accessible by any user provided APIs. Normally. I added a new flag in the constants file called CAN_ACCESS_SYSTEM_FILES. Right now it’s disabled, but my plan is to introduce something in the future. As a user you would be able to type ‘something’ into the command line. and it would give you system file access. Right now there are a handful of files that are inaccessible. As I’ve tried to make literally everything moddable. So this restriction might be removed for retail.

This leads me to a bug I fixed earlier today. The user registry value for theme.backups was causing the directory to fill with incorrect information for the root directory. I assume it was trying to read the /themes/* folder instead of /themes/[name] as [name] was blank. Here’s an example of how the root directory comes together for all of the various files and folders, when it’s not broken. I’ve got some testing data in there, so expect this to be cleaned up for release.

20251112201922 Some assets used are not created by me, and will not be in the final game, this is developer footage only

Nov 13th - Keybinds


The idea is players should be able to freely map multiple keys to any specific action. Theres no real reason it should have a limit, so the design should support multiple input forms, and a singular check. Obviously certain things need specific support, triggers and joysticks have a float value for example. Buttons are just toggles with timers between press and release. But once you’ve unified everything, it’s easy to use.

//button controller values
put("os.controls.start-menu", "KEYBOARD_F1");
put("os.controls.fullscreen-toggle", "KEYBOARD_F11");

The registry in my OS is just one big hash map, so this is how I’m handling OS remappable controls for now. The idea is I can have multiple input sources:

put("os.controls.fullscreen-toggle", "KEYBOARD_F11,MOUSE_UP");

So any time the mouse was pressed, or F11 - the fullscreen-toggle action will be polled.

Nov 14th - Thoughts On The OS


Name - System 64


I thought of a new name last night. I think I like it, but that’s what happens with every single internal name I’ve given the operating system itself - OS 64, or System 64. I think the name reflects where the project is for me right now. It can go in any direction, but I have a clear, focused goal. I want there to be mystery on the surface - but I want the concept to be infinitely digestible and easy to understand. The pitch for the game is a Horror story take takes place inside of an operating system. I think that’s easy enough to understand for most.

Start Menu Key Toggle


I tried for a couple hours to get the Windows key to be overridable - so instead of the start menu popping up on the host OS, the in-game start menu would pop up instead. This worked, kind of. But it introduced a bunch of bugs, that were caused due to the way I handled the low level keyboard input.

I tried a couple alternatives, and found both Python and Auto Hot Key work better. Both are solutions I could explore in the future, but I’d rather something written in C. I wasn’t able to it working to the standard I expected, so I cut the feature for now.

Side Note


I can’t get the idea of an app store out of my head. Something that connects the users in a simple yet obvious way. Originally I was going to host the data myself. But after serious consideration, I think putting the pressure on valve is the better idea. Utilizing Steam’s SDK, I can allow the Steam Workshop to be our official app store. I can curate the front page, along with a handful of selected categories. The community can vote with their activity and downloads. Then I can present the most popular with a nice search function. Easily offer a subscription button from within the app store itself. So users can install using the steam network and client. All I’d have to do is support the steam folder for overrides. Easier said than done, but I’m willing to put the work in.

I’m probably going to workshop this later this weekend if I get a chance, if not maybe some time this month. Who knows when I’ll do it, I’ve been busy with core OS changes right now, right now I’m working on popups.

Popups


Popups are something I’ve had since day 1, but since I didn’t have exclusive fullscreen mode since day 1 - my original implementation failed catastrophically when I tried to display a popup while fullscreened. (Borderless windowed worked fine) - This lead me to completely resigning how popups look, and more importantly, how they work. Not a major issue, but it’s something I’ve been meaning to solve for a minute.

20251114210222 Some assets used are not created by me, and will not be in the final game, this is developer footage only

Arrow Keys


Another thing I’ve been meaning to solve for a while, (in this case, since I started the project) - is arrow keys. Arrow keys for navigation is a very basic and well known concept in UX. It dates back to before the mouse. Arrow keys were the original way of navigating a computer - back when it was a text-only terminal. Because computers mean backwards compatibility first - every single computer has a way to use it without a mouse. At least, they used to. I grew up knowing how to loosely navigate a computer, with just the keyboard. I can do it today, but there is a lot you cannot do anymore. But it’s still inherently possible. Which means I should support it, as part of my philosophy "if without thinking, you try it, and you cannot do it, the action should be supported if possible." This loosely translates to "add the missing stuff, guy." as the things that are missing to whoever notices them - is always glaringly obviously.

Some assets used are not created by me, and will not be in the final game, this is developer footage only

Notifications


Notifications are again, something I’ve had a plan for since day 1. I purposefully avoided them until later, for two reasons.

  1. I want to have a driving force for most updates, not just want, but a need. Either from a technical problem I need to solve, or a logical one. The logical problem notifications solve, is in-game alerts.

  2. Achievements - I wanted to wait until I was ready to implement the achievements API, as the achievement system and notification system are essentially going to be the same thing. Notifications is where your alerts for achievements go, it’s how they are displayed, it’s a big thing. I wanted the OS to be in it’s best state possible, where I had all of the bells and whistles ready, or in the works.

Achievements are pretty close, whipping up a quick API would be easy. But I’ve ran into the realistic need right now that there are a handful of places I could have used notifications, and it’s loosely piling up.

My idea for notifications are pretty clear, it should be something the player has relative information for, or it should be related to the story in some way. I don’t want notifications to be used to teach, as information overload would cause the notification center to be a source of pain. Learning sucks. I want this place to feel rewarding - training your brain with dopamine that this place is safe. Then I want to slowly introduce the story, and things will go from there.

Story Mode


I’ve decided I need to go down the Minecraft route. I have to have a creative mode. There is no other way to put it, the game is a great sandbox as it sits, and forcing players to go through a story, just to experience that in the end is a waste. I think if someone wants to go into testing user made mods / programs, they should be allowed to. This means I’m going to create a dialogue at the start of the setup wizard, and it will literally ask you what you want to do. Still figuring out how I’ll do that without breaking the 4th wall, as I want the game to be “played” from the second the exe has been clicked on.

Nov 15th - Saving


I figured I’ll talk a bit about the save system and how it works. Originally I wrote this system a couple years ago, it was meant to be part of a configuration language I was designing. It was neat but not really useful, so I slapped a serializer on top of it, and it was the back bone for my save system. After some polishing, here is the things it can do:

  1. Doesn’t save if it doesn’t need to. If the data has not been changed from the initial state, or load state - there is no need to write anything to the file system, risking corruption of the game save.

  2. Detect corrupt states by including a verify check at the start of the file, and at the bottom

    • If corruption is detected, it will take the current save, rename it to <timestamp>.corrupt, if this ever happens just email me the corrupted save and I’ll send you back a working one. (Or feel free to edit it yourself!)
  3. Easy to edit with a plain-text format to help encourage user modding. No save editor is needed here, just open it with Notepad on your computer. By default types are introduced, but there is also a fallback mode for those who want to write it more relaxed:

    • age=4000
      name=Bob
      pi=3.14
      more_pi=3.1415
      hungry=true
      
  4. Built-in type support, both the serialized save format and the API have strict type control to ensure you can define data exactly how you want it.

    • I:age=4000
      S:name=Bob
      F:pi=3.14
      D:more_pi=3.1415
      B:hungry=true
      
  5. The Lua backend can interact with the registry system through the OS IPC.

    • os.execute("ipc registry user setstr name Bob") -- set name
      results = os.execute("ipc registry user getstr name") -- get name
      
    • You can also use IPC commands directly from the terminal if you wanted.
  6. You can edit everything in-game using my version of regedit. I consider this the registry - there are actually 5 registries total in my OS - and the registry editor can edit every single one of them. 20251115111119 Some assets used are not created by me, and will not be in the final game, this is developer footage only

Nov 17th - Website


I’ve finally soft-launched the website at https://stealthisgame.com - the domain is temporary, until I finalize the name I figure I’ll just use this for now.

I have been doing a lot of changes towards getting the website online. This includes: + Editing the dev log, formatting for the website generator, and gathering images and videos. + Adjusted the auto build script to build & publish the website on demand. + Finalizing the theme, I decided to go with hugo-blog-awesome.

The editing has taken the longest time. I’ve decided to scrap whenever I wrote about the story, as I don’t want to spoil anything. I’d like the story to be experienced from entirely entirely the game, if possible.

Nov 18th - Dev Logs Online

I’ve published the Dev Logs online. I’ve done my best to edit them and make them presentable. I’m going to continue writing as part of the process for making this game.

Nov 20th - Directory Command Sorting

Something I did without realizing it was different from Windows - is I sorted the dir / ls command to be folder first, then alphabetical:

My dir sort:

11/17/2025    02:38 PM    <DIR>          .
09/14/2025    03:19 PM    <DIR>          ..
11/09/2025    03:47 PM    <DIR>          New Folder
11/09/2025    09:24 AM    <DIR>          New Folder - Copy (1)
11/09/2025    05:38 AM    <DIR>          New Folder - Copy (1) - Copy (1)
11/09/2025    08:16 AM    <DIR>          New Folder - Copy (2)
10/15/2025    11:23 AM    <DIR>          test
02/14/2024    10:03 AM            34,012 4.wav
09/18/2025    04:27 PM         4,397,314 LARGE_TEXT_EXAMPLE.txt
11/09/2025    08:39 AM                 0 New File.lua
02/25/2022    01:32 PM           289,145 bananas.bo
09/22/2025    03:30 AM            10,742 gui-lib.lua
09/30/2025    10:43 PM            13,257 gui.lua
09/30/2025    10:42 PM            12,572 mig-layout.lua
09/18/2025    09:57 PM             7,990 test.lua
10/14/2025    02:23 PM             4,431 test_cmd.lua
09/29/2025    05:25 AM             1,650 webgl-demo.html

On windows, the order would be alphabetical sort only - but intuitively, almost without thinking - I set mine to be folder first, then sort by alphabetical.

Window’s dir sort:

11/17/2025  02:38 PM    <DIR>          .
09/14/2025  02:19 PM    <DIR>          ..
02/14/2024  10:03 AM            34,012 4.wav
02/25/2022  01:32 PM           289,145 bananas.bo
09/22/2025  02:30 AM            10,742 gui-lib.lua
09/30/2025  09:43 PM            13,257 gui.lua
09/18/2025  03:27 PM         4,397,314 LARGE_TEXT_EXAMPLE.txt
09/30/2025  09:42 PM            12,572 mig-layout.lua
11/09/2025  08:39 AM                 0 New File.lua
11/09/2025  03:47 PM    <DIR>          New Folder
11/09/2025  09:24 AM    <DIR>          New Folder - Copy (1)
11/09/2025  05:38 AM    <DIR>          New Folder - Copy (1) - Copy (1)
11/09/2025  08:16 AM    <DIR>          New Folder - Copy (2)
10/15/2025  10:23 AM    <DIR>          test
09/18/2025  08:57 PM             7,990 test.lua
10/14/2025  01:23 PM             4,431 test_cmd.lua
09/29/2025  04:25 AM             1,650 webgl-demo.html

I felt the intuitive choice was to sort folders first, as that is the difference between opening a file, or viewing a directory. They are two entirely different concepts. Maybe it’s a hold-over from the original Windows DOS days. Weird. I’ll make sure to note anything else interesting like this as I come across it.

Nov 23 - Manual Editing

I’ve been working on the manuals, specifically only the modding manual - The Grimoire - it’s not published yet, so that link won’t work. But the minute it’s published, that’s where it will be.

Like usual whenever I do these kind of document level changes, I try to adjust the folder organization - mostly in an effort to clean things up. I’m pretty happy with the folder layout now, previously I had thrown together all of the dev notes, website data, and manuals in the documents folder. Now I’ve moved those 3 specific sections into the website. It feels a lot easier to navigate now - hopefully this leads to more documentation.

Popups have been going good, I’ve implemented the IPC handler for them and rigged everything up, so Lua (or the command line) can trigger popups, and then use the results to perform actions.

Pasted image 20251123193421 Some assets used are not created by me, and will not be in the final game, this is developer footage only You can then use the variable like you would any other variable in Lua:

print(result)
2