diff --git a/src/main/java/com/leflat/jass/client/ArtificialClient.java b/src/main/java/com/leflat/jass/client/ArtificialClient.java index be0f312..c3e4009 100644 --- a/src/main/java/com/leflat/jass/client/ArtificialClient.java +++ b/src/main/java/com/leflat/jass/client/ArtificialClient.java @@ -38,7 +38,7 @@ public int connect(String name, String host, int gameId) { network = null; return connectionInfo.error; } - id = connectionInfo.playerId; + id = connectionInfo.playerId; positionsByIds.put(id, 0); controller = new RemoteController(this, network); controllerThread = new Thread(controller, "controller-thread"); diff --git a/src/main/java/com/leflat/jass/client/DialogConnect.java b/src/main/java/com/leflat/jass/client/DialogConnect.java deleted file mode 100644 index 3443ea1..0000000 --- a/src/main/java/com/leflat/jass/client/DialogConnect.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * DialogConnect.java - * - * Created on 18. avril 2000, 21:34 - */ - -/* - * - * @author Berclaz Jérôme - * @version - */ - -package com.leflat.jass.client; - - -import javax.swing.*; -import javax.swing.text.MaskFormatter; -import java.awt.*; -import java.text.ParseException; - -public class DialogConnect extends javax.swing.JDialog { - private static final String INITIAL_NAME = "Joueur"; - private static final String INITIAL_HOST = "localhost"; - boolean ok = false; - String name, host; - int gameId; - - /** - * Creates new form DialogConnect - */ - public DialogConnect(java.awt.Frame parent) { - super(parent, true); - initComponents(); - this.setSize(360, 220); - pack(); - jTextFieldHost.setText(INITIAL_HOST); - jTextFieldName.setText(INITIAL_NAME); - } - - public DialogConnect(java.awt.Frame parent, String name, String host) { - this(parent); - jTextFieldName.setText(name); - jTextFieldHost.setText(host); - } - - /** - * This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the FormEditor. - */ - private void initComponents() {//GEN-BEGIN:initComponents - jPanel1 = new javax.swing.JPanel(); - jLabelName = new javax.swing.JLabel(); - jLabelGame = new javax.swing.JLabel(); - jLabelServer = new javax.swing.JLabel(); - jTextFieldName = new javax.swing.JTextField(); - MaskFormatter formatter = null; - try { - formatter = new MaskFormatter("### ###"); - formatter.setValueContainsLiteralCharacters(false); - } catch (ParseException e) { - e.printStackTrace(); - } - jTextFieldGame = new javax.swing.JFormattedTextField(formatter); - jTextFieldGame.setInputVerifier(new InputVerifier() { - @Override - public boolean verify(JComponent jComponent) { - var field = (JFormattedTextField) jComponent; - String text = field.getText(); - if (text.isBlank()) { - return true; - } - return text.strip().length() == 7; - } - }); - jTextFieldHost = new javax.swing.JTextField(); - jButtonOk = new javax.swing.JButton(); - jButtonCancel = new javax.swing.JButton(); - getContentPane().setLayout(new java.awt.GridBagLayout()); - java.awt.GridBagConstraints gridBagConstraints1; - setResizable(false); - setTitle("Connexion"); - addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosing(java.awt.event.WindowEvent evt) { - closeDialog(); - } - } - ); - - jPanel1.setLayout(new java.awt.GridBagLayout()); - java.awt.GridBagConstraints gridBagConstraints2; - jPanel1.setBorder(new javax.swing.border.TitledBorder("Paramètres de connexion")); - - jLabelName.setText("Nom"); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 0; - gridBagConstraints2.gridy = 0; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.insets = new java.awt.Insets(14, 20, 0, 0); - jPanel1.add(jLabelName, gridBagConstraints2); - - jLabelGame.setText("Jeu"); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 0; - gridBagConstraints2.gridy = 2; - gridBagConstraints2.gridwidth = 2; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.insets = new java.awt.Insets(10, 20, 0, 0); - jPanel1.add(jLabelGame, gridBagConstraints2); - - jLabelServer.setText("Serveur"); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 0; - gridBagConstraints2.gridy = 4; - gridBagConstraints2.gridwidth = 3; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.insets = new java.awt.Insets(10, 21, 0, 0); - jPanel1.add(jLabelServer, gridBagConstraints2); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 3; - gridBagConstraints2.gridy = 0; - gridBagConstraints2.gridheight = 2; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.ipadx = 146; - gridBagConstraints2.insets = new java.awt.Insets(11, 61, 8, 0); - jPanel1.add(jTextFieldName, gridBagConstraints2); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 3; - gridBagConstraints2.gridy = 2; - gridBagConstraints2.gridheight = 2; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.ipadx = 146; - gridBagConstraints2.insets = new java.awt.Insets(9, 61, 8, 0); - jPanel1.add(jTextFieldGame, gridBagConstraints2); - - gridBagConstraints2 = new java.awt.GridBagConstraints(); - gridBagConstraints2.gridx = 3; - gridBagConstraints2.gridy = 4; - gridBagConstraints2.gridheight = 2; - gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints2.ipadx = 77; - gridBagConstraints2.insets = new java.awt.Insets(9, 61, 8, 0); - jPanel1.add(jTextFieldHost, gridBagConstraints2); - - gridBagConstraints1 = new java.awt.GridBagConstraints(); - gridBagConstraints1.gridx = 0; - gridBagConstraints1.gridy = 0; - gridBagConstraints1.gridwidth = 3; - gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints1.ipadx = 28; - gridBagConstraints1.ipady = -7; - gridBagConstraints1.insets = new java.awt.Insets(3, 10, 3, 9); - getContentPane().add(jPanel1, gridBagConstraints1); - - jButtonOk.setText("Ok"); - jButtonOk.setDefaultCapable(true); - jButtonOk.addActionListener(this::jButtonOkActionPerformed); - gridBagConstraints1 = new java.awt.GridBagConstraints(); - gridBagConstraints1.gridx = 0; - gridBagConstraints1.gridy = 1; - gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints1.insets = new java.awt.Insets(10, 50, 10, 0); - getContentPane().add(jButtonOk, gridBagConstraints1); - - jButtonCancel.setText("Annuler"); - jButtonCancel.addActionListener(this::jButtonCancelActionPerformed); - gridBagConstraints1 = new java.awt.GridBagConstraints(); - gridBagConstraints1.gridx = 1; - gridBagConstraints1.gridy = 1; - gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints1.insets = new java.awt.Insets(10, 103, 10, 0); - getContentPane().add(jButtonCancel, gridBagConstraints1); - - getRootPane().setDefaultButton(jButtonOk); - }//GEN-END:initComponents - - private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed -// Add your handling code here: - this.dispose(); - }//GEN-LAST:event_jButtonCancelActionPerformed - - private void jButtonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonOkActionPerformed -// Add your handling code here: - if (!jTextFieldGame.getText().isBlank() && jTextFieldGame.getValue() == null) { - jLabelGame.setForeground(new Color(128, 0, 0)); - return; - } - ok = true; - gameId = jTextFieldGame.getValue() == null ? -1 : Integer.parseInt((String) jTextFieldGame.getValue()); - name = jTextFieldName.getText(); - host = jTextFieldHost.getText(); - this.dispose(); - }//GEN-LAST:event_jButtonOkActionPerformed - - /** - * Closes the dialog - */ - private void closeDialog() {//GEN-FIRST:event_closeDialog - setVisible(false); - dispose(); - }//GEN-LAST:event_closeDialog - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JPanel jPanel1; - private javax.swing.JLabel jLabelName; - private javax.swing.JLabel jLabelGame; - private javax.swing.JLabel jLabelServer; - private javax.swing.JTextField jTextFieldName; - private javax.swing.JFormattedTextField jTextFieldGame; - private javax.swing.JTextField jTextFieldHost; - private javax.swing.JButton jButtonOk; - private javax.swing.JButton jButtonCancel; - // End of variables declaration//GEN-END:variables - -} diff --git a/src/main/java/com/leflat/jass/client/DialogConnection.form b/src/main/java/com/leflat/jass/client/DialogConnection.form new file mode 100644 index 0000000..90eb542 --- /dev/null +++ b/src/main/java/com/leflat/jass/client/DialogConnection.form @@ -0,0 +1,142 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/com/leflat/jass/client/DialogConnection.java b/src/main/java/com/leflat/jass/client/DialogConnection.java new file mode 100644 index 0000000..40f1ccf --- /dev/null +++ b/src/main/java/com/leflat/jass/client/DialogConnection.java @@ -0,0 +1,158 @@ +package com.leflat.jass.client; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.MaskFormatter; +import java.awt.*; +import java.awt.event.*; +import java.text.ParseException; + +public class DialogConnection extends JDialog { + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JTextField textFieldName; + private JTextField textFieldHost; + private JCheckBox joinExistingGameCheckBox; + private JSpinner spinnerAiPlayers; + private JFormattedTextField textFieldGameNumber; + private JLabel labelGameId; + private JLabel labelAiPlayer; + private Border defaultBorder; + + public boolean ok; + public String name; + public String host; + public int aiPlayers; + public int gameId; + + public DialogConnection(Frame parent) { + super(parent, true); + setComponents(); + } + + public DialogConnection(Frame parent, String name, String host) { + this(parent); + textFieldName.setText(name); + textFieldHost.setText(host); + } + + private void setComponents() { + setTitle("Connexion"); + setContentPane(contentPane); + getRootPane().setDefaultButton(buttonOK); + try { + var formatter = new MaskFormatter("### ###"); + formatter.setPlaceholderCharacter('_'); + textFieldGameNumber.setFormatterFactory(new DefaultFormatterFactory(formatter)); + } catch (ParseException e) { + throw new RuntimeException(e); + } + onCheckBox(); + spinnerAiPlayers.setModel(new SpinnerNumberModel(0, 0, 3, 1)); + defaultBorder = textFieldName.getBorder(); + + buttonOK.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onOK(); + } + }); + + buttonCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onCancel(); + } + }); + + joinExistingGameCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + onCheckBox(); + } + }); + + // call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onCancel(); + } + }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + if (checkFieldErrors()) { + return; + } + if (joinExistingGameCheckBox.isSelected()) { + String gameIdString = textFieldGameNumber.getText(); + gameId = Integer.parseInt(gameIdString.replace(" ", "")); + aiPlayers = 0; + } else { + aiPlayers = (Integer)spinnerAiPlayers.getValue(); + gameId = -1; + } + name = textFieldName.getText(); + host = textFieldHost.getText(); + ok = true; + dispose(); + } + + private boolean checkFieldErrors() { + boolean errors = false; + if (textFieldHost.getText().isBlank()) { + Border border = BorderFactory.createLineBorder(Color.RED, 2); + textFieldHost.setBorder(BorderFactory.createCompoundBorder(border, BorderFactory.createEmptyBorder(2, 7, 2, 7))); + errors = true; + } else { + textFieldHost.setBorder(defaultBorder); + } + if (textFieldName.getText().isBlank()) { + Border border = BorderFactory.createLineBorder(Color.RED, 2); + textFieldName.setBorder(BorderFactory.createCompoundBorder(border, BorderFactory.createEmptyBorder(2, 7, 2, 7))); + errors = true; + } else { + textFieldName.setBorder(defaultBorder); + } + if (joinExistingGameCheckBox.isSelected()) { + if (textFieldGameNumber.getValue() == null) { + Border border = BorderFactory.createLineBorder(Color.RED, 2); + textFieldGameNumber.setBorder(BorderFactory.createCompoundBorder(border, BorderFactory.createEmptyBorder(2, 7, 2, 7))); + errors = true; + } else { + textFieldGameNumber.setBorder(defaultBorder); + } + } else { + textFieldGameNumber.setBorder(defaultBorder); + } + return errors; + } + + private void onCancel() { + ok = false; + dispose(); + } + + private void onCheckBox() { + boolean joinGame = joinExistingGameCheckBox.isSelected(); + textFieldGameNumber.setEnabled(joinGame); + labelGameId.setEnabled(joinGame); + spinnerAiPlayers.setEnabled(!joinGame); + labelAiPlayer.setEnabled(!joinGame); + } + + public static void main(String[] args) { + var dialog = new DialogConnection(null, "name", "host"); + dialog.pack(); + dialog.setVisible(true); + System.exit(0); + } +} \ No newline at end of file diff --git a/src/main/java/com/leflat/jass/client/ModernGamePanel.java b/src/main/java/com/leflat/jass/client/ModernGamePanel.java index 489818a..effacd6 100644 --- a/src/main/java/com/leflat/jass/client/ModernGamePanel.java +++ b/src/main/java/com/leflat/jass/client/ModernGamePanel.java @@ -107,6 +107,7 @@ public void clearCards() { } drawnCards.clear(); lastPlie.clear(); + playedCards.clear(); repaint(); } @@ -253,6 +254,9 @@ public void collectCards(PlayerPosition position) { int totalNbrSteps = round(ANIMATION_DURATION_S * 1000 / frameDurationMs); for (var playerPos : PlayerPosition.values()) { + if (playerPos == PlayerPosition.NONE) { + continue; + } var cardPos = getPlayedCardPosition(playerPos, centerArea, cardDimension); int width, height; if (playerPos == PlayerPosition.MYSELF || playerPos == PlayerPosition.ACROSS) { @@ -272,6 +276,9 @@ public void collectCards(PlayerPosition position) { animationTimer = new Timer(frameDurationMs, actionEvent -> { Rectangle repaintArea = null; for (var playerPos : PlayerPosition.values()) { + if (playerPos == PlayerPosition.NONE) { + continue; + } var pos = animationPositions.get(playerPos); var step = animationSteps.get(playerPos); repaintArea = repaintArea == null ? new Rectangle(pos) : repaintArea.union(pos); diff --git a/src/main/java/com/leflat/jass/client/ModernUi.java b/src/main/java/com/leflat/jass/client/ModernUi.java index fa3c21a..39bf1a1 100644 --- a/src/main/java/com/leflat/jass/client/ModernUi.java +++ b/src/main/java/com/leflat/jass/client/ModernUi.java @@ -77,14 +77,15 @@ public void showUi(boolean enable) { } private void connectDialog() { - int gameId; + int returnCode; do { - DialogConnect dc; + DialogConnection dc; if (myName != null && serverHost != null) { - dc = new DialogConnect(this, myName, serverHost); + dc = new DialogConnection(this, myName, serverHost); } else { - dc = new DialogConnect(this); + dc = new DialogConnection(this); } + dc.pack(); dc.setLocationRelativeTo(this); dc.setVisible(true); if (!dc.ok) { @@ -94,11 +95,18 @@ private void connectDialog() { } myName = dc.name; serverHost = dc.host; - gameId = myself.connect(dc.name, dc.host, dc.gameId); - if (gameId >= 0) { - setGameId(gameId); + returnCode = myself.connect(dc.name, dc.host, dc.gameId); + if (returnCode >= 0) { + setGameId(returnCode); + if (dc.gameId < 0 && dc.aiPlayers > 0) { + for (int i=0; i maxScore) { maxScore = score; }