diff --git a/Console/TeslaConsole.BattleTech/BTGame.cs b/Console/TeslaConsole.BattleTech/BTGame.cs index dd26e81..26735f8 100644 --- a/Console/TeslaConsole.BattleTech/BTGame.cs +++ b/Console/TeslaConsole.BattleTech/BTGame.cs @@ -182,6 +182,8 @@ internal class BTGame : DockContent private Timer tmrAutoTranslocate; + private CheckBox mDosBoxShift; + private string GameStatusText { set @@ -394,6 +396,19 @@ internal class BTGame : DockContent return ((KeyValuePair)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) { if (mCurrentState == BTGameState.Run && mRequestedState == BTGameState.Run && !mProcessingMissionEndStateChangeReq) @@ -747,14 +762,14 @@ internal class BTGame : DockContent if (pod.HostType == HostType.GameMachineHostType) { 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); mMissionPlayers.Add(num++, bTPlayer); PilotNameCache.PilotNames.Add(value); } else { - bTMission.Cameras.Add(new BTCamera(pod.IPAddress.ToString(), pod.HostType)); + bTMission.Cameras.Add(new BTCamera(MissionAddress(pod), pod.HostType)); } } mEggFileMessages = bTMission.ToEggFileMessages(); @@ -847,6 +862,7 @@ internal class BTGame : DockContent private void SwitchControlsMode(bool editMode) { + mDosBoxShift.Enabled = editMode; mMap.Enabled = editMode; mWeather.Enabled = editMode; mTimeOfDay.Enabled = editMode; @@ -1077,6 +1093,7 @@ internal class BTGame : DockContent { if (flag.Value) { + ((Pod)dataGridViewRow.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked; ((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this); } else @@ -1299,6 +1316,7 @@ internal class BTGame : DockContent this.mRandomWeather = new System.Windows.Forms.Button(); this.mRandomTimeOfDay = new System.Windows.Forms.Button(); this.mMissionLengthTextBox = new System.Windows.Forms.TextBox(); + this.mDosBoxShift = new System.Windows.Forms.CheckBox(); this.mPilotsGroupBox = new System.Windows.Forms.GroupBox(); this.mPilotsDataGrid = new System.Windows.Forms.DataGridView(); 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.Name = "mMissionPropertiesGroupBox"; 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.TabStop = false; 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.mRandomTimeOfDay, 2, 2); 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.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns; 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.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(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.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; @@ -1522,6 +1541,15 @@ internal class BTGame : DockContent this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20); this.mMissionLengthTextBox.TabIndex = 12; 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.Dock = System.Windows.Forms.DockStyle.Fill; this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113); diff --git a/Console/TeslaConsole.RedPlanet/RPGame.cs b/Console/TeslaConsole.RedPlanet/RPGame.cs index 388eba6..f372efa 100644 --- a/Console/TeslaConsole.RedPlanet/RPGame.cs +++ b/Console/TeslaConsole.RedPlanet/RPGame.cs @@ -176,6 +176,8 @@ public class RPGame : DockContent private Timer tmrAutoTranslocate; + private CheckBox mDosBoxShift; + private string GameStatusText { set @@ -421,6 +423,19 @@ public class RPGame : DockContent return ((KeyValuePair)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) { 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]); 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)) { dictionary[rPFootballPlayer.TeamKey] = new List(); @@ -800,7 +815,7 @@ public class RPGame : DockContent } 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); mMissionPlayers.Add(num++, rPRacePlayer); } @@ -808,7 +823,7 @@ public class RPGame : DockContent } else { - rPMission.Cameras.Add(new RPCamera(pod.IPAddress.ToString(), pod.HostType)); + rPMission.Cameras.Add(new RPCamera(MissionAddress(pod), pod.HostType)); } } if (mFootballMode) @@ -907,6 +922,7 @@ public class RPGame : DockContent private void SwitchControlsMode(bool editMode) { + mDosBoxShift.Enabled = editMode; ComboBox comboBox = mMap; ComboBox comboBox2 = mWeather; ComboBox comboBox3 = mTimeOfDay; @@ -1187,6 +1203,7 @@ public class RPGame : DockContent { if (flag.Value) { + ((Pod)dataGridViewRow.Tag).MungaGame.DosBoxAddressShift = mDosBoxShift.Checked; ((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this); } else @@ -1414,6 +1431,7 @@ public class RPGame : DockContent this.mRandomWeather = new System.Windows.Forms.Button(); this.mRandomTimeOfDay = new System.Windows.Forms.Button(); this.mMissionLengthTextBox = new System.Windows.Forms.TextBox(); + this.mDosBoxShift = new System.Windows.Forms.CheckBox(); this.mPilotsGroupBox = new System.Windows.Forms.GroupBox(); this.mPilotsDataGrid = new System.Windows.Forms.DataGridView(); 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.Name = "mMissionPropertiesGroupBox"; 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.TabStop = false; 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.mRandomTimeOfDay, 2, 2); 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.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns; 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.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(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.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; @@ -1633,6 +1652,15 @@ public class RPGame : DockContent this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20); this.mMissionLengthTextBox.TabIndex = 12; 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.Dock = System.Windows.Forms.DockStyle.Fill; this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113); diff --git a/Console/TeslaConsole/DosBox.cs b/Console/TeslaConsole/DosBox.cs new file mode 100644 index 0000000..ef88310 --- /dev/null +++ b/Console/TeslaConsole/DosBox.cs @@ -0,0 +1,28 @@ +using System.Net; + +namespace TeslaConsole; + +/// +/// 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. +/// +internal static class DosBox +{ + public const int AddressOffset = 100; + + /// + /// Returns the address with its last octet raised by . + /// The octet wraps modulo 256; real site configs keep host octets at or + /// below 155 so the shifted address stays inside the subnet. + /// + public static IPAddress ShiftAddress(IPAddress address) + { + byte[] bytes = address.GetAddressBytes(); + bytes[bytes.Length - 1] = (byte)(bytes[bytes.Length - 1] + AddressOffset); + return new IPAddress(bytes); + } +} diff --git a/Console/TeslaConsole/MungaGame.cs b/Console/TeslaConsole/MungaGame.cs index ae8a1ff..014cc7b 100644 --- a/Console/TeslaConsole/MungaGame.cs +++ b/Console/TeslaConsole/MungaGame.cs @@ -32,6 +32,8 @@ public class MungaGame private MungaConnectionState mState; + private bool mDosBoxAddressShift; + private readonly List mRequestors = new List(); private Form mOwner; @@ -109,6 +111,37 @@ public class MungaGame } } + /// + /// 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. + /// + internal bool DosBoxAddressShift + { + get + { + lock (mInternalLock) + { + return mDosBoxAddressShift; + } + } + set + { + lock (mInternalLock) + { + if (mDosBoxAddressShift != value) + { + mDosBoxAddressShift = value; + if (mState != MungaConnectionState.Disconnected) + { + Disconnect(); + } + } + } + } + } + public bool IsOwned { get @@ -262,7 +295,7 @@ public class MungaGame State = MungaConnectionState.Connecting; ShutdownSocket(); 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) {