diff options
| author | Cara Salter <cara@devcara.com> | 2022-08-15 23:43:52 -0400 | 
|---|---|---|
| committer | Cara Salter <cara@devcara.com> | 2022-08-15 23:43:52 -0400 | 
| commit | e6ae01729aeaffc560c59e7887c5743521677e4d (patch) | |
| tree | 34ea1333a9c0ce85ac72852cd7fd1b85651dda9d | |
| parent | f15f93f6e55d6c09b5f556f8fc8e21c29f549a96 (diff) | |
| download | cmud-e6ae01729aeaffc560c59e7887c5743521677e4d.tar.gz cmud-e6ae01729aeaffc560c59e7887c5743521677e4d.zip  | |
data work
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | npcs.md | 0 | ||||
| -rw-r--r-- | src/data.c | 131 | ||||
| -rw-r--r-- | src/data.h | 15 | ||||
| -rw-r--r-- | src/game.c | 36 | ||||
| -rw-r--r-- | src/game.h | 36 | ||||
| -rw-r--r-- | src/login.c | 20 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/server.c | 18 | 
11 files changed, 262 insertions, 15 deletions
@@ -109,3 +109,6 @@ flycheck_*.el  # End of https://www.toptal.com/developers/gitignore/api/c,emacs  cmud* +data/ +design/ +mud.conf @@ -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. @@ -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; +} @@ -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;      }    } @@ -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");  | 
