aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-08-15 23:43:52 -0400
committerCara Salter <cara@devcara.com>2022-08-15 23:43:52 -0400
commite6ae01729aeaffc560c59e7887c5743521677e4d (patch)
tree34ea1333a9c0ce85ac72852cd7fd1b85651dda9d
parentf15f93f6e55d6c09b5f556f8fc8e21c29f549a96 (diff)
downloadcmud-e6ae01729aeaffc560c59e7887c5743521677e4d.tar.gz
cmud-e6ae01729aeaffc560c59e7887c5743521677e4d.zip
data work
-rw-r--r--.gitignore3
-rw-r--r--Makefile8
-rw-r--r--README.md5
-rw-r--r--npcs.md0
-rw-r--r--src/data.c131
-rw-r--r--src/data.h15
-rw-r--r--src/game.c36
-rw-r--r--src/game.h36
-rw-r--r--src/login.c20
-rw-r--r--src/main.c5
-rw-r--r--src/server.c18
11 files changed, 262 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index a426513..59998fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -109,3 +109,6 @@ flycheck_*.el
# End of https://www.toptal.com/developers/gitignore/api/c,emacs
cmud*
+data/
+design/
+mud.conf
diff --git a/Makefile b/Makefile
index 9907492..5774cac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
CC=gcc
-CFLAGS=-I. -static
-SRCS=src/main.c src/login.c src/server.c src/data.c src/util.c
+CFLAGS=-I.
+SRCS=src/main.c src/login.c src/server.c src/data.c src/util.c src/game.c
BIN=cmud
-LFLAGS=-largon2 -lconfig
+LFLAGS=-largon2 -lpthread
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
@@ -22,5 +22,7 @@ srcdist: clean
clean:
rm $(BIN)*
+install: main
+
run: dev
./cmud-devel
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8920abe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# CMUD
+
+Experimenting with network programming in C by, how else, building a MUD engine.
+This is a spiritual successor of `~muirrum/hakkardrs`, but that project never
+really got off the ground.
diff --git a/npcs.md b/npcs.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/npcs.md
diff --git a/src/data.c b/src/data.c
index 0d43d3c..8c7ed53 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1,5 +1,6 @@
-#include <asm-generic/errno-base.h>
#define _GNU_SOURCE
+#include <errno.h>
+#include <stdlib.h>
#include "data.h"
#include "login.h"
#include <errno.h>
@@ -8,6 +9,8 @@
#include <sys/stat.h>
#include <unistd.h>
+int deserialize_player(FILE* fp, player_t *plr);
+int serialize_player(player_t* plr, FILE* fp);
int try_make_data_dirs() {
int err = 0;
err = mkdir("data", S_IRWXU);
@@ -43,9 +46,15 @@ int try_load_plr(char *player_name, playerc_t *plr) {
printf("Got fp\n");
- fread(&plr->plr, sizeof(player_t), 1, fp);
+ if (deserialize_player(fp, &plr->plr)) {
+ printf("Couldn't deserialize player\n");
+ return -1;
+ }
} else {
- return 4; // File doesn't exist
+
+ printf("Couldn't open file: %d\n", errno);
+ printf("%s", strerror(errno));
+ return -1;
}
printf("Read file into plr\n");
@@ -75,8 +84,122 @@ int try_write_plr(player_t *plr) {
FILE *fp = fopen(fname, "wb");
- fwrite(&plr, sizeof(player_t), 1, fp);
+ char* buf = malloc(sizeof(player_t) + 1);
+ serialize_player(plr, fp);
+
+ printf("serialized as: %s\n");
+
+ fprintf(fp, "%s", buf);
fclose(fp);
return err;
}
+
+/*
+ * Ugh
+ *
+ * serialize_player takes in a `player_t` struct and a buffer and does some
+ * magic to write out the player in a format that can be easily parsed back
+ * including strings
+ *
+ * because we can't have nice things
+ *
+ * this function is sensitive to player struct updates so if things break but
+ * don't fail to compile this is probably the reason
+ */
+int serialize_player(player_t *plr, FILE* fp) {
+ int err = 0;
+
+ err = fprintf(fp, "%d,%d,%d,%d,%d,%s,%s", plr->xp, plr->hp, plr->max_hp, plr->level, plr->location_id, plr->pw_hash, plr->name);
+
+ return err;
+}
+
+/*
+ * deserialize_player reverses the results of serialize_player.
+ *
+ * because even when we're gay we can't have nice things
+ *
+ * this function is *also* sensitive to player struct updates (no shit) so if
+ * things break but still compile it's probably this thing
+ */
+int deserialize_player(FILE* fp, player_t* plr) {
+ int err = 0;
+
+ if (fp == NULL) {
+ perror("can't open player file");
+ return -1;
+ }
+
+ int c;
+
+ enum ParsePlayerState state = ReadingData;
+ enum ParsePlayerType type = Xp;
+
+ char* buf = malloc(1 << 10);
+ printf("Allocated buf\n");
+
+ while ((c = getc(fp) != EOF)) {
+ if (c == ',') {
+ state = Comma;
+ printf("Found comma");
+ }
+ switch (state) {
+ case ReadingData:
+ strncat(buf, c, 1);
+ break;
+ case Comma:
+ switch (type) {
+ case Xp: ;
+ int xp = atoi(buf);
+ plr->xp = xp;
+ state = ReadingData;
+ type = Hp;
+ memset(buf, 0, strlen(buf));
+ break;
+ case Hp: ;
+ int hp = atoi(buf);
+ plr->hp = hp;
+ state = ReadingData;
+ type = MaxHp;
+ memset(buf, 0, strlen(buf));
+ break;
+ case MaxHp: ;
+ int max_hp = atoi(buf);
+ plr->max_hp = max_hp;
+ state = ReadingData;
+ type = Level;
+ memset(buf, 0, strlen(buf));
+ break;
+ case Level: ;
+ int level = atoi(buf);
+ plr->level = level;
+ state = ReadingData;
+ type = LocationId;
+ memset(buf, 0, strlen(buf));
+ break;
+ case LocationId: ;
+ int location_id = atoi(buf);
+ plr->location_id = location_id;
+ state = ReadingData;
+ type = PwHash;
+ memset(buf, 0, strlen(buf));
+ break;
+ case PwHash: ;
+ plr->pw_hash = malloc(1 << 5);
+ strcpy(plr->pw_hash, buf);
+ state = ReadingData;
+ type = Name;
+ memset(buf, 0, strlen(buf));
+ break;
+ case Name: ;
+ plr->name = malloc(1 << 5);
+ strcpy(plr->name, buf);
+ // we're done here
+ free(buf);
+ return 0;
+ }
+ }
+ }
+ return err;
+}
diff --git a/src/data.h b/src/data.h
index 94bc033..3288b44 100644
--- a/src/data.h
+++ b/src/data.h
@@ -6,4 +6,19 @@ int try_load_plr(char *player_name, playerc_t *conn);
int try_write_plr(player_t *plr);
+enum ParsePlayerState {
+ ReadingData,
+ Comma
+};
+
+enum ParsePlayerType {
+ Hp,
+ MaxHp,
+ Level,
+ Xp,
+ LocationId,
+ PwHash,
+ Name
+};
+
#endif
diff --git a/src/game.c b/src/game.c
new file mode 100644
index 0000000..a5d6ca1
--- /dev/null
+++ b/src/game.c
@@ -0,0 +1,36 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: game.c
+ *
+ * Description: Implementations for the global action request tracker
+ *
+ * Version: 1.0
+ * Created: 01/31/2022 11:59:12 AM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter <cara@devcara.com>,
+ * Organization:
+ *
+ * =====================================================================================
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <threads.h>
+#include "game.h"
+
+static mtx_t queue;
+
+int game_loop() {
+ int err = 0;
+
+ // Initialize mutex
+ err = mtx_init(&queue, mtx_plain);
+ if (err == thrd_error) {
+ perror("initializing mutex");
+ return -1;
+ }
+
+ return err;
+}
diff --git a/src/game.h b/src/game.h
new file mode 100644
index 0000000..2fe6d3d
--- /dev/null
+++ b/src/game.h
@@ -0,0 +1,36 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: game.h
+ *
+ * Description: Types and prototypes for the global action request tracker
+ *
+ * Version: 1.0
+ * Created: 01/31/2022 11:55:50 AM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter <cara@devcara.com>,
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+
+#ifndef _GAME_H
+#define _GAME_H
+
+enum RequestType {
+ Msg,
+ MoveTo,
+ Attack
+};
+
+typedef struct {
+ enum RequestType type;
+ char* args[];
+} Request;
+
+int submit_request(Request req);
+
+#endif
diff --git a/src/login.c b/src/login.c
index 9eba897..b38fdd1 100644
--- a/src/login.c
+++ b/src/login.c
@@ -38,7 +38,7 @@ int step_login(playerc_t *player, int conn_fd) {
for (;;) {
switch (player->state) {
- case LoggedOut: /* the player has yet to log in, this is a fresh connection!
+ case LoggedOut: ; /* the player has yet to log in, this is a fresh connection!
*/
printf("The player is logged out\n");
send_to_fd(player->conn,
@@ -58,16 +58,22 @@ int step_login(playerc_t *player, int conn_fd) {
recv(player->conn, buf, sizeof(buf), 0);
if (buf[0] == 'y') {
player->state = WantMakeAccount;
+ break;
} else if (buf[0] == 'n') {
send_to_fd(player->conn,
"Awww :(. Oh well, hope to see you again soon!\n");
return 4;
}
- continue;
+ break;
} else {
- player->state = LoggedOut;
- continue;
+ player->state = EnterPassword;
+ break;
}
+ case EnterPassword: ;
+ asprintf(&buf, "Welcome back %s! Please enter your password, so we can confirm it.\n", player->plr.name);
+ send_to_fd(player->conn, buf);
+ recv(player->conn, buf, sizeof(buf), 0);
+ break;
case WantMakeAccount:
asprintf(&buf, "Welcome aboard %s! Why don't you start us off by giving me a password.\n", player->plr.name);
send_to_fd(player->conn, buf);
@@ -83,7 +89,7 @@ int step_login(playerc_t *player, int conn_fd) {
send_to_fd(player->conn, "Uhhh, something happened. Try again.");
printf("%d\n", err);
player->state = LoggedOut;
- continue;
+ break;
} else {
send_to_fd(player->conn, "Sounds good! let's drop you into a world!");
player->state = Complete;
@@ -91,10 +97,14 @@ int step_login(playerc_t *player, int conn_fd) {
player->plr.level = 1;
player->plr.xp = 0;
player->plr.location_id = 0;
+ printf("Trying to write player\n");
try_write_plr(&player->plr);
+ printf("Done\n");
player->state = Complete;
}
}
+ case Complete: ;
+ return 0;
}
}
diff --git a/src/main.c b/src/main.c
index 4f848ba..856b1c6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,8 @@
/**
- * Creates a socket for the server
+ * Initializes main game loop and hands off to listeners
* */
#include "server.h"
+#include <stdlib.h>
#include <stdio.h>
/**
@@ -12,9 +13,7 @@
int main() {
int err = 0;
server_t server = {0};
-
err = server_listen(&server);
-
if (err) {
printf("Failed to listen on address");
return err;
diff --git a/src/server.c b/src/server.c
index 68fec90..632cb28 100644
--- a/src/server.c
+++ b/src/server.c
@@ -5,8 +5,15 @@
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <signal.h>
#include <unistd.h>
+static int socket_fd;
+
+void closeServer(int dummy) {
+ shutdown(socket_fd, 2);
+}
+
int server_listen(server_t *server) {
/*
**
@@ -27,10 +34,19 @@ int server_listen(server_t *server) {
struct sockaddr_in server_addr = {0};
+ if (signal(SIGINT, closeServer) == SIG_ERR) {
+ printf("Could not set signal handler\n");
+ return -1;
+ }
+
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8000);
+ if (setsockopt(server->listen_fd, SOL_SOCKET, SO_REUSEADDR,1,sizeof(1))) {
+ printf("Could not set SO_REUSEADDR on server socket, continuing\n");
+ }
+
err = bind(server->listen_fd, (struct sockaddr *)&server_addr,
sizeof(server_addr));
if (err == -1) {
@@ -39,6 +55,8 @@ int server_listen(server_t *server) {
return err;
}
+ socket_fd = server->listen_fd;
+
err = listen(server->listen_fd, 100);
if (err == -1) {
perror("listen");