Compare commits

...

7 Commits

Author SHA1 Message Date
d62e0b7188 chuuuut 2025-03-13 10:10:16 +01:00
ef7bbc8492 packetpool: remove simulation 2025-03-13 10:08:36 +01:00
Clément
eee63cc5c6 lil fix 2025-03-13 10:03:26 +01:00
Clément
a4c5d3f67b add roomss 2025-03-13 09:52:25 +01:00
Clément
709a92aa4c little cleanup 2025-03-12 23:38:30 +01:00
Clément
67124f4731 labelled the name of the room when in it 2025-03-12 23:34:08 +01:00
Clément
631cd25a9d updates the rooms every second 2025-03-12 23:29:22 +01:00
3 changed files with 83 additions and 22 deletions

View File

@@ -1,5 +1,7 @@
package client; package client;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.*; import javafx.scene.control.*;
@@ -7,6 +9,7 @@ import javafx.scene.layout.*;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.scene.text.TextFlow; import javafx.scene.text.TextFlow;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.util.Duration;
import network.protocol.packets.ServerResponsePacket; import network.protocol.packets.ServerResponsePacket;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@@ -41,13 +44,16 @@ public class ClientGuiController implements ClientListener {
@FXML @FXML
private ScrollPane chatPane; private ScrollPane chatPane;
@FXML
private Label roomName;
public void setClient(Client client) { public void setClient(Client client) {
this.client = client; this.client = client;
} }
@FXML @FXML
public void initialize() throws SocketException { public void initialize() throws SocketException {
client = new Client(new InetSocketAddress("localhost", 6665), this, UsernameSingleton.getInstance().getUsername()); client = new Client(new InetSocketAddress("192.168.163.131", 6665), this, UsernameSingleton.getInstance().getUsername());
Platform.runLater(() -> { Platform.runLater(() -> {
Stage stage = (Stage) vueContainer.getScene().getWindow(); Stage stage = (Stage) vueContainer.getScene().getWindow();
stage.setResizable(true); // Fixed a bug that made the close button disappear under my Wayland setup (don't know if it's the same for x11) stage.setResizable(true); // Fixed a bug that made the close button disappear under my Wayland setup (don't know if it's the same for x11)
@@ -57,6 +63,17 @@ public class ClientGuiController implements ClientListener {
}); });
chatList.heightProperty().addListener((obs, oldVal, newVal) -> chatPane.setVvalue(1.0)); chatList.heightProperty().addListener((obs, oldVal, newVal) -> chatPane.setVvalue(1.0));
}); });
requestRoomsRegularly();
}
/**
* Request the list of rooms from the server every second.
*/
private void requestRoomsRegularly() {
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(10), event -> client.RequestRoomList()));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
} }
@Override @Override
@@ -111,7 +128,7 @@ public class ClientGuiController implements ClientListener {
String timeString = formatter.format(time); String timeString = formatter.format(time);
Text chatterText = new Text(chatter + ": "); Text chatterText = new Text(chatter + ": ");
chatterText.setStyle("-fx-fill: black; -fx-font-weight: bold;"); chatterText.setStyle("-fx-fill: black; -fx-font-weight: bold;");
TextFlow messageText = formatMessage(chatter, untagged); TextFlow messageText = formatMessage(untagged);
TextFlow wholeMessage = new TextFlow(chatterText, messageText); TextFlow wholeMessage = new TextFlow(chatterText, messageText);
Text timeText = new Text(" " + timeString); Text timeText = new Text(" " + timeString);
timeText.setStyle("-fx-fill: gray; -fx-font-size: 10px;"); timeText.setStyle("-fx-fill: gray; -fx-font-size: 10px;");
@@ -132,7 +149,7 @@ public class ClientGuiController implements ClientListener {
Pattern pattern = Pattern.compile("\u001B\\[44;30m(.*?)\u001B\\[49;39m"); Pattern pattern = Pattern.compile("\u001B\\[44;30m(.*?)\u001B\\[49;39m");
Matcher matcher = pattern.matcher(message); Matcher matcher = pattern.matcher(message);
StringBuffer result = new StringBuffer(); StringBuilder result = new StringBuilder();
while (matcher.find()) { while (matcher.find()) {
String taggedName = matcher.group(1); String taggedName = matcher.group(1);
matcher.appendReplacement(result, taggedName); matcher.appendReplacement(result, taggedName);
@@ -167,11 +184,13 @@ public class ClientGuiController implements ClientListener {
*/ */
private void createChatEnv(String roomName) { private void createChatEnv(String roomName) {
Platform.runLater(() -> { Platform.runLater(() -> {
this.roomName.setText("Room: " + roomName);
chatList.getChildren().clear(); chatList.getChildren().clear();
chatInput.getChildren().clear(); chatInput.getChildren().clear();
Button leaveButton = new Button("Leave room"); Button leaveButton = new Button("Leave room");
leaveButton.setOnAction(event -> { leaveButton.setOnAction(event -> {
client.SendLeaveRoom(); client.SendLeaveRoom();
this.roomName.setText("");
chatList.getChildren().clear(); chatList.getChildren().clear();
chatInput.getChildren().clear(); chatInput.getChildren().clear();
}); });
@@ -199,11 +218,10 @@ public class ClientGuiController implements ClientListener {
/** /**
* Colorize the message according to the color codes. * Colorize the message according to the color codes.
* @param chatter the name of the person who sent the message
* @param content the content of the message * @param content the content of the message
* @return the formatted message * @return the formatted message
*/ */
private TextFlow formatMessage(String chatter, String content) { private TextFlow formatMessage(String content) {
TextFlow textFlow = new TextFlow(); TextFlow textFlow = new TextFlow();
// Evil regex : match every sequence starting with a color code ending with the next color code // Evil regex : match every sequence starting with a color code ending with the next color code
Pattern pattern = Pattern.compile("&([rbgyn])([^&]*)"); Pattern pattern = Pattern.compile("&([rbgyn])([^&]*)");
@@ -250,4 +268,16 @@ public class ClientGuiController implements ClientListener {
public void handleActualRoom(String roomName) { public void handleActualRoom(String roomName) {
} }
public void createRoom() {
TextInputDialog dialog = new TextInputDialog();
dialog.setTitle("Create a room");
dialog.setHeaderText("Enter the name of the room");
dialog.setContentText("Room name:");
Optional<String> result = dialog.showAndWait();
result.ifPresent(name -> {
client.SendCreateRoom(name);
createChatEnv(name);
});
}
} }

View File

@@ -24,7 +24,7 @@ public class PacketPool {
private static int MAX_SEND_TRY = 50; private static int MAX_SEND_TRY = 50;
private static long SEND_DELAY = 10; private static long SEND_DELAY = 10;
private static long RETRY_INTERVAL = SEND_DELAY * 2; private static long RETRY_INTERVAL = 100;
private static float PACKET_LOSS_PROBABILITY = 0.1f; private static float PACKET_LOSS_PROBABILITY = 0.1f;
private static record ReliablePacketAddress(ReliablePacket packet, InetSocketAddress address) { private static record ReliablePacketAddress(ReliablePacket packet, InetSocketAddress address) {
@@ -71,6 +71,7 @@ public class PacketPool {
/** /**
* Set the recieve sequence number * Set the recieve sequence number
*
* @param address * @param address
* @param newValue * @param newValue
*/ */
@@ -80,6 +81,7 @@ public class PacketPool {
/** /**
* Try to add the address into memory * Try to add the address into memory
*
* @param address * @param address
*/ */
private void tryAddContext(InetSocketAddress address) { private void tryAddContext(InetSocketAddress address) {
@@ -88,6 +90,7 @@ public class PacketPool {
/** /**
* Construct a PacketPool * Construct a PacketPool
*
* @param socket * @param socket
*/ */
public PacketPool(Socket socket) { public PacketPool(Socket socket) {
@@ -114,6 +117,7 @@ public class PacketPool {
/** /**
* Send a packet to the socket * Send a packet to the socket
*
* @param packet * @param packet
* @param address * @param address
* @throws IOException * @throws IOException
@@ -122,13 +126,17 @@ public class PacketPool {
var packetsSentTries = this.addressContexts.get(address).packetsSentTries; var packetsSentTries = this.addressContexts.get(address).packetsSentTries;
new Thread(() -> { new Thread(() -> {
// try {
// Thread.sleep(SEND_DELAY);
// if (Math.random() > PACKET_LOSS_PROBABILITY)
try { try {
Thread.sleep(SEND_DELAY);
if (Math.random() > PACKET_LOSS_PROBABILITY)
this.socket.sendPacket(packet, address); this.socket.sendPacket(packet, address);
} catch (InterruptedException | IOException e) { } catch (IOException e) {
// e.printStackTrace(); // e.printStackTrace();
} }
// } catch (InterruptedException | IOException e) {
// // e.printStackTrace();
// }
}).start(); }).start();
if (packet.getPacket() instanceof AcknowlegdementPacket) if (packet.getPacket() instanceof AcknowlegdementPacket)
@@ -143,7 +151,9 @@ public class PacketPool {
} }
/** /**
* Send a packet to socket and try to resend if an acknowlegment was not recieved * Send a packet to socket and try to resend if an acknowlegment was not
* recieved
*
* @param packet * @param packet
* @param address * @param address
* @throws IOException * @throws IOException
@@ -163,6 +173,7 @@ public class PacketPool {
/** /**
* Send a packet (and encapsulate it) * Send a packet (and encapsulate it)
*
* @param packet * @param packet
* @param address * @param address
* @throws IOException * @throws IOException
@@ -175,6 +186,7 @@ public class PacketPool {
/** /**
* Try to resend a packet * Try to resend a packet
*
* @param reliablePacketAddress * @param reliablePacketAddress
*/ */
private void tryResend(ReliablePacketAddress reliablePacketAddress) { private void tryResend(ReliablePacketAddress reliablePacketAddress) {
@@ -212,7 +224,6 @@ public class PacketPool {
ctx.sendThreads.remove(Thread.currentThread()); ctx.sendThreads.remove(Thread.currentThread());
} }
/** /**
* @param address * @param address
* @return The smallest sequence number recieved * @return The smallest sequence number recieved
@@ -227,7 +238,9 @@ public class PacketPool {
} }
/** /**
* Move packets in buffer to the packet recieved queue to be processed by the app * Move packets in buffer to the packet recieved queue to be processed by the
* app
*
* @param address * @param address
* @return the sequence number of the last packet that was added to the queue * @return the sequence number of the last packet that was added to the queue
*/ */
@@ -251,6 +264,7 @@ public class PacketPool {
/** /**
* Process packet when recieved * Process packet when recieved
*
* @param packet * @param packet
* @param address * @param address
* @throws IOException * @throws IOException
@@ -311,6 +325,7 @@ public class PacketPool {
/** /**
* Closes the connexion * Closes the connexion
*
* @param adress * @param adress
*/ */
private void close(InetSocketAddress adress) { private void close(InetSocketAddress adress) {
@@ -321,6 +336,7 @@ public class PacketPool {
/** /**
* Stop the threads of the connexion * Stop the threads of the connexion
*
* @param adressContext * @param adressContext
*/ */
private void close(AdressContext adressContext) { private void close(AdressContext adressContext) {

View File

@@ -12,7 +12,7 @@
<BorderPane xmlns="http://javafx.com/javafx" <BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
fx:controller="client.ClientGuiController" fx:controller="client.ClientGuiController"
prefHeight="400.0" prefWidth="600.0" styleClass="vue-container" fx:id="vueContainer"> prefHeight="400.0" prefWidth="600.0" fx:id="vueContainer">
<top> <top>
<HBox alignment="CENTER" styleClass="logo-box"> <HBox alignment="CENTER" styleClass="logo-box">
<padding> <padding>
@@ -25,24 +25,39 @@
</HBox> </HBox>
</top> </top>
<left> <left>
<ScrollPane prefWidth="200.0" styleClass="rooms-pane" fx:id="roomsPane" fitToWidth="true"> <ScrollPane prefWidth="200.0" fitToWidth="true">
<VBox fx:id="rooms" spacing="10.0" alignment="CENTER" VBox.vgrow="ALWAYS"> <BorderPane>
<center>
<VBox spacing="10.0" alignment="CENTER" VBox.vgrow="ALWAYS">
<Label text="Rooms" styleClass="rooms-label"/> <Label text="Rooms" styleClass="rooms-label"/>
<VBox fx:id="roomList" styleClass="rooms-list" spacing="5.0" VBox.vgrow="ALWAYS" alignment="CENTER"/> <VBox fx:id="roomList" styleClass="rooms-list" spacing="5.0" VBox.vgrow="ALWAYS" alignment="CENTER"/>
</VBox> </VBox>
</center>
<bottom>
<Button text="Create room" onAction="#createRoom" />
</bottom>
</BorderPane>
</ScrollPane> </ScrollPane>
</left> </left>
<center> <center>
<BorderPane> <BorderPane>
<top>
<HBox alignment="CENTER">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<Label fx:id="roomName" style="-fx-font-size: 18px; -fx-font-weight: bold;"/>
</HBox>
</top>
<center> <center>
<ScrollPane styleClass="chat-pane" fx:id="chatPane" fitToWidth="true"> <ScrollPane fx:id="chatPane" fitToWidth="true">
<VBox fx:id="chat" spacing="10.0"> <VBox spacing="10.0">
<VBox fx:id="chatList" styleClass="chat-list" spacing="5.0" VBox.vgrow="ALWAYS"/> <VBox fx:id="chatList" styleClass="chat-list" spacing="5.0" VBox.vgrow="ALWAYS"/>
</VBox> </VBox>
</ScrollPane> </ScrollPane>
</center> </center>
<bottom> <bottom>
<HBox fx:id="chatInput" styleClass="chat-input" spacing="5.0" style="-fx-padding: 10;" /> <HBox fx:id="chatInput" spacing="5.0" style="-fx-padding: 10;" />
</bottom> </bottom>
</BorderPane> </BorderPane>
</center> </center>