better map messaging

main
Brett 2023-04-20 17:30:51 -04:00
parent c106cca6b1
commit 941aa58576
5 changed files with 87 additions and 23 deletions

View File

@ -6,7 +6,7 @@ import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
Client gameClient = new Client("localhost");
new Client("localhost");
}
}

View File

@ -53,7 +53,7 @@ public class GameDisplay {
Integer.toString(map.getTownHall().getGoldCapacity()),
Integer.toString(map.getTownHall().getCurrentGold())));
Print.print(resourcesPrinter.createTable(true, false, true));
ArrayList<String> total = new ArrayList<>(resourcesPrinter.createTable(true, false, true));
Print buildingPrinter = new Print("Village Buildings", 2, resourcesPrinter.getWidth());
buildingPrinter.addColumn(new Print.Column("Name"));
@ -65,7 +65,7 @@ public class GameDisplay {
Integer.toString(b.getLevel() + 1),
Integer.toString(b.getHealth())));
Print.print(buildingPrinter.createTable(true, false, true));
total.addAll(buildingPrinter.createTable(true, false, true));
Print inhabs = new Print("Village Inhabitants", 2, buildingPrinter.getWidth());
inhabs.addColumn(new Print.Column("Name"));
@ -74,7 +74,11 @@ public class GameDisplay {
for (Inhabitant i : map.inhabitants)
inhabs.addRow(new Print.Row(i.getClass().getSimpleName(), Integer.toString(i.getLevel() + 1)));
return inhabs.createTable(true, true, true);
total.addAll(inhabs.createTable(true, true, true));
System.out.println(buildingPrinter.getWidth());
System.out.println(resourcesPrinter.getWidth());
System.out.println(inhabs.getWidth());
return total;
}
public void printVillageState(Map map, String displayName) {

View File

@ -22,6 +22,9 @@ public class Client implements Runnable {
private final Map<Long, Message.Sent> sentMessages = Collections.synchronizedMap(new HashMap<>());
private int lastMessageID = 0;
private final InetAddress serverAddress;
private String[] lineBuffer = new String[0];
private int expectedLines = 0;
private int currentLines = 0;
private long ourClientID = 0;
@ -120,7 +123,23 @@ public class Client implements Runnable {
case PacketTable.MESSAGE:
System.out.println(stream.readUTF());
break;
case PacketTable.BEGIN_MAP_DATA:
expectedLines = stream.readInt();
currentLines = 0;
lineBuffer = new String[expectedLines];
break;
case PacketTable.MAP_LINE_DATA:
int lineNumber = stream.readInt();
lineBuffer[lineNumber] = stream.readUTF();
currentLines++;
if (currentLines >= expectedLines) {
for (String line : lineBuffer){
System.out.println(line);
}
}
break;
case PacketTable.DISCONNECT:
System.out.println("Disconnecting!");
running = false;
break;
}

View File

@ -22,7 +22,10 @@ public class PacketTable {
public static final byte TRAIN = 0x6;
// messageHeader, upgrade
public static final byte UPGRADE = 0x7;
// messageHeader, serial packets with map info
public static final byte PRINT_MAP_DATA = 0x8;
// messageHeader
public static final byte PRINT_MAP_DATA = 0x8; // client -> server only!
// messageHeader, line count
public static final byte BEGIN_MAP_DATA = 0x9; // server -> client
// messageHeader, line number (int), UTF8 String (the line)
public static final byte MAP_LINE_DATA = 0xA; // server -> client
}

View File

@ -143,6 +143,9 @@ public class Server implements Runnable {
throw new RuntimeException("A message was acknowledged but does not exist!");
message.acknowledged();
sentMessages.remove(request.getMessageID());
synchronized (sentMessages) {
sentMessages.notifyAll();
}
break;
case PacketTable.MESSAGE:
System.out.println(request.getReader().readUTF());
@ -165,7 +168,7 @@ public class Server implements Runnable {
usingEngine.upgradeBuilding(clientMap, Integer.parseInt(request.getReader().readUTF()));
break;
case PacketTable.PRINT_MAP_DATA:
usingEngine.view.getVillageStateTable(clientMap, "Home Village").forEach(this::sendMessageLn);
sendMapData(usingEngine.view.getVillageStateTable(clientMap, "Home Village"));
break;
}
if (request.getPacketID() != PacketTable.ACK)
@ -187,35 +190,70 @@ public class Server implements Runnable {
}
requestLock.unlock();
ArrayList<Long> removes = new ArrayList<>();
for (HashMap.Entry<Long, Message.Sent> message : sentMessages.entrySet()){
Message.Sent sent = message.getValue();
if (!sent.isAcknowledged() && sent.getTimeSinceSent().get() > MAX_PACKET_ACK_TIME_SECONDS) {
System.out.println("The client did not acknowledge our message, did they receive it?");
sendMessage(sent);
removes.add(message.getKey());
// sentEntries needn't be in the synchronized block
Set<HashMap.Entry<Long, Message.Sent>> sentEntries = sentMessages.entrySet();
synchronized (sentMessages) {
ArrayList<Long> removes = new ArrayList<>();
for (HashMap.Entry<Long, Message.Sent> message : sentEntries) {
Message.Sent sent = message.getValue();
if (!sent.isAcknowledged() && sent.getTimeSinceSent().get() > MAX_PACKET_ACK_TIME_SECONDS) {
System.out.println("The client did not acknowledge our message, did they receive it?");
sendMessage(sent);
removes.add(message.getKey());
}
}
for (Long l : removes)
sentMessages.remove(l);
}
for (Long l : removes)
sentMessages.remove(l);
}
}
private void sendMessageLn(String str) {
private void sendMapData(ArrayList<String> lines) {
final long messageID = ++lastSentMessageID;
Message.Sent beginMapInfoMessage = new Message.Sent(PacketTable.BEGIN_MAP_DATA, clientID, messageID);
try {
beginMapInfoMessage.getWriter().writeInt(lines.size());
sendMessage(beginMapInfoMessage);
} catch (IOException e) {
sendAndLogLn("Unable to send map data: " + e.getMessage());
return;
}
new Thread(() -> {
while (sentMessages.containsKey(messageID)){
try {
synchronized (sentMessages) {
sentMessages.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// once we know that the client is waiting on our map data, we can send it in any order.
for (int i = 0; i < lines.size(); i++){
Message.Sent line = new Message.Sent(PacketTable.MAP_LINE_DATA, clientID, ++lastSentMessageID);
try {
// but we need the line index!
line.getWriter().writeInt(i);
line.getWriter().writeUTF(lines.get(i));
} catch (IOException e){
e.printStackTrace();
}
sendMessage(line);
}
}).start();
}
private void sendAndLogLn(String str){
Message.Sent mess = new Message.Sent(PacketTable.MESSAGE, clientID, ++lastSentMessageID);
try {
mess.getWriter().writeUTF(str + "\n");
sendMessage(mess);
System.out.println(str);
} catch (IOException e){
e.printStackTrace();
}
}
private void sendAndLogLn(String str){
sendMessageLn(str);
System.out.println(str);
}
public void sendMessage(Message.Sent message){
if (message.getPacketID() != PacketTable.ACK)