fix string message sending, added ack to all messages, fix sync issue

main
Brett 2023-04-20 14:56:13 -04:00
parent fc0981852a
commit 24708a2fda
4 changed files with 48 additions and 22 deletions

View File

@ -150,6 +150,8 @@ public class GameEngine {
public synchronized boolean build (Map map, String buildingArg) { public synchronized boolean build (Map map, String buildingArg) {
BuildingFactory bfactory = new BuildingFactory(); BuildingFactory bfactory = new BuildingFactory();
Building type = bfactory.getBuilding(buildingArg); Building type = bfactory.getBuilding(buildingArg);
if (type == null)
return false;
return map.build(new Tile(), type); return map.build(new Tile(), type);
} }

View File

@ -9,35 +9,50 @@ import java.net.DatagramPacket;
import java.net.DatagramSocket; import java.net.DatagramSocket;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
public class Client implements Runnable { public class Client implements Runnable {
private GameDisplay view = new GameDisplay(); private GameDisplay view = new GameDisplay();
private DatagramSocket clientSocket; private DatagramSocket clientSocket;
private boolean running = true; private volatile boolean running = true;
private Thread receiveThread; private Thread receiveThread;
private final HashMap<Long, Message.Sent> sentMessages = new HashMap<>(); private final Map<Long, Message.Sent> sentMessages = Collections.synchronizedMap(new HashMap<>());
private int lastMessageID = 0; private int lastMessageID = 0;
private final InetAddress serverAddress; private final InetAddress serverAddress;
private long ourClientID = 0;
public Client(String address) throws IOException { public Client(String address) throws IOException {
serverAddress = InetAddress.getByName(address); serverAddress = InetAddress.getByName(address);
clientSocket = new DatagramSocket(); clientSocket = new DatagramSocket();
receiveThread = new Thread(this); receiveThread = new Thread(this);
receiveThread.start(); receiveThread.start();
sendMessage(new Message.Sent(PacketTable.CONNECT, 0, ++lastMessageID)); sendMessage(new Message.Sent(PacketTable.CONNECT, ourClientID, ++lastMessageID));
while (running) { while (running) {
String prompt; String prompt;
if ((prompt = view.nextInput()) != null) { if ((prompt = view.nextInput()) != null) {
if (prompt.trim().isEmpty()) if (prompt.trim().isEmpty())
continue; continue;
if (prompt.charAt(0) == '6') if (prompt.charAt(0) == '6') {
running = false;
break; break;
}
view.printGameMenu();
String[] args = prompt.split(" ");
char c = prompt.charAt(0);
if (c > '0' && c < '4') {
if (args.length < 2) {
System.err.println("Args must include type!");
continue;
}
}
byte messageType; byte messageType;
switch (prompt.charAt(0)) { switch (c) {
case '1': case '1':
messageType = PacketTable.BUILD; messageType = PacketTable.BUILD;
break; break;
@ -47,15 +62,16 @@ public class Client implements Runnable {
case '3': case '3':
messageType = PacketTable.UPGRADE; messageType = PacketTable.UPGRADE;
break; break;
case '5':
messageType = PacketTable.PRINT_MAP_DATA;
break;
default: default:
System.err.println("> Invalid command input!"); System.err.println("> Invalid command input!");
return; return;
} }
Message.Sent buildMessage = new Message.Sent(messageType,0,++lastMessageID); Message.Sent buildMessage = new Message.Sent(messageType,ourClientID,++lastMessageID);
buildMessage.getData().write(prompt.substring(1).getBytes()); buildMessage.getWriter().writeUTF(prompt.substring(1));
sendMessage(buildMessage); sendMessage(buildMessage);
view.printGameMenu();
} }
ArrayList<Long> removes = new ArrayList<>(); ArrayList<Long> removes = new ArrayList<>();
for (HashMap.Entry<Long, Message.Sent> message : sentMessages.entrySet()){ for (HashMap.Entry<Long, Message.Sent> message : sentMessages.entrySet()){
@ -89,6 +105,8 @@ public class Client implements Runnable {
switch (packetID) { switch (packetID) {
case PacketTable.ACK: case PacketTable.ACK:
if (ourClientID == 0)
ourClientID = clientID;
Message.Sent message = sentMessages.get(messageID); Message.Sent message = sentMessages.get(messageID);
if (message == null) if (message == null)
throw new RuntimeException("Server acknowledged a message we never sent! (" + messageID + ")"); throw new RuntimeException("Server acknowledged a message we never sent! (" + messageID + ")");
@ -99,11 +117,16 @@ public class Client implements Runnable {
for (HashMap.Entry<Long, Message.Sent> ms : sentMessages.entrySet()) for (HashMap.Entry<Long, Message.Sent> ms : sentMessages.entrySet())
System.out.println("MessageID: " + ms.getKey()); System.out.println("MessageID: " + ms.getKey());
break; break;
case PacketTable.MESSAGE:
System.out.println(stream.readUTF());
break;
case PacketTable.DISCONNECT: case PacketTable.DISCONNECT:
running = false; running = false;
break; break;
} }
if (packetID != PacketTable.ACK && packetID != PacketTable.DISCONNECT){
sendMessage(new Message.Sent(PacketTable.ACK, ourClientID, messageID));
}
} catch (Exception e){ } catch (Exception e){
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -23,6 +23,6 @@ public class PacketTable {
// messageHeader, upgrade // messageHeader, upgrade
public static final byte UPGRADE = 0x7; public static final byte UPGRADE = 0x7;
// messageHeader, serial packets with map info // messageHeader, serial packets with map info
public static final byte USER_MAP_DATA = 0x8; public static final byte PRINT_MAP_DATA = 0x8;
} }

View File

@ -9,10 +9,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.rmi.ServerException; import java.rmi.ServerException;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -55,7 +52,7 @@ public class Server implements Runnable {
long clientID = stream.readLong(); long clientID = stream.readLong();
long messageID = stream.readLong(); long messageID = stream.readLong();
System.out.println("Receiving message with ID " + messageID + " to client: " + clientID + " of type " + packetID); System.out.println("Receiving message with ID " + messageID + " from client: " + clientID + " of type " + packetID);
ConnectedClient client = clients.get(clientID); ConnectedClient client = clients.get(clientID);
@ -67,7 +64,7 @@ public class Server implements Runnable {
continue; continue;
} }
if (client == null) if (client == null)
throw new ServerException("Client disconnected with invalid client id! (" + clientID + ")"); throw new ServerException("Client sent message invalid client id! (" + clientID + ")");
if (packetID == PacketTable.DISCONNECT) { if (packetID == PacketTable.DISCONNECT) {
client.halt(); client.halt();
clients.remove(clientID); clients.remove(clientID);
@ -95,7 +92,7 @@ public class Server implements Runnable {
private final Queue<Message.Received> pendingRequests = new PriorityQueue<>(); private final Queue<Message.Received> pendingRequests = new PriorityQueue<>();
private final ReentrantLock requestLock = new ReentrantLock(); private final ReentrantLock requestLock = new ReentrantLock();
private final AtomicBoolean allowUpdate; private final AtomicBoolean allowUpdate;
private final HashMap<Long, Message.Sent> sentMessages = new HashMap<>(); private final java.util.Map<Long, Message.Sent> sentMessages = Collections.synchronizedMap(new HashMap<>());
private final DatagramSocket serverSocket; private final DatagramSocket serverSocket;
private final long clientID; private final long clientID;
private volatile boolean running = true; private volatile boolean running = true;
@ -148,16 +145,20 @@ public class Server implements Runnable {
System.out.println(request.getReader().readUTF()); System.out.println(request.getReader().readUTF());
break; break;
case PacketTable.BUILD: case PacketTable.BUILD:
usingEngine.build(clientMap,new String(request.getData(), StandardCharsets.UTF_8)); if (usingEngine.build(clientMap, request.getReader().readUTF())){
System.out.println("Client " + clientID + " has built something!");
} else {
System.out.println("Client " + clientID + " failed to build!");
}
break; break;
case PacketTable.TRAIN: case PacketTable.TRAIN:
usingEngine.train(clientMap,new String(request.getData(), StandardCharsets.UTF_8)); usingEngine.train(clientMap, request.getReader().readUTF());
break; break;
case PacketTable.UPGRADE: case PacketTable.UPGRADE:
usingEngine.upgradeBuilding(clientMap, ByteBuffer.wrap(request.getData()).getInt()); usingEngine.upgradeBuilding(clientMap, Integer.parseInt(request.getReader().readUTF()));
break; break;
} }
sendMessage(new Message.Sent(PacketTable.ACK, clientID, request.getMessageID()));
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }