Week 2: Linked Together


I was a little bogged down with other stuff this week.

That and the stuff I'm about to start working on is thoroughly intimidating.

- [Hyperlink Blocked] -

A key layer of the gameplay is the ability to "link" to files as opposed to instantly collecting them when you click on them. The idea behind this is it gives incentive for returning to the surface regularly (Which at this point is super easy, but I want to make much more difficult of a decision), as well as giving something for the player to lose when they overheat. For level 1 players (players who can only barely explore the file systems and click on files) hyperlinking is something they don't really have to worry about, but will accidentally succeed at occasionally, but for level 2+ players will be something that can be strategically managed to collect the most resources before making the time consuming journey back to the top level from the depths.

I wanted to make a fun way of showing how many files you currently have linked so that you can make informed decisions about your risk. and the clear way was to turn the "linking" of files into actual links in a chain (Because digital technology loves to imitate life), The chain links between the files icons are done in the malware pixel art as a way to show that while the file icons in the file system use the system art style, its actually the malware code that's moving the files. I could have accomplished this very easily by doing just a line and putting the link sprites and icon sprites at regular points along the line, but I wanted to do something more dynamic. I did a bunch of really annoying vector math to work out how to get the links to zig-zag along a line and be able to smoothly join and turn around arbitrary points.

While the math was a pain to figure out the end result works quite well, and would lend itself nicely to some sort of animation that pulls in the chain later on in the polishing phase.

- All netcode is bad netcode -

And I am trying my best not to write bad netcode. The major challenge with the multiplayer features of the game is mostly self imposed limitations. I have found a server hosting service (Render) that has a hobby tier that is quite generous and works well for the websocket implementations I am trying to put together. It has some limits though, and the limits are per month. Going over the server limits would just stop the server from functioning until the end of the month (so I'm not at any financial risk or anything). But that gives me a challenge to make code that stays under the data limits of the server for as long as possible (even though its insanely unlikely enough people will ever play the game to come close, the limit is like 100Gb per month). I also just have a thirst for writing code that is as efficient as possible, which quickly evolves into an obsession when faced with a challenge like this.

The core necessity of the net code is to keep the game state synced between players. This game state is very stilted since I'm not doing any real time updates, and instead doing updates in chunks to save on data. The game state consists of files in the file system and their states. Simple files like value files have just two states: collected, and not collected. If a value file is connected its value is added to the global point total. Data files have a bit more complicated state: They can be untouched, someone could have collected their initial value but did not succeed in hyperlinking them to the surface, or they can be completely collected. All of these states have a different impact on the current remaining game time. So any netcode would have to communicate the changes in states for these.

One clever idea I had proposed was to represent every interactable in the game with a number of bits equivalent to its highest possible number of states, and then share the entire game state at once. Since every player will generate the exact same level given the exact same seed all it would take is going down a long list of every interactable, calculating how many bits would be required to represent its maximum state and then extracting that number from the data sent over the net. This would be efficient in some scenarios, but I decided against its use for now, if I had the time I would probably add this as an option that could be generated when a player joins late, and the data sent in the form of deltas would be more bits than just syncing the entire game. The other issue is that this method doesn't scale well, and since I don't know how large the game will ultimately be, I'm not sure how many bits I'm going to need. That means I want to use a dynamically scaled delta update method. That means every message specifies different files and only tells how their states have changed. This does mean that every player needs the full history of messages, so every message has an ID that tells the player that receives it its order, so they know if they are missing one.

The final delta method works by specifying a depth, then a node at that depth, then inside that node it is one bit for every file in that node with a 1 if the file was changed, then only the required state information for the files that are changed.

- Time to work out the communication -

I already have the major encoding and decoding for the net information worked out, but I still need to actually create the script that the host, client, and the proxy server have to run. The important thing for that is what the actual messages will look like. Here is a diagram of how I'm working out what needs to be sent for each interaction.

The main thing is that the proxy server should be able to keep a record of every message sent, where data only needs to be sent to the host when something changes with the game.

I really want to try to use Go lang for the proxy server, but I'm not sure how difficult that will end up being

- Thadwick