Console: internet-session roster from TeslaLobby; vPOD per-address bind
The eight internet pod rows are furniture the operator builds once in Manage Site — the slot-to-IP map is frozen — but which of those slots a human actually claimed changes every session. New SessionRoster reads the roster TeslaLobby writes at the state=launching flip, and both game panes grow a session strip above Mission Properties: a banner (session key, game, slots claimed, waiting, written-at), Apply Session, and the Reset Pods that until now existed only as a right-click on a Go button that is disabled exactly when the reset is wanted. Two properties shape all of it. Only claimed slots appear in the file, so absence is the unclaimed signal and every failure path — truncated, stale, unreadable, refused — degrades to "no roster", which is byte-for-byte today's arcade behaviour; museums run this software and a bad JSON file must never stop a mission that would otherwise run by hand. And enabled implies claimed, not the reverse: the operator may always sit a pilot out, never add one, because an enabled row nobody claimed puts a dead IP in the egg and the pods then wait on a peer that will never boot. Roster issues join the pane's existing issue text, so the Go button is still the gate. The roster is one file per launch generation and deliberately not a live view: pod peer tables are boot-static, so a player whose lobby crashed is still in every pod's table and still playable, and live tracking would evict that working pod mid-session. Poll runs at ~1Hz off the existing network timer with its own deadline, and the strips are built at runtime — InitializeComponent is decompiled 1995 designer output that the differential tests compare literally. Go/Load also re-checks CheckAllValues at the click instead of trusting the last status tick: a pod that died in that gap went straight into the mission, and the post-Load barrier in NetworkScan then waited forever for a WaitingForLaunch that never arrives. vPOD gains -bind <ip>. Both listeners defaulted to IPAddress.Any, so a second vPOD on the machine lost the port and the console could only ever see one fake pod; binding each instance to its own address runs a whole eight-pod session side by side with no cockpits. Bind all of them or none — Windows lets IPAddress.Any take a port that specific addresses already hold, and the unbound instance then answers for every slot nobody claimed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-2
@@ -28,6 +28,7 @@ internal sealed class MungaPodServer
|
||||
}
|
||||
|
||||
private readonly int mPort;
|
||||
private readonly IPAddress mBind; // null = every interface (the default)
|
||||
private TcpListener mListener;
|
||||
private Thread mAcceptThread;
|
||||
private volatile bool mRunning;
|
||||
@@ -54,8 +55,16 @@ internal sealed class MungaPodServer
|
||||
}
|
||||
|
||||
public MungaPodServer(int port)
|
||||
: this(port, null)
|
||||
{
|
||||
}
|
||||
|
||||
// bind == null keeps the historical every-interface behaviour, so existing
|
||||
// callers and single-pod runs are unchanged.
|
||||
public MungaPodServer(int port, IPAddress bind)
|
||||
{
|
||||
mPort = port;
|
||||
mBind = bind;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@@ -64,12 +73,14 @@ internal sealed class MungaPodServer
|
||||
{
|
||||
return;
|
||||
}
|
||||
mListener = new TcpListener(IPAddress.Any, mPort);
|
||||
mListener = new TcpListener(mBind ?? IPAddress.Any, mPort);
|
||||
mListener.Start();
|
||||
mRunning = true;
|
||||
mAcceptThread = new Thread(AcceptLoop) { IsBackground = true, Name = "vPOD-accept" };
|
||||
mAcceptThread.Start();
|
||||
Log?.Invoke($"Listening on TCP {mPort} (all interfaces).");
|
||||
Log?.Invoke(mBind == null
|
||||
? $"Listening on TCP {mPort} (all interfaces)."
|
||||
: $"Listening on TCP {mPort} ({mBind} only).");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
|
||||
Reference in New Issue
Block a user