Console: DOSBox IPs (+100) checkbox on all four game pages

The DOSBox-X preservation pods run the original DOS builds of BattleTech
4.10 / Red Planet 4.10 inside an emulator whose bridged NIC is enumerated
100 above the host pod's last octet. A new checkbox on each game page
(RP Death Race / Martian Football, BT Free For All / No Return) shifts
every siteconfig address the page uses by +100 so the same pages control
either version of the games:

- Munga game connections (port 1501) target host+100; toggling the box
  drops and reconnects any requested pods at the new address.
- Mission egg player and camera entries carry the shifted address.
- The checkbox locks while a mission is loaded/running, like the other
  mission properties.

Launcher / site-management traffic is untouched -- those services still
run on the pod host itself. Pages share a pod's MungaGame, so the most
recent page to toggle or enable wins if two pages fight over one pod.

Verified end-to-end against vPOD: netstat shows the game connection move
127.0.0.1 -> 127.0.0.101 -> 127.0.0.1 as the box is toggled, and the egg
received by vPOD carries pilot=127.0.0.101. All 103 diff tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-10 14:59:58 -05:00
co-authored by Claude Fable 5
parent d30ce8bdbe
commit 6a77fd0991
4 changed files with 129 additions and 12 deletions
+33 -5
View File
@@ -182,6 +182,8 @@ internal class BTGame : DockContent
private Timer tmrAutoTranslocate; private Timer tmrAutoTranslocate;
private CheckBox mDosBoxShift;
private string GameStatusText private string GameStatusText
{ {
set set
@@ -394,6 +396,19 @@ internal class BTGame : DockContent
return ((KeyValuePair<string, string>)cell.Value).Key; return ((KeyValuePair<string, string>)cell.Value).Key;
} }
private string MissionAddress(Pod pod)
{
return (mDosBoxShift.Checked ? DosBox.ShiftAddress(pod.IPAddress) : pod.IPAddress).ToString();
}
private void mDosBoxShift_CheckedChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
{
((Pod)item.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked;
}
}
private void NetworkScan(object sender, EventArgs e) private void NetworkScan(object sender, EventArgs e)
{ {
if (mCurrentState == BTGameState.Run && mRequestedState == BTGameState.Run && !mProcessingMissionEndStateChangeReq) if (mCurrentState == BTGameState.Run && mRequestedState == BTGameState.Run && !mProcessingMissionEndStateChangeReq)
@@ -747,14 +762,14 @@ internal class BTGame : DockContent
if (pod.HostType == HostType.GameMachineHostType) if (pod.HostType == HostType.GameMachineHostType)
{ {
string value = (string)item.Cells[mPilotColumn.Index].Value; string value = (string)item.Cells[mPilotColumn.Index].Value;
BTPlayer bTPlayer = new BTPlayer(pod.IPAddress.ToString(), value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((BTVehicle)item.Cells[mVehicleColumn.Index].Value).Key, GetStringOrKey(item.Cells[mColorColumn.Index]), GetStringOrKey(item.Cells[mPatchColumn.Index]), GetStringOrKey(item.Cells[mBadgeColumn.Index]), GetStringOrKey(item.Cells[mExperienceColumn.Index]), role, mAdvancedDamage.Checked); BTPlayer bTPlayer = new BTPlayer(MissionAddress(pod), value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((BTVehicle)item.Cells[mVehicleColumn.Index].Value).Key, GetStringOrKey(item.Cells[mColorColumn.Index]), GetStringOrKey(item.Cells[mPatchColumn.Index]), GetStringOrKey(item.Cells[mBadgeColumn.Index]), GetStringOrKey(item.Cells[mExperienceColumn.Index]), role, mAdvancedDamage.Checked);
bTMission.BattlePlayers.Add(bTPlayer); bTMission.BattlePlayers.Add(bTPlayer);
mMissionPlayers.Add(num++, bTPlayer); mMissionPlayers.Add(num++, bTPlayer);
PilotNameCache.PilotNames.Add(value); PilotNameCache.PilotNames.Add(value);
} }
else else
{ {
bTMission.Cameras.Add(new BTCamera(pod.IPAddress.ToString(), pod.HostType)); bTMission.Cameras.Add(new BTCamera(MissionAddress(pod), pod.HostType));
} }
} }
mEggFileMessages = bTMission.ToEggFileMessages(); mEggFileMessages = bTMission.ToEggFileMessages();
@@ -847,6 +862,7 @@ internal class BTGame : DockContent
private void SwitchControlsMode(bool editMode) private void SwitchControlsMode(bool editMode)
{ {
mDosBoxShift.Enabled = editMode;
mMap.Enabled = editMode; mMap.Enabled = editMode;
mWeather.Enabled = editMode; mWeather.Enabled = editMode;
mTimeOfDay.Enabled = editMode; mTimeOfDay.Enabled = editMode;
@@ -1077,6 +1093,7 @@ internal class BTGame : DockContent
{ {
if (flag.Value) if (flag.Value)
{ {
((Pod)dataGridViewRow.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked;
((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this); ((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this);
} }
else else
@@ -1299,6 +1316,7 @@ internal class BTGame : DockContent
this.mRandomWeather = new System.Windows.Forms.Button(); this.mRandomWeather = new System.Windows.Forms.Button();
this.mRandomTimeOfDay = new System.Windows.Forms.Button(); this.mRandomTimeOfDay = new System.Windows.Forms.Button();
this.mMissionLengthTextBox = new System.Windows.Forms.TextBox(); this.mMissionLengthTextBox = new System.Windows.Forms.TextBox();
this.mDosBoxShift = new System.Windows.Forms.CheckBox();
this.mPilotsGroupBox = new System.Windows.Forms.GroupBox(); this.mPilotsGroupBox = new System.Windows.Forms.GroupBox();
this.mPilotsDataGrid = new System.Windows.Forms.DataGridView(); this.mPilotsDataGrid = new System.Windows.Forms.DataGridView();
this.mEnabledColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn(); this.mEnabledColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
@@ -1327,7 +1345,7 @@ internal class BTGame : DockContent
this.mMissionPropertiesGroupBox.Location = new System.Drawing.Point(8, 8); this.mMissionPropertiesGroupBox.Location = new System.Drawing.Point(8, 8);
this.mMissionPropertiesGroupBox.Name = "mMissionPropertiesGroupBox"; this.mMissionPropertiesGroupBox.Name = "mMissionPropertiesGroupBox";
this.mMissionPropertiesGroupBox.Padding = new System.Windows.Forms.Padding(5); this.mMissionPropertiesGroupBox.Padding = new System.Windows.Forms.Padding(5);
this.mMissionPropertiesGroupBox.Size = new System.Drawing.Size(1040, 105); this.mMissionPropertiesGroupBox.Size = new System.Drawing.Size(1040, 140);
this.mMissionPropertiesGroupBox.TabIndex = 10; this.mMissionPropertiesGroupBox.TabIndex = 10;
this.mMissionPropertiesGroupBox.TabStop = false; this.mMissionPropertiesGroupBox.TabStop = false;
this.mMissionPropertiesGroupBox.Text = "Mission Properties"; this.mMissionPropertiesGroupBox.Text = "Mission Properties";
@@ -1360,17 +1378,18 @@ internal class BTGame : DockContent
this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1); this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1);
this.mMissionPropertiesTable.Controls.Add(this.mRandomTimeOfDay, 2, 2); this.mMissionPropertiesTable.Controls.Add(this.mRandomTimeOfDay, 2, 2);
this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextBox, 4, 1); this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextBox, 4, 1);
this.mMissionPropertiesTable.Controls.Add(this.mDosBoxShift, 6, 3);
this.mMissionPropertiesTable.Dock = System.Windows.Forms.DockStyle.Fill; this.mMissionPropertiesTable.Dock = System.Windows.Forms.DockStyle.Fill;
this.mMissionPropertiesTable.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns; this.mMissionPropertiesTable.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns;
this.mMissionPropertiesTable.Location = new System.Drawing.Point(5, 18); this.mMissionPropertiesTable.Location = new System.Drawing.Point(5, 18);
this.mMissionPropertiesTable.MinimumSize = new System.Drawing.Size(0, 85); this.mMissionPropertiesTable.MinimumSize = new System.Drawing.Size(0, 115);
this.mMissionPropertiesTable.Name = "mMissionPropertiesTable"; this.mMissionPropertiesTable.Name = "mMissionPropertiesTable";
this.mMissionPropertiesTable.RowCount = 4; this.mMissionPropertiesTable.RowCount = 4;
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f)); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f));
this.mMissionPropertiesTable.Size = new System.Drawing.Size(1030, 85); this.mMissionPropertiesTable.Size = new System.Drawing.Size(1030, 115);
this.mMissionPropertiesTable.TabIndex = 0; this.mMissionPropertiesTable.TabIndex = 0;
this.mIssuesLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; this.mIssuesLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
this.mIssuesLabel.AutoSize = true; this.mIssuesLabel.AutoSize = true;
@@ -1522,6 +1541,15 @@ internal class BTGame : DockContent
this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20); this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20);
this.mMissionLengthTextBox.TabIndex = 12; this.mMissionLengthTextBox.TabIndex = 12;
this.mMissionLengthTextBox.TextChanged += new System.EventHandler(mMissionLengthTextBox_TextChanged); this.mMissionLengthTextBox.TextChanged += new System.EventHandler(mMissionLengthTextBox_TextChanged);
this.mDosBoxShift.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left;
this.mDosBoxShift.AutoSize = true;
this.mDosBoxShift.Location = new System.Drawing.Point(529, 90);
this.mDosBoxShift.Name = "mDosBoxShift";
this.mDosBoxShift.Size = new System.Drawing.Size(122, 17);
this.mDosBoxShift.TabIndex = 13;
this.mDosBoxShift.Text = "DOSBox IPs (+100)";
this.mDosBoxShift.UseVisualStyleBackColor = true;
this.mDosBoxShift.CheckedChanged += new System.EventHandler(mDosBoxShift_CheckedChanged);
this.mPilotsGroupBox.Controls.Add(this.mPilotsDataGrid); this.mPilotsGroupBox.Controls.Add(this.mPilotsDataGrid);
this.mPilotsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; this.mPilotsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113); this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113);
+34 -6
View File
@@ -176,6 +176,8 @@ public class RPGame : DockContent
private Timer tmrAutoTranslocate; private Timer tmrAutoTranslocate;
private CheckBox mDosBoxShift;
private string GameStatusText private string GameStatusText
{ {
set set
@@ -421,6 +423,19 @@ public class RPGame : DockContent
return ((KeyValuePair<string, string>)cell.Value).Key; return ((KeyValuePair<string, string>)cell.Value).Key;
} }
private string MissionAddress(Pod pod)
{
return (mDosBoxShift.Checked ? DosBox.ShiftAddress(pod.IPAddress) : pod.IPAddress).ToString();
}
private void mDosBoxShift_CheckedChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
{
((Pod)item.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked;
}
}
private void NetworkScan(object sender, EventArgs e) private void NetworkScan(object sender, EventArgs e)
{ {
if (mCurrentState == RPGameState.Run && mRequestedState == RPGameState.Run && !mProcessingMissionEndStateChangeReq) if (mCurrentState == RPGameState.Run && mRequestedState == RPGameState.Run && !mProcessingMissionEndStateChangeReq)
@@ -791,7 +806,7 @@ public class RPGame : DockContent
{ {
RPTeam rPTeam = ((item.Cells[mColorColumn.Index].Value is RPTeam) ? ((RPTeam)item.Cells[mColorColumn.Index].Value) : RPConfig.Football.Teams[(string)item.Cells[mColorColumn.Index].Value]); RPTeam rPTeam = ((item.Cells[mColorColumn.Index].Value is RPTeam) ? ((RPTeam)item.Cells[mColorColumn.Index].Value) : RPConfig.Football.Teams[(string)item.Cells[mColorColumn.Index].Value]);
string stringOrKey = GetStringOrKey(item.Cells[mBadgeColumn.Index]); string stringOrKey = GetStringOrKey(item.Cells[mBadgeColumn.Index]);
RPFootballPlayer rPFootballPlayer = new RPFootballPlayer(pod.IPAddress.ToString(), value = (string)item.Cells[mPilotColumn.Index].Value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((RPVehicle)item.Cells[mVehicleColumn.Index].Value).Key, rPTeam.Key, stringOrKey, (stringOrKey == "runner") ? rPTeam.RunnerColor : rPTeam.TeamColor); RPFootballPlayer rPFootballPlayer = new RPFootballPlayer(MissionAddress(pod), value = (string)item.Cells[mPilotColumn.Index].Value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((RPVehicle)item.Cells[mVehicleColumn.Index].Value).Key, rPTeam.Key, stringOrKey, (stringOrKey == "runner") ? rPTeam.RunnerColor : rPTeam.TeamColor);
if (!dictionary.ContainsKey(rPFootballPlayer.TeamKey)) if (!dictionary.ContainsKey(rPFootballPlayer.TeamKey))
{ {
dictionary[rPFootballPlayer.TeamKey] = new List<RPFootballPlayer>(); dictionary[rPFootballPlayer.TeamKey] = new List<RPFootballPlayer>();
@@ -800,7 +815,7 @@ public class RPGame : DockContent
} }
else else
{ {
RPRacePlayer rPRacePlayer = new RPRacePlayer(pod.IPAddress.ToString(), value = (string)item.Cells[mPilotColumn.Index].Value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((RPVehicle)item.Cells[mVehicleColumn.Index].Value).Key, GetStringOrKey(item.Cells[mColorColumn.Index]), GetStringOrKey(item.Cells[mBadgeColumn.Index])); RPRacePlayer rPRacePlayer = new RPRacePlayer(MissionAddress(pod), value = (string)item.Cells[mPilotColumn.Index].Value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((RPVehicle)item.Cells[mVehicleColumn.Index].Value).Key, GetStringOrKey(item.Cells[mColorColumn.Index]), GetStringOrKey(item.Cells[mBadgeColumn.Index]));
((RPRaceMission)rPMission).RacePlayers.Add(rPRacePlayer); ((RPRaceMission)rPMission).RacePlayers.Add(rPRacePlayer);
mMissionPlayers.Add(num++, rPRacePlayer); mMissionPlayers.Add(num++, rPRacePlayer);
} }
@@ -808,7 +823,7 @@ public class RPGame : DockContent
} }
else else
{ {
rPMission.Cameras.Add(new RPCamera(pod.IPAddress.ToString(), pod.HostType)); rPMission.Cameras.Add(new RPCamera(MissionAddress(pod), pod.HostType));
} }
} }
if (mFootballMode) if (mFootballMode)
@@ -907,6 +922,7 @@ public class RPGame : DockContent
private void SwitchControlsMode(bool editMode) private void SwitchControlsMode(bool editMode)
{ {
mDosBoxShift.Enabled = editMode;
ComboBox comboBox = mMap; ComboBox comboBox = mMap;
ComboBox comboBox2 = mWeather; ComboBox comboBox2 = mWeather;
ComboBox comboBox3 = mTimeOfDay; ComboBox comboBox3 = mTimeOfDay;
@@ -1187,6 +1203,7 @@ public class RPGame : DockContent
{ {
if (flag.Value) if (flag.Value)
{ {
((Pod)dataGridViewRow.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked;
((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this); ((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this);
} }
else else
@@ -1414,6 +1431,7 @@ public class RPGame : DockContent
this.mRandomWeather = new System.Windows.Forms.Button(); this.mRandomWeather = new System.Windows.Forms.Button();
this.mRandomTimeOfDay = new System.Windows.Forms.Button(); this.mRandomTimeOfDay = new System.Windows.Forms.Button();
this.mMissionLengthTextBox = new System.Windows.Forms.TextBox(); this.mMissionLengthTextBox = new System.Windows.Forms.TextBox();
this.mDosBoxShift = new System.Windows.Forms.CheckBox();
this.mPilotsGroupBox = new System.Windows.Forms.GroupBox(); this.mPilotsGroupBox = new System.Windows.Forms.GroupBox();
this.mPilotsDataGrid = new System.Windows.Forms.DataGridView(); this.mPilotsDataGrid = new System.Windows.Forms.DataGridView();
this.mEnabledColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn(); this.mEnabledColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
@@ -1440,7 +1458,7 @@ public class RPGame : DockContent
this.mMissionPropertiesGroupBox.Location = new System.Drawing.Point(8, 8); this.mMissionPropertiesGroupBox.Location = new System.Drawing.Point(8, 8);
this.mMissionPropertiesGroupBox.Name = "mMissionPropertiesGroupBox"; this.mMissionPropertiesGroupBox.Name = "mMissionPropertiesGroupBox";
this.mMissionPropertiesGroupBox.Padding = new System.Windows.Forms.Padding(5); this.mMissionPropertiesGroupBox.Padding = new System.Windows.Forms.Padding(5);
this.mMissionPropertiesGroupBox.Size = new System.Drawing.Size(1040, 105); this.mMissionPropertiesGroupBox.Size = new System.Drawing.Size(1040, 140);
this.mMissionPropertiesGroupBox.TabIndex = 10; this.mMissionPropertiesGroupBox.TabIndex = 10;
this.mMissionPropertiesGroupBox.TabStop = false; this.mMissionPropertiesGroupBox.TabStop = false;
this.mMissionPropertiesGroupBox.Text = "Mission Properties"; this.mMissionPropertiesGroupBox.Text = "Mission Properties";
@@ -1473,17 +1491,18 @@ public class RPGame : DockContent
this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1); this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1);
this.mMissionPropertiesTable.Controls.Add(this.mRandomTimeOfDay, 2, 2); this.mMissionPropertiesTable.Controls.Add(this.mRandomTimeOfDay, 2, 2);
this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextBox, 4, 1); this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextBox, 4, 1);
this.mMissionPropertiesTable.Controls.Add(this.mDosBoxShift, 6, 3);
this.mMissionPropertiesTable.Dock = System.Windows.Forms.DockStyle.Fill; this.mMissionPropertiesTable.Dock = System.Windows.Forms.DockStyle.Fill;
this.mMissionPropertiesTable.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns; this.mMissionPropertiesTable.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns;
this.mMissionPropertiesTable.Location = new System.Drawing.Point(5, 18); this.mMissionPropertiesTable.Location = new System.Drawing.Point(5, 18);
this.mMissionPropertiesTable.MinimumSize = new System.Drawing.Size(0, 85); this.mMissionPropertiesTable.MinimumSize = new System.Drawing.Size(0, 115);
this.mMissionPropertiesTable.Name = "mMissionPropertiesTable"; this.mMissionPropertiesTable.Name = "mMissionPropertiesTable";
this.mMissionPropertiesTable.RowCount = 4; this.mMissionPropertiesTable.RowCount = 4;
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f)); this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f));
this.mMissionPropertiesTable.Size = new System.Drawing.Size(1030, 85); this.mMissionPropertiesTable.Size = new System.Drawing.Size(1030, 115);
this.mMissionPropertiesTable.TabIndex = 0; this.mMissionPropertiesTable.TabIndex = 0;
this.mIssuesLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; this.mIssuesLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
this.mIssuesLabel.AutoSize = true; this.mIssuesLabel.AutoSize = true;
@@ -1633,6 +1652,15 @@ public class RPGame : DockContent
this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20); this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20);
this.mMissionLengthTextBox.TabIndex = 12; this.mMissionLengthTextBox.TabIndex = 12;
this.mMissionLengthTextBox.TextChanged += new System.EventHandler(mMissionLengthTextBox_TextChanged); this.mMissionLengthTextBox.TextChanged += new System.EventHandler(mMissionLengthTextBox_TextChanged);
this.mDosBoxShift.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left;
this.mDosBoxShift.AutoSize = true;
this.mDosBoxShift.Location = new System.Drawing.Point(529, 90);
this.mDosBoxShift.Name = "mDosBoxShift";
this.mDosBoxShift.Size = new System.Drawing.Size(122, 17);
this.mDosBoxShift.TabIndex = 13;
this.mDosBoxShift.Text = "DOSBox IPs (+100)";
this.mDosBoxShift.UseVisualStyleBackColor = true;
this.mDosBoxShift.CheckedChanged += new System.EventHandler(mDosBoxShift_CheckedChanged);
this.mPilotsGroupBox.Controls.Add(this.mPilotsDataGrid); this.mPilotsGroupBox.Controls.Add(this.mPilotsDataGrid);
this.mPilotsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; this.mPilotsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113); this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113);
+28
View File
@@ -0,0 +1,28 @@
using System.Net;
namespace TeslaConsole;
/// <summary>
/// Support for the DOSBox-X preservation pods. The emulator that runs the
/// original DOS build of a game is bridged onto the pod network with its last
/// octet enumerated 100 above the host pod's address, so when a game page is
/// driving the emulated version it must target host+100 instead of the
/// address stored in the site config. Only the game traffic shifts — the
/// launcher and provisioning services still run on the host itself.
/// </summary>
internal static class DosBox
{
public const int AddressOffset = 100;
/// <summary>
/// Returns the address with its last octet raised by <see cref="AddressOffset"/>.
/// The octet wraps modulo 256; real site configs keep host octets at or
/// below 155 so the shifted address stays inside the subnet.
/// </summary>
public static IPAddress ShiftAddress(IPAddress address)
{
byte[] bytes = address.GetAddressBytes();
bytes[bytes.Length - 1] = (byte)(bytes[bytes.Length - 1] + AddressOffset);
return new IPAddress(bytes);
}
}
+34 -1
View File
@@ -32,6 +32,8 @@ public class MungaGame
private MungaConnectionState mState; private MungaConnectionState mState;
private bool mDosBoxAddressShift;
private readonly List<object> mRequestors = new List<object>(); private readonly List<object> mRequestors = new List<object>();
private Form mOwner; private Form mOwner;
@@ -109,6 +111,37 @@ public class MungaGame
} }
} }
/// <summary>
/// When set, the game connection targets the pod's DOSBox-X guest
/// (last octet +100) instead of the pod itself. Changing the value while
/// connected drops the connection; it reconnects at the new address as
/// long as the game is still requested.
/// </summary>
internal bool DosBoxAddressShift
{
get
{
lock (mInternalLock)
{
return mDosBoxAddressShift;
}
}
set
{
lock (mInternalLock)
{
if (mDosBoxAddressShift != value)
{
mDosBoxAddressShift = value;
if (mState != MungaConnectionState.Disconnected)
{
Disconnect();
}
}
}
}
}
public bool IsOwned public bool IsOwned
{ {
get get
@@ -262,7 +295,7 @@ public class MungaGame
State = MungaConnectionState.Connecting; State = MungaConnectionState.Connecting;
ShutdownSocket(); ShutdownSocket();
mSocket = new MungaSocket(); mSocket = new MungaSocket();
mSocket.BeginConnect(mPod.IPAddress, 1501, delegate(IAsyncResult ar) mSocket.BeginConnect(mDosBoxAddressShift ? DosBox.ShiftAddress(mPod.IPAddress) : mPod.IPAddress, 1501, delegate(IAsyncResult ar)
{ {
lock (mInternalLock) lock (mInternalLock)
{ {