Intel Macs stop crashing to desktop, and equipment stops vanishing from racks. The Network page tells you whether each carrier line is actually up, and a multiplayer game that refuses to let you in now tells you why.
Fixed
Multiplayer
- A join that fails says what went wrong. Almost every reason ended up as "Couldn't start the simulation engine", which names the wrong part of the game and gives you nothing to do about it. There are twenty-two things that can turn a join away and only five of them used to be recognised. Now the game says the session is full, or the host has not started yet, or you are on different versions, or Steam did not confirm who you are, and so on.
- A join that never reaches the host says so too. "The host did not accept the connection", "could not find a route in time" and "Steam would not open the connection from this PC" are three different problems with three different answers, and all three used to read the same.
- Only the host can change difficulty and world hostility. In a shared game any player could change them for everyone. Guests can still see what the run is set to; the controls say the host owns them.
Mac
- Intel Macs no longer crash to desktop. The game could close without warning at any point, most often while entering a rack or laying cables, and it happened on every Intel machine.
Racks
- Equipment stops vanishing from racks. A single failed model read used to hide every machine of that type, and its cables, for the rest of the session.
- A network card you fit appears on the server. Its ports arrived but the rack never redrew, so there was nothing to plug a cable into until something else on the site happened to change.
- Patching a switch port redraws the rack too. Same cause, same fix: changing what is plugged into a machine now counts as the world changing shape.
Network
- Every carrier demarc no longer reads UNKNOWN. The Network page had no source for that column and printed the same placeholder for every line you own. It now reads online, saturated, outage or offline.
- A line going down repaints the list. The carrier list only redrew when a demarc was renamed or its capacity changed, so a failed circuit could sit there looking healthy.
- Live throughput no longer counts as the world changing shape. Every reading nudged the signal that says a server moved, so a still datacentre did placement work four times a second.
- A bonded link counts its far end through a patch panel. Bonds running through a panel read every member as dead, because the check stopped at the panel socket instead of the machine behind it.
Services
- A control plane uses the biggest machine that actually fits it. It picked the machine with the most memory even when that box had the fewest cores, then split the plane in two because that box was too small. On a fleet with hundreds of suitable servers it was splitting planes that fitted whole.
- Splitting a control plane no longer costs you its redundancy. A plane that outgrew one machine used to drop to a single copy and quietly ignore the replica count you set. Shards and replicas are now separate: two shards with three replicas is six machines, and it still survives losing one.
- The Services page names both numbers, and says when it is short. It read "sharded across two hosts" and dropped the replica count entirely. It now reads "2 shards x 3 replicas" and tells you if it could only place some of them.
Security
- A router behind another router no longer filters anything. Its firewall sits between the carrier and your network, and a second one in line never sees that boundary. You can still wire it that way; it just costs you a hop.
- The console says when a router has no carrier line. It used to show a clean threat board on a device that was doing nothing, which read as the firewall being broken.
Added
- The pause menu is a proper screen now. Nav down the left, content on the right, instead of a small stack of buttons. Escape dims the world and the menu slides in.
- Settings opens inside it rather than as a second window on top of the first.
- A Session page. Who's connected, their connection quality, what your upload is costing you, and the invite button. All in one place instead of squeezed between Save and Quit.
- You choose who can join. Friends, invite only, or closed. Changing it never removes anyone already playing; it only decides who can turn up next. Host only.
- Sandbox runs can change their world settings mid-run. Every slider from the Sandbox setup screen, available from the pause menu while you play. Campaign and scenario runs can't: the setting wouldn't survive a reload there, and a control that quietly forgets is worse than no control.
- The Security page has tabs. Overview, Defences, Exposure and Audit, instead of one long scroll you had to read past three unrelated things to get through.
- Exposure tells you who attracts the attention. Background scanning scales with the customers you take and how well known you are, and nothing anywhere said so. The new tab ranks your tenants by how much noise they draw.
- Prospects say whether they will attract trouble. Before you sign, not after. Some personas raise the background noise for the whole site, and some can be singled out for a real attack.
Notes
- Saves work in both directions with v0.1.49. Nothing about the format changed.
- Multiplayer needs everyone on v0.1.50. The customer and prospect messages carry two new fields, so a v0.1.49 player cannot join a v0.1.50 game or the reverse.
- API: `CustomerView` and `ProspectView` gain `threat_exposure_weight` and `threat_targeted`. Both additive; older clients reading neither are unaffected.
- Protocol: connection errors carry `code`, `msg_key` and `msg_args` alongside the existing `msg`, matching the shape disconnect reasons have used since v0.1.44. All three are optional and default to empty, so anything reading only `msg` is unaffected. This is what lets the client name a refusal instead of guessing at its English text.
- Protocol: the `kicked_lagging` disconnect code is gone. Falling behind stopped being a reason to drop a player some time ago; the code outlived the behaviour and nothing could send it.
- Protocol: `PlayerCommand::SetSandboxTuning { key, value }` sets one sandbox knob on a running world. Refused outside a sandbox run, and refused from anyone but the host.
- API: `WorldSnapshot` gains `hostility`, `{ follows_difficulty, value }`. The multiplier the world is actually running at, plus whether it is tracking difficulty rather than pinned. `difficulty` has always been readable; this is the other half.