Skip to content

Commit 8df034f

Browse files
authored
Show network information dialog added (#7995)
This adds a dialog under Game->Network Information which then can display the local IP, public IP, and host connection address. They are hidden by default, and require button presses to display, with each being a separate button. <img width="401" height="359" alt="NetworkInformation" src="https://github.com/user-attachments/assets/c4754c52-1893-445e-b720-4b6a65ed6b72" />
2 parents a754177 + d6c5cbb commit 8df034f

File tree

5 files changed

+256
-1
lines changed

5 files changed

+256
-1
lines changed

megamek/resources/megamek/client/messages.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ ChatLounge.name.selectUnits=Select Units
791791
ChatLounge.name.spaceMap=Space Map
792792
ChatLounge.name.teamOverview=Team Overview
793793
ChatLounge.name.unitSetup=Unit Setup
794+
ChatLounge.name.networkOverview=Network Overview
794795
ChatLounge.noCamo=No Camo
795796
ChatLounge.noCmdr.title=No Commander!
796797
ChatLounge.noCmdr.msg=Commander killed victory is selected but the following players don't have a commander:\n
@@ -1132,6 +1133,7 @@ CommonMenuBar.viewAccessibilityWindow=Accessibility Window
11321133
CommonMenuBar.viewIncGUIScale=Increase GUI Scale
11331134
CommonMenuBar.viewDecGUIScale=Decrease GUI Scale
11341135
CommonMenuBar.viewKeyboardShortcuts=Keyboard Shortcuts
1136+
CommonMenuBar.viewNetworkInformation=Network Information
11351137
CommonMenuBar.viewPlanetaryConditions=Planetary Conditions
11361138
CommonMenuBar.ViewMenu=View
11371139
CommonMenuBar.viewMinimap=Minimap
@@ -3552,6 +3554,13 @@ MissionRole.generator=Generator
35523554
MissionRole.generator.tooltip=Structure provides power for dependent buildings.
35533555
MissionRole.control=Control center
35543556
MissionRole.control.tooltip=Structure controls other structures.
3557+
#Network Information Dialog Text
3558+
NetworkInformation.localIP=Local IP Address:
3559+
NetworkInformation.remoteIP=Public IP Address:
3560+
NetworkInformation.connectedIP=Game Connected to:
3561+
NetworkInformation.buttonShowIPs=Show/Hide address
3562+
NetworkInformation.blankIP=No Address
3563+
NetworkInformation.title=Network Information
35553564
#Random Map Dialog
35563565
RandomMapDialog.ShowAtStart=<HTML><I><FONT SIZE = -2>Show at Map Editor startup
35573566
RandomMapDialog.mountainPlain=Plain

megamek/src/megamek/client/ui/clientGUI/ClientGUI.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import megamek.client.ui.dialogs.buttonDialogs.EditBotsDialog;
106106
import megamek.client.ui.dialogs.buttonDialogs.GameOptionsDialog;
107107
import megamek.client.ui.dialogs.buttonDialogs.LOSDialog;
108+
import megamek.client.ui.dialogs.buttonDialogs.NetworkInformationDialog;
108109
import megamek.client.ui.dialogs.forceDisplay.ForceDisplayDialog;
109110
import megamek.client.ui.dialogs.forceDisplay.ForceDisplayPanel;
110111
import megamek.client.ui.dialogs.helpDialogs.AbstractHelpDialog;
@@ -278,6 +279,7 @@ public class ClientGUI extends AbstractClientGUI
278279
public static final String VIEW_CHANGE_THEME = "viewChangeTheme";
279280
public static final String VIEW_ROUND_REPORT = "viewRoundReport";
280281
public static final String VIEW_GAME_OPTIONS = "viewGameOptions";
282+
public static final String VIEW_NETWORK_INFORMATION = "viewNetworkInformation";
281283
public static final String VIEW_CLIENT_SETTINGS = "viewClientSettings";
282284
public static final String VIEW_LOS_SETTING = "viewLOSSetting";
283285
public static final String VIEW_PLAYER_SETTINGS = "viewPlayerSettings";
@@ -372,6 +374,7 @@ public class ClientGUI extends AbstractClientGUI
372374

373375
// some dialogs...
374376
private GameOptionsDialog gameOptionsDialog;
377+
private NetworkInformationDialog networkInformationDialog;
375378
private MegaMekUnitSelectorDialog mekSelectorDialog;
376379
private PlayerListDialog playerListDialog;
377380
private RandomArmyDialog randomArmyDialog;
@@ -882,6 +885,14 @@ private void showOptions() {
882885
getGameOptionsDialog().setVisible(true);
883886
}
884887

888+
private void showNetworkInformation() {
889+
// Display the network information screen
890+
getNetworkInformationDialog().refresh();
891+
getNetworkInformationDialog().pack();
892+
getNetworkInformationDialog().setVisible(true);
893+
}
894+
895+
885896
public void customizePlayer() {
886897
PlayerSettingsDialog psd = new PlayerSettingsDialog(this, client, (BoardView) boardViews.get(0));
887898
psd.setVisible(true);
@@ -959,6 +970,9 @@ public void resetWindowPositions() {
959970
if (gameOptionsDialog != null) {
960971
gameOptionsDialog.setBounds(0, 0, gameOptionsDialog.getWidth(), gameOptionsDialog.getHeight());
961972
}
973+
if (networkInformationDialog != null) {
974+
networkInformationDialog.setBounds(0, 0, networkInformationDialog.getWidth(), networkInformationDialog.getHeight());
975+
}
962976
if (commonSettingsDialog != null) {
963977
commonSettingsDialog.setBounds(0, 0, commonSettingsDialog.getWidth(), commonSettingsDialog.getHeight());
964978
}
@@ -1070,6 +1084,9 @@ public void actionPerformed(ActionEvent event) {
10701084
case VIEW_GAME_OPTIONS:
10711085
showOptions();
10721086
break;
1087+
case VIEW_NETWORK_INFORMATION:
1088+
showNetworkInformation();
1089+
break;
10731090
case VIEW_PLAYER_SETTINGS:
10741091
customizePlayer();
10751092
break;
@@ -1350,6 +1367,13 @@ public GameOptionsDialog getGameOptionsDialog() {
13501367
}
13511368
return gameOptionsDialog;
13521369
}
1370+
1371+
public NetworkInformationDialog getNetworkInformationDialog() {
1372+
if (networkInformationDialog == null) {
1373+
networkInformationDialog = new NetworkInformationDialog(this);
1374+
}
1375+
return networkInformationDialog;
1376+
}
13531377

13541378
public MegaMekUnitSelectorDialog getMekSelectorDialog() {
13551379
return mekSelectorDialog;

megamek/src/megamek/client/ui/clientGUI/CommonMenuBar.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public class CommonMenuBar extends JMenuBar implements ActionListener, IPreferen
9696
private final JCheckBoxMenuItem gamePlayerList = new JCheckBoxMenuItem(getString("CommonMenuBar.viewPlayerList"));
9797
private final JMenuItem gameGameOptions = new JMenuItem(getString("CommonMenuBar.viewGameOptions"));
9898
private final JMenuItem gamePlayerSettings = new JMenuItem(getString("CommonMenuBar.viewPlayerSettings"));
99+
private final JMenuItem gameNetworkInformation = new JMenuItem(getString("CommonMenuBar.viewNetworkInformation"));
99100

100101
// The Units menu
101102
private final JMenuItem fileUnitsReinforce = new JMenuItem(getString("CommonMenuBar.fileUnitsReinforce"));
@@ -233,6 +234,7 @@ private CommonMenuBar(boolean isMainMenu, boolean isGame, boolean isBoardEditor)
233234

234235
initMenuItem(gameGameOptions, menu, VIEW_GAME_OPTIONS, VK_O);
235236
initMenuItem(gamePlayerSettings, menu, VIEW_PLAYER_SETTINGS);
237+
initMenuItem(gameNetworkInformation, menu, VIEW_NETWORK_INFORMATION);
236238
initMenuItem(fileUnitsCopy, menu, FILE_UNITS_COPY);
237239
fileUnitsCopy.setAccelerator(KeyStroke.getKeyStroke(VK_C, CTRL_DOWN_MASK));
238240
initMenuItem(fileUnitsPaste, menu, FILE_UNITS_PASTE);
@@ -538,6 +540,7 @@ private synchronized void updateEnabledStates() {
538540
viewLabels.setEnabled(isInGameBoardView);
539541

540542
gameGameOptions.setEnabled(isInGame || isLobby);
543+
gameNetworkInformation.setEnabled(isInGame || isLobby || isMainMenu);
541544
gamePlayerSettings.setEnabled(isInGame);
542545

543546
viewMinimap.setEnabled(isBoardView);

megamek/src/megamek/client/ui/clientGUI/MegaMekGUI.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import megamek.client.ui.dialogs.buttonDialogs.BotConfigDialog;
8787
import megamek.client.ui.dialogs.buttonDialogs.CommonSettingsDialog;
8888
import megamek.client.ui.dialogs.buttonDialogs.GameOptionsDialog;
89+
import megamek.client.ui.dialogs.buttonDialogs.NetworkInformationDialog;
8990
import megamek.client.ui.dialogs.clientDialogs.PlanetaryConditionsDialog;
9091
import megamek.client.ui.dialogs.gameConnectionDialogs.ConnectDialog;
9192
import megamek.client.ui.dialogs.gameConnectionDialogs.HostDialog;
@@ -162,6 +163,7 @@ public class MegaMekGUI implements IPreferenceChangeListener {
162163
private ManagedVolatileImage medalImage;
163164
private TipOfTheDay tipOfTheDay;
164165
private AbstractRandomArmyDialog randomArmyDialog;
166+
private NetworkInformationDialog networkInformationDialog;
165167

166168
private static MegaMekController controller;
167169

@@ -1012,7 +1014,7 @@ void scenario(String fileName) {
10121014
orig.setValue(opt.getValue());
10131015
}
10141016
}
1015-
1017+
10161018
// popup planetary conditions dialog
10171019
if ((game instanceof PlanetaryConditionsUsing plGame) && !scenario.hasFixedPlanetaryConditions()) {
10181020
PlanetaryConditionsDialog pcd = new PlanetaryConditionsDialog(frame, plGame.getPlanetaryConditions());
@@ -1310,6 +1312,9 @@ void unlaunch() {
13101312
case ClientGUI.FILE_GAME_QUICK_LOAD:
13111313
quickLoadGame();
13121314
break;
1315+
case ClientGUI.VIEW_NETWORK_INFORMATION:
1316+
showNetworkInformation();
1317+
break;
13131318
case ClientGUI.HELP_ABOUT:
13141319
new CommonAboutDialog(frame).setVisible(true);
13151320
break;
@@ -1343,6 +1348,19 @@ void unlaunch() {
13431348
}
13441349
};
13451350

1351+
private void showNetworkInformation() {
1352+
// Display the network information screen
1353+
getNetworkInformationDialog().refresh();
1354+
getNetworkInformationDialog().pack();
1355+
getNetworkInformationDialog().setVisible(true);
1356+
}
1357+
1358+
public NetworkInformationDialog getNetworkInformationDialog() {
1359+
if (networkInformationDialog == null) {
1360+
networkInformationDialog = new NetworkInformationDialog(this.frame);
1361+
}
1362+
return networkInformationDialog;
1363+
}
13461364
@Override
13471365
public void preferenceChange(PreferenceChangeEvent evt) {
13481366
switch (evt.getName()) {
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright (C) 2026 The MegaMek Team. All Rights Reserved.
3+
*
4+
* This file is part of MegaMek.
5+
*
6+
* MegaMek is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License (GPL),
8+
* version 3 or (at your option) any later version,
9+
* as published by the Free Software Foundation.
10+
*
11+
* MegaMek is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty
13+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU General Public License for more details.
15+
*
16+
* A copy of the GPL should have been included with this project;
17+
* if not, see <https://www.gnu.org/licenses/>.
18+
*
19+
* NOTICE: The MegaMek organization is a non-profit group of volunteers
20+
* creating free software for the BattleTech community.
21+
*
22+
* MechWarrior, BattleMech, `Mech and AeroTech are registered trademarks
23+
* of The Topps Company, Inc. All Rights Reserved.
24+
*
25+
* Catalyst Game Labs and the Catalyst Game Labs logo are trademarks of
26+
* InMediaRes Productions, LLC.
27+
*
28+
* MechWarrior Copyright Microsoft Corporation. MegaMek was created under
29+
* Microsoft's "Game Content Usage Rules"
30+
* <https://www.xbox.com/en-US/developers/rules> and it is not endorsed by or
31+
* affiliated with Microsoft.
32+
*/
33+
package megamek.client.ui.dialogs.buttonDialogs;
34+
35+
import java.awt.Container;
36+
import java.awt.Dimension;
37+
import java.awt.event.ActionEvent;
38+
import java.awt.event.ActionListener;
39+
import java.io.BufferedReader;
40+
import java.io.InputStreamReader;
41+
import java.io.Serial;
42+
import java.net.InetAddress;
43+
import java.net.URL;
44+
import javax.swing.Box;
45+
import javax.swing.BoxLayout;
46+
import javax.swing.JButton;
47+
import javax.swing.JFrame;
48+
import javax.swing.JLabel;
49+
import javax.swing.JPanel;
50+
51+
import megamek.client.ui.Messages;
52+
import megamek.client.ui.clientGUI.ClientGUI;
53+
54+
/**
55+
* A JPanel that holds the networking information about the network information of the current session.
56+
*/
57+
public class NetworkInformationDialog extends AbstractButtonDialog implements ActionListener {
58+
59+
private JFrame frame;
60+
61+
@Serial
62+
private static final long serialVersionUID = -4754010220963493049L;
63+
64+
private final JLabel lblLocalIP = new JLabel(Messages.getString("NetworkInformation.localIP"));
65+
private JLabel localIP = new JLabel(Messages.getString("NetworkInformation.blankIP"));
66+
private final JLabel lblRemoteIP = new JLabel(Messages.getString("NetworkInformation.remoteIP"));
67+
private JLabel remoteIP = new JLabel(Messages.getString("NetworkInformation.blankIP"));
68+
;
69+
private final JLabel lblConnectedIP = new JLabel(Messages.getString("NetworkInformation.connectedIP"));
70+
private JLabel connectedIP = new JLabel(Messages.getString("NetworkInformation.blankIP"));
71+
;
72+
private final JButton butShowLocalIPs = new JButton(" " + Messages.getString("NetworkInformation.buttonShowIPs"));
73+
private final JButton butShowRemoteIPs = new JButton(" " + Messages.getString("NetworkInformation.buttonShowIPs"));
74+
private final JButton butShowHostIPs = new JButton(" " + Messages.getString("NetworkInformation.buttonShowIPs"));
75+
private final JLabel lblBlank = new JLabel("");
76+
private ClientGUI clientGui;
77+
78+
/**
79+
* Constructs the network overview panel; the given ClientGUI is used to access the game data.
80+
*/
81+
public NetworkInformationDialog(ClientGUI cg) {
82+
super(cg.getFrame(), "NetworkInformationDialog", "NetworkInformation.title");
83+
clientGui = cg;
84+
init(cg.getFrame());
85+
}
86+
87+
public NetworkInformationDialog(JFrame frame) {
88+
super(frame, "NetworkInformationDialog", "NetworkInformation.title");
89+
init(frame);
90+
}
91+
92+
private void init(JFrame frame) {
93+
this.frame = frame;
94+
refresh();
95+
initialize();
96+
}
97+
98+
@Override
99+
public void actionPerformed(ActionEvent e) {
100+
if (e.getSource() == butShowLocalIPs) {
101+
if (localIP.isVisible()) {
102+
localIP.setVisible(false);
103+
} else {
104+
localIP.setVisible(true);
105+
}
106+
}
107+
if (e.getSource() == butShowRemoteIPs) {
108+
if (remoteIP.isVisible()) {
109+
remoteIP.setVisible(false);
110+
} else {
111+
remoteIP.setVisible(true);
112+
}
113+
}
114+
if (e.getSource() == butShowHostIPs) {
115+
if (connectedIP.isVisible()) {
116+
connectedIP.setVisible(false);
117+
} else {
118+
connectedIP.setVisible(true);
119+
}
120+
}
121+
}
122+
123+
@Override
124+
protected Container createCenterPane() {
125+
var mainPanel = new JPanel();
126+
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
127+
refresh();
128+
localIP.setVisible(false);
129+
remoteIP.setVisible(false);
130+
connectedIP.setVisible(false);
131+
132+
JPanel row1 = new JPanel();
133+
row1.setLayout(new BoxLayout(row1, BoxLayout.X_AXIS));
134+
row1.add(lblLocalIP);
135+
row1.add(Box.createHorizontalStrut(10));
136+
row1.add(localIP);
137+
row1.add(Box.createHorizontalGlue());
138+
row1.add(butShowLocalIPs);
139+
140+
JPanel row2 = new JPanel();
141+
row2.setLayout(new BoxLayout(row2, BoxLayout.X_AXIS));
142+
row2.add(lblRemoteIP);
143+
row2.add(Box.createHorizontalStrut(10));
144+
row2.add(remoteIP);
145+
row2.add(Box.createHorizontalGlue());
146+
row2.add(butShowRemoteIPs);
147+
148+
JPanel row3 = new JPanel();
149+
row3.setLayout(new BoxLayout(row3, BoxLayout.X_AXIS));
150+
row3.add(lblConnectedIP);
151+
row3.add(Box.createHorizontalStrut(10));
152+
row3.add(connectedIP);
153+
row3.add(Box.createHorizontalGlue());
154+
row3.add(butShowHostIPs);
155+
156+
mainPanel.add(row1);
157+
mainPanel.add(row2);
158+
mainPanel.add(row3);
159+
160+
butShowLocalIPs.addActionListener(this);
161+
butShowHostIPs.addActionListener(this);
162+
butShowRemoteIPs.addActionListener(this);
163+
mainPanel.setPreferredSize(new Dimension(400, 300));
164+
return mainPanel;
165+
}
166+
167+
public void refresh() {
168+
localIP.setText(" " + getIPaddress(true));
169+
remoteIP.setText(" " + getIPaddress(false));
170+
if (clientGui != null) {
171+
connectedIP.setText(" " + clientGui.getClient().getHost());
172+
}
173+
}
174+
175+
private String getIPaddress(boolean localIP) {
176+
String thisIpAddress = "";
177+
178+
if (localIP) {
179+
try {
180+
InetAddress thisIp = InetAddress.getLocalHost();
181+
thisIpAddress = thisIp.getHostAddress();
182+
} catch (Exception e) {
183+
}
184+
if (thisIpAddress.length() == 0 || thisIpAddress == null) {
185+
thisIpAddress = "Could not obtain local IP address";
186+
}
187+
} else {
188+
try {
189+
URL whatismyip = new URL("http://checkip.amazonaws.com");
190+
BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
191+
thisIpAddress = in.readLine();
192+
in.close();
193+
} catch (Exception e) {
194+
}
195+
if (thisIpAddress.length() == 0 || thisIpAddress == null) {
196+
thisIpAddress = "Could not obtain public IP address";
197+
}
198+
}
199+
return thisIpAddress;
200+
}
201+
}

0 commit comments

Comments
 (0)