about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorJune McEnroe <programble@gmail.com>2017-07-31 21:30:22 -0400
committerJune McEnroe <programble@gmail.com>2017-07-31 21:30:22 -0400
commite2e97511e8b3ff819274b8ea802e20a41e50858f (patch)
treef9e2c129e18da878366385965ae5c8d9df6e1cd9
parentPerform enter as two moves rather than a loop (diff)
downloadtorus-e2e97511e8b3ff819274b8ea802e20a41e50858f.tar.gz
torus-e2e97511e8b3ff819274b8ea802e20a41e50858f.zip
Show other clients' cursors
Also unfuck removing on send failure.
-rwxr-xr-xclient.c20
-rwxr-xr-xserver.c118
-rw-r--r--torus.h9
3 files changed, 109 insertions, 38 deletions
diff --git a/client.c b/client.c
index 4eb726b..d77aeb7 100755
--- a/client.c
+++ b/client.c
@@ -245,6 +245,17 @@ static void serverTile(void) {
     }
 }
 
+static void serverCursor(uint8_t oldX, uint8_t oldY, uint8_t newX, uint8_t newY) {
+    if (oldX != CURSOR_NONE) {
+        move(oldY, oldX);
+        addch(inch() & ~A_REVERSE);
+    }
+    if (newX != CURSOR_NONE) {
+        move(newY, newX);
+        addch(inch() | A_REVERSE);
+    }
+}
+
 static void readMessage(void) {
     struct ServerMessage msg;
     ssize_t len = recv(client, &msg, sizeof(msg), 0);
@@ -273,6 +284,15 @@ static void readMessage(void) {
             );
             break;
 
+        case SERVER_CURSOR:
+            serverCursor(
+                msg.data.c.oldCellX,
+                msg.data.c.oldCellY,
+                msg.data.c.newCellX,
+                msg.data.c.newCellY
+            );
+            break;
+
         default:
             errx(EX_PROTOCOL, "I don't know what %d means!", msg.type);
     }
diff --git a/server.c b/server.c
index 46f4c06..b88c386 100755
--- a/server.c
+++ b/server.c
@@ -82,52 +82,66 @@ static struct Client *clientAdd(int fd) {
     return client;
 }
 
-static void clientRemove(struct Client *client) {
-    if (client->prev) client->prev->next = client->next;
-    if (client->next) client->next->prev = client->prev;
-    if (clientHead == client) clientHead = client->next;
-    close(client->fd);
-    free(client);
-}
+static void clientRemove(struct Client *client);
 
-static bool clientSend(struct Client *client, const struct ServerMessage *msg) {
+static bool clientSend(const struct Client *client, const struct ServerMessage *msg) {
     ssize_t len = send(client->fd, msg, sizeof(*msg), 0);
-    if (len < 0) {
-        clientRemove(client);
-        return false;
-    }
+    if (len < 0) return false;
 
     if (msg->type == SERVER_TILE) {
         struct Tile *tile = tileGet(client->tileX, client->tileY);
         len = send(client->fd, tile, sizeof(*tile), 0);
-        if (len < 0) {
-            clientRemove(client);
-            return false;
-        }
+        if (len < 0) return false;
     }
 
     return true;
 }
 
-static bool clientCast(struct Client *origin, const struct ServerMessage *msg) {
-    uint32_t tileX = origin->tileX;
-    uint32_t tileY = origin->tileY;
-
-    bool success = clientSend(origin, msg);
-
+static void clientCast(const struct Client *origin, const struct ServerMessage *msg) {
     for (struct Client *client = clientHead; client; client = client->next) {
         if (client == origin) continue;
-        if (client->tileX != tileX) continue;
-        if (client->tileY != tileY) continue;
+        if (client->tileX != origin->tileX) continue;
+        if (client->tileY != origin->tileY) continue;
 
-        struct Client *next = client->next;
         if (!clientSend(client, msg)) {
-            client = next;
+            client = client->next;
+            clientRemove(client);
             if (!client) break;
         }
     }
+}
 
-    return success;
+static void clientRemove(struct Client *client) {
+    if (client->prev) client->prev->next = client->next;
+    if (client->next) client->next->prev = client->prev;
+    if (clientHead == client) clientHead = client->next;
+
+    struct ServerMessage msg = { .type = SERVER_CURSOR };
+    msg.data.c.oldCellX = client->cellX;
+    msg.data.c.oldCellY = client->cellY;
+    msg.data.c.newCellX = CURSOR_NONE;
+    msg.data.c.newCellX = CURSOR_NONE;
+    clientCast(client, &msg);
+
+    close(client->fd);
+    free(client);
+}
+
+static bool clientCursors(const struct Client *client) {
+    struct ServerMessage msg = { .type = SERVER_CURSOR };
+    msg.data.c.oldCellX = CURSOR_NONE;
+    msg.data.c.oldCellY = CURSOR_NONE;
+
+    for (struct Client *friend = clientHead; friend; friend = friend->next) {
+        if (friend == client) continue;
+        if (friend->tileX != client->tileX) continue;
+        if (friend->tileY != client->tileY) continue;
+
+        msg.data.c.newCellX = friend->cellX;
+        msg.data.c.newCellY = friend->cellY;
+        if (!clientSend(client, &msg)) return false;
+    }
+    return true;
 }
 
 static bool clientMove(struct Client *client, int8_t dx, int8_t dy) {
@@ -158,13 +172,35 @@ static bool clientMove(struct Client *client, int8_t dx, int8_t dy) {
 
     if (client->tileX != old.tileX || client->tileY != old.tileY) {
         msg.type = SERVER_TILE;
-        return clientSend(client, &msg);
+        if (!clientSend(client, &msg)) return false;
+        if (!clientCursors(client)) return false;
+
+        msg.type = SERVER_CURSOR;
+        msg.data.c.oldCellX = old.cellX;
+        msg.data.c.oldCellY = old.cellY;
+        msg.data.c.newCellX = CURSOR_NONE;
+        msg.data.c.newCellX = CURSOR_NONE;
+        clientCast(&old, &msg);
+
+        msg.data.c.oldCellX = CURSOR_NONE;
+        msg.data.c.oldCellY = CURSOR_NONE;
+        msg.data.c.newCellX = client->cellX;
+        msg.data.c.newCellY = client->cellY;
+        clientCast(client, &msg);
+
+    } else {
+        msg.type = SERVER_CURSOR;
+        msg.data.c.oldCellX = old.cellX;
+        msg.data.c.oldCellY = old.cellY;
+        msg.data.c.newCellX = client->cellX;
+        msg.data.c.newCellY = client->cellY;
+        clientCast(client, &msg);
     }
 
     return true;
 }
 
-static bool clientPut(struct Client *client, uint8_t color, char cell) {
+static bool clientPut(const struct Client *client, uint8_t color, char cell) {
     struct Tile *tile = tileGet(client->tileX, client->tileY);
     tile->colors[client->cellY][client->cellX] = color;
     tile->cells[client->cellY][client->cellX] = cell;
@@ -174,7 +210,10 @@ static bool clientPut(struct Client *client, uint8_t color, char cell) {
     msg.data.p.cellY = client->cellY;
     msg.data.p.color = color;
     msg.data.p.cell = cell;
-    return clientCast(client, &msg);
+
+    bool success = clientSend(client, &msg);
+    clientCast(client, &msg);
+    return success;
 }
 
 int main() {
@@ -238,8 +277,13 @@ int main() {
             if (nevents < 0) err(EX_OSERR, "kevent");
 
             struct ServerMessage msg = { .type = SERVER_TILE };
-            if (!clientSend(client, &msg)) continue;
-            clientMove(client, 0, 0);
+            if (
+                !clientSend(client, &msg) ||
+                !clientMove(client, 0, 0) ||
+                !clientCursors(client)
+            ) {
+                clientRemove(client);
+            }
 
             continue;
         }
@@ -257,17 +301,15 @@ int main() {
             continue;
         }
 
+        bool success = false;
         switch (msg.type) {
             case CLIENT_MOVE:
-                clientMove(client, msg.data.m.dx, msg.data.m.dy);
+                success = clientMove(client, msg.data.m.dx, msg.data.m.dy);
                 break;
-
             case CLIENT_PUT:
-                clientPut(client, msg.data.p.color, msg.data.p.cell);
+                success = clientPut(client, msg.data.p.color, msg.data.p.cell);
                 break;
-
-            default:
-                clientRemove(client);
         }
+        if (!success) clientRemove(client);
     }
 }
diff --git a/torus.h b/torus.h
index ff9c0e8..9158ef7 100644
--- a/torus.h
+++ b/torus.h
@@ -47,6 +47,7 @@ enum ServerMessageType {
     SERVER_TILE,
     SERVER_MOVE,
     SERVER_PUT,
+    SERVER_CURSOR,
 };
 
 struct ServerMessage {
@@ -62,9 +63,17 @@ struct ServerMessage {
             uint8_t color;
             char cell;
         } p;
+        struct {
+            uint8_t oldCellX;
+            uint8_t oldCellY;
+            uint8_t newCellX;
+            uint8_t newCellY;
+        } c;
     } data;
 };
 
+#define CURSOR_NONE UINT8_MAX
+
 enum ClientMessageType {
     CLIENT_MOVE,
     CLIENT_PUT,