diff --git a/client/src/main/java/nl/andrewlalis/aos_client/launcher/Launcher.java b/client/src/main/java/nl/andrewlalis/aos_client/launcher/Launcher.java index 4d45b87..3fd3c47 100644 --- a/client/src/main/java/nl/andrewlalis/aos_client/launcher/Launcher.java +++ b/client/src/main/java/nl/andrewlalis/aos_client/launcher/Launcher.java @@ -7,11 +7,11 @@ import nl.andrewlalis.aos_client.launcher.servers.ServerInfoListModel; import javax.swing.*; import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -35,7 +35,6 @@ public class Launcher extends JFrame { private Container buildContent() { JTabbedPane mainPanel = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); - mainPanel.addTab("Connect", null, this.getConnectPanel(), "Connect to a server and play."); mainPanel.addTab("Servers", null, this.getServersPanel(), "View a list of available servers."); // // JPanel settingsPanel = new JPanel(); @@ -44,57 +43,6 @@ public class Launcher extends JFrame { return mainPanel; } - private Container getConnectPanel() { - JPanel inputPanel = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(5, 5, 5, 5); - - c.gridx = 0; - c.gridy = 0; - inputPanel.add(new JLabel("Address"), c); - JTextField addressField = new JTextField(20); - c.gridx = 1; - inputPanel.add(addressField, c); - - c.gridy = 1; - c.gridx = 0; - inputPanel.add(new JLabel("Username"), c); - JTextField usernameField = new JTextField(20); - c.gridx = 1; - inputPanel.add(usernameField, c); - - var enterListener = new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - if (validateConnectInput(addressField, usernameField)) { - connect(addressField, usernameField); - } - } - } - }; - addressField.addKeyListener(enterListener); - usernameField.addKeyListener(enterListener); - - JPanel buttonPanel = new JPanel(new FlowLayout()); - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(e -> this.dispose()); - JButton connectButton = new JButton("Connect"); - connectButton.addActionListener(e -> { - if (validateConnectInput(addressField, usernameField)) { - connect(addressField, usernameField); - } - }); - buttonPanel.add(cancelButton); - buttonPanel.add(connectButton); - - JPanel mainPanel = new JPanel(new BorderLayout()); - mainPanel.add(new JLabel("Directly connect to a server and play."), BorderLayout.NORTH); - mainPanel.add(inputPanel, BorderLayout.CENTER); - mainPanel.add(buttonPanel, BorderLayout.SOUTH); - return mainPanel; - } - private Container getServersPanel() { JPanel panel = new JPanel(new BorderLayout()); @@ -144,16 +92,76 @@ public class Launcher extends JFrame { JPanel buttonPanel = new JPanel(); JButton addServerButton = new JButton("Add Server"); + addServerButton.setToolTipText("Add a new server to the list."); addServerButton.addActionListener(e -> { // TODO: Add server dialog. }); buttonPanel.add(addServerButton); + JButton directConnectButton = new JButton("Direct Connect"); + directConnectButton.setToolTipText("Connect to any server directly."); + directConnectButton.addActionListener(e -> { + JDialog dialog = new JDialog(this, true); + dialog.setTitle("Direct Connect"); + dialog.setContentPane(getConnectPanel(dialog)); + dialog.pack(); + dialog.setLocationRelativeTo(this); + dialog.setVisible(true); + }); + buttonPanel.add(directConnectButton); + + JButton helpButton = new JButton("Help"); + helpButton.setToolTipText("Show some helpful information for using this program."); + helpButton.addActionListener(e -> { + String uri = "https://github.com/andrewlalis/AceOfShades/blob/main/help.md"; + try { + Desktop.getDesktop().browse(new URI(uri)); + } catch (IOException | URISyntaxException ex) { + ex.printStackTrace(); + JOptionPane.showMessageDialog(this, "Could not open URI in browser. For help, please visit\n" + uri, "Error", JOptionPane.WARNING_MESSAGE); + } + }); + buttonPanel.add(helpButton); panel.add(buttonPanel, BorderLayout.SOUTH); return panel; } + private Container getConnectPanel(JDialog dialog) { + JPanel inputPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(5, 5, 5, 5); + + c.gridx = 0; + c.gridy = 0; + inputPanel.add(new JLabel("Address"), c); + JTextField addressField = new JTextField(20); + c.gridx = 1; + inputPanel.add(addressField, c); + + c.gridy = 1; + c.gridx = 0; + inputPanel.add(new JLabel("Username"), c); + JTextField usernameField = new JTextField(20); + c.gridx = 1; + inputPanel.add(usernameField, c); + + JPanel buttonPanel = new JPanel(new FlowLayout()); + JButton connectButton = new JButton("Connect"); + connectButton.addActionListener(e -> { + if (validateConnectInput(addressField, usernameField)) { + dialog.dispose(); + connect(new ServerInfo("Unknown", addressField.getText(), usernameField.getText())); + } + }); + buttonPanel.add(connectButton); + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(inputPanel, BorderLayout.CENTER); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + return mainPanel; + } + private boolean validateConnectInput(JTextField addressField, JTextField usernameField) { List warnings = new ArrayList<>(); if (addressField.getText() == null || addressField.getText().isBlank()) { @@ -179,20 +187,6 @@ public class Launcher extends JFrame { return warnings.isEmpty(); } - private void connect(JTextField addressField, JTextField usernameField) { - String hostAndPort = addressField.getText(); - String[] parts = hostAndPort.split(":"); - String host = parts[0].trim(); - int port = Integer.parseInt(parts[1]); - String username = usernameField.getText(); - try { - new Client(host, port, username); - } catch (IOException ex) { - ex.printStackTrace(); - JOptionPane.showMessageDialog(null, "Could not connect:\n" + ex.getMessage(), "Connection Error", JOptionPane.WARNING_MESSAGE); - } - } - private void connect(ServerInfo serverInfo) { String username = serverInfo.getUsername(); if (username == null) { diff --git a/help.md b/help.md new file mode 100644 index 0000000..cac837e --- /dev/null +++ b/help.md @@ -0,0 +1,36 @@ +# Ace of Shades - Help Information +In this document, we'll go over how to use the launcher, basic game controls, and some explanations of game mechanics so that you can start playing right away. + +## Launcher +The launcher is a small application that makes it easy to connect to different servers to join their hosted games. The first thing you'll see is a list of servers. **You can remove or edit a server by right-clicking on it**, and **you can add new servers using the Add Server button** at the bottom. + +Each entry in the list is just a way to remember a specific address (and optionally your preferred username when connecting to that server), so that **you can double-click on a server to instantly connect**. + +> Servers have an *address* which consists usually of an IP address and port number. For example, there might be a server whose address is `123.123.123.123:54321`. +> +> It's up to the server to decide whether to allow you to join, so pick a sensible username. + +## Controls +To control your player in-game, the following are the default controls: + +| Control | Description | +|--------------|-------------------------------------------------| +| `WASD` | Move player forward, left, backward, and right. | +| `R` | Reload your weapon. | +| `T` | Start typing a message in chat. | +| `/` | Start typing a command in chat. | +| `LEFT-CLICK` | Use your weapon. | +| `SCROLL` | Zoom in or out. | +| `MOUSE-MOVE` | Aim your weapon. | +| `ENTER` | Send your message or command in chat. | + +> Be careful when typing a message or command in chat! Other players can and will try to kill you. + +## Basic Mechanics +In most scenarios, when you join a server, you'll be placed onto a *team*. Each team has a spawn point, which is where you'll start out. There's also a resupply area for each team, where you can replenish your health and ammunition when running low. + +Each time you kill someone from another team, your own team's score increases. Different servers may come up with different rules for what constitutes a victory, but the premise is simple: **kill as many enemies as possible**. + +You can quit at any time by closing the game window. + +> Some servers may have policies which discourage *combat-logging* (disconnecting when about to die), and they may ban you from reconnecting! Take this into account, and play fair.