From 0b6b33721ba810ca5846943cf53c5e4dabd19332 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 8 Jun 2025 14:38:22 -0500 Subject: [PATCH] Prog --- lib/CMakeLists.txt | 10 +- src/CMakeLists.txt | 7 +- src/assert/assert.c | 6 - src/assert/assert.h | 13 - src/console/CMakeLists.txt | 12 - src/console/console.c | 395 ------------------ src/console/console.h | 114 ----- src/console/consolecmd.c | 27 -- src/console/consolecmd.h | 39 -- src/console/consoledefs.h | 21 - src/console/consolevar.c | 64 --- src/console/consolevar.h | 65 --- src/display/CMakeLists.txt | 4 +- src/display/render.c | 26 +- src/display/render.h | 29 +- src/dusk.h | 2 - src/error/error.c | 56 --- src/error/error.h | 60 --- src/game/direction.h | 20 - src/game/entity/entity.c | 78 ---- src/game/entity/entity.h | 39 -- src/game/game.c | 18 - src/game/game.h | 25 -- src/input.c | 58 --- src/input.h | 72 +--- src/main.c | 59 +-- src/network/CMakeLists.txt | 11 - src/network/client/CMakeLists.txt | 12 - src/network/client/client.c | 96 ----- src/network/client/client.h | 117 ------ src/network/client/networkclient.h | 24 -- src/network/packet/CMakeLists.txt | 14 - src/network/packet/packet.c | 84 ---- src/network/packet/packet.h | 80 ---- src/network/packet/packetdisconnect.c | 52 --- src/network/packet/packetdisconnect.h | 43 -- src/network/packet/packetping.c | 53 --- src/network/packet/packetping.h | 44 -- src/network/packet/packetqueue.c | 86 ---- src/network/packet/packetqueue.h | 60 --- src/network/packet/packetwelcome.c | 40 -- src/network/packet/packetwelcome.h | 35 -- src/network/server/CMakeLists.txt | 15 - src/network/server/networked/CMakeLists.txt | 11 - .../server/networked/networkedserver.c | 224 ---------- .../server/networked/networkedserver.h | 56 --- .../server/networked/networkedserverclient.c | 382 ----------------- .../server/networked/networkedserverclient.h | 111 ----- src/network/server/server.c | 127 ------ src/network/server/server.h | 93 ----- src/network/server/serverclient.c | 79 ---- src/network/server/serverclient.h | 64 --- src/{game => rpg}/CMakeLists.txt | 5 +- src/{game => rpg}/entity/CMakeLists.txt | 1 + src/rpg/entity/entity.c | 34 ++ src/rpg/entity/entity.h | 54 +++ src/rpg/entity/player.c | 14 + src/rpg/entity/player.h | 22 + src/{game/map/map.h => rpg/event/event.h} | 5 +- src/{error => rpg/item}/CMakeLists.txt | 2 +- src/rpg/item/item.h | 9 + src/rpg/item/itemtype.c | 22 + src/rpg/item/itemtype.h | 30 ++ .../singleplayer => rpg/quest}/CMakeLists.txt | 1 + .../networkclient.c => rpg/quest/quest.c} | 2 +- .../packet/packetbase.h => rpg/quest/quest.h} | 8 +- src/util/memory.c | 11 - src/util/random.c | 15 - src/util/random.h | 27 +- 69 files changed, 210 insertions(+), 3384 deletions(-) delete mode 100644 src/console/CMakeLists.txt delete mode 100644 src/console/console.c delete mode 100644 src/console/console.h delete mode 100644 src/console/consolecmd.c delete mode 100644 src/console/consolecmd.h delete mode 100644 src/console/consoledefs.h delete mode 100644 src/console/consolevar.c delete mode 100644 src/console/consolevar.h delete mode 100644 src/error/error.c delete mode 100644 src/error/error.h delete mode 100644 src/game/direction.h delete mode 100644 src/game/entity/entity.c delete mode 100644 src/game/entity/entity.h delete mode 100644 src/game/game.c delete mode 100644 src/game/game.h delete mode 100644 src/network/CMakeLists.txt delete mode 100644 src/network/client/CMakeLists.txt delete mode 100644 src/network/client/client.c delete mode 100644 src/network/client/client.h delete mode 100644 src/network/client/networkclient.h delete mode 100644 src/network/packet/CMakeLists.txt delete mode 100644 src/network/packet/packet.c delete mode 100644 src/network/packet/packet.h delete mode 100644 src/network/packet/packetdisconnect.c delete mode 100644 src/network/packet/packetdisconnect.h delete mode 100644 src/network/packet/packetping.c delete mode 100644 src/network/packet/packetping.h delete mode 100644 src/network/packet/packetqueue.c delete mode 100644 src/network/packet/packetqueue.h delete mode 100644 src/network/packet/packetwelcome.c delete mode 100644 src/network/packet/packetwelcome.h delete mode 100644 src/network/server/CMakeLists.txt delete mode 100644 src/network/server/networked/CMakeLists.txt delete mode 100644 src/network/server/networked/networkedserver.c delete mode 100644 src/network/server/networked/networkedserver.h delete mode 100644 src/network/server/networked/networkedserverclient.c delete mode 100644 src/network/server/networked/networkedserverclient.h delete mode 100644 src/network/server/server.c delete mode 100644 src/network/server/server.h delete mode 100644 src/network/server/serverclient.c delete mode 100644 src/network/server/serverclient.h rename src/{game => rpg}/CMakeLists.txt (73%) rename src/{game => rpg}/entity/CMakeLists.txt (93%) create mode 100644 src/rpg/entity/entity.c create mode 100644 src/rpg/entity/entity.h create mode 100644 src/rpg/entity/player.c create mode 100644 src/rpg/entity/player.h rename src/{game/map/map.h => rpg/event/event.h} (79%) rename src/{error => rpg/item}/CMakeLists.txt (92%) create mode 100644 src/rpg/item/item.h create mode 100644 src/rpg/item/itemtype.c create mode 100644 src/rpg/item/itemtype.h rename src/{network/server/singleplayer => rpg/quest}/CMakeLists.txt (93%) rename src/{network/client/networkclient.c => rpg/quest/quest.c} (84%) rename src/{network/packet/packetbase.h => rpg/quest/quest.h} (53%) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 19d1276..2737231 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,12 +3,4 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -include(FetchContent) - -# RayLib -FetchContent_Declare( - raylib - URL https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz - URL_HASH MD5=61638c4c2c097fbca1d6a71e4da36c16 -) -FetchContent_MakeAvailable(raylib) \ No newline at end of file +include(FetchContent) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3827960..223985a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,6 @@ target_link_libraries(${DUSK_TARGET_NAME} PUBLIC m - raylib ) # Includes @@ -20,14 +19,10 @@ target_include_directories(${DUSK_TARGET_NAME} target_sources(${DUSK_TARGET_NAME} PRIVATE main.c - input.c ) # Subdirs add_subdirectory(assert) -add_subdirectory(console) add_subdirectory(display) -add_subdirectory(error) -add_subdirectory(game) -add_subdirectory(network) +add_subdirectory(rpg) add_subdirectory(util) \ No newline at end of file diff --git a/src/assert/assert.c b/src/assert/assert.c index 6873b46..77bade8 100644 --- a/src/assert/assert.c +++ b/src/assert/assert.c @@ -7,12 +7,6 @@ #include "assert.h" -pthread_t assertMainThread = 0; - -void assertInit() { - assertMainThread = pthread_self(); -} - void assertTrueImpl( const char *file, const int32_t line, diff --git a/src/assert/assert.h b/src/assert/assert.h index 3b4232f..56b8668 100644 --- a/src/assert/assert.h +++ b/src/assert/assert.h @@ -8,13 +8,6 @@ #pragma once #include "dusk.h" -extern pthread_t assertMainThread; - -/** - * Initialises the assert system. - */ -void assertInit(); - /** * Assert a given value to be true. * @@ -135,10 +128,4 @@ void assertMemoryRangeMatchesImpl( #define assertStrLenMin(str, len, message) \ assertTrue(strlen(str) >= len, message) -#define assertIsMainThread(message) \ - assertTrue(pthread_self() == assertMainThread, message) - -#define assertNotMainThread(message) \ - assertFalse(pthread_self() == assertMainThread, message) - // EOF \ No newline at end of file diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt deleted file mode 100644 index c4da6c5..0000000 --- a/src/console/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - console.c - consolecmd.c - consolevar.c -) \ No newline at end of file diff --git a/src/console/console.c b/src/console/console.c deleted file mode 100644 index d43df5d..0000000 --- a/src/console/console.c +++ /dev/null @@ -1,395 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "console.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "input.h" - -console_t CONSOLE; - -void consoleInit() { - memoryZero(&CONSOLE, sizeof(console_t)); - pthread_mutex_init(&CONSOLE.lock, NULL); // Initialize the mutex - - // Register the get and set command. - CONSOLE.cmdGet = consoleRegCmd("get", cmdGet); - CONSOLE.cmdSet = consoleRegCmd("set", cmdSet); - consoleRegCmd("echo", cmdEcho); - - consolePrint(" = Dawn Console = "); -} - -consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) { - pthread_mutex_lock(&CONSOLE.lock); // Lock - consolecmd_t *cmd = &CONSOLE.commands[CONSOLE.commandCount++]; - consoleCmdInit(cmd, name, function); - pthread_mutex_unlock(&CONSOLE.lock); // Unlock - return cmd; -} - -consolevar_t * consoleRegVar( - const char_t *name, - const char_t *value, - consolevarchanged_t event -) { - pthread_mutex_lock(&CONSOLE.lock); // Lock - consolevar_t *var = &CONSOLE.variables[CONSOLE.variableCount++]; - consoleVarInitListener(var, name, value, event); - pthread_mutex_unlock(&CONSOLE.lock); // Unlock - return var; -} - -void consolePrint(const char_t *message, ...) { - char_t buffer[CONSOLE_LINE_MAX]; - - va_list args; - va_start(args, message); - int32_t len = stringFormatVA(buffer, CONSOLE_LINE_MAX, message, args); - va_end(args); - - // Move all lines back - memoryMove( - CONSOLE.line[0], - CONSOLE.line[1], - (CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX - ); - - // Copy the new line - memoryCopy( - CONSOLE.line[CONSOLE_HISTORY_MAX - 1], - buffer, - len + 1 - ); - printf("%s\n", buffer); -} - -void consoleExec(const char_t *line) { - pthread_mutex_lock(&CONSOLE.lock); // Lock - assertNotNull(line, "line must not be NULL"); - assertTrue( - CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, - "Too many commands in the buffer." - ); - - char_t buffer[CONSOLE_LINE_MAX]; - size_t i = 0, j = 0; - char_t c; - consoleexecstate_t state = CONSOLE_EXEC_STATE_INITIAL; - consolecmdexec_t *exec = NULL; - - while(state != CONSOLE_EXEC_STATE_FULLY_PARSED) { - c = line[i]; - - switch(state) { - case CONSOLE_EXEC_STATE_INITIAL: - assertTrue(j == 0, "Buffer not empty?"); - - if(c == '\0') { - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - break; - } - - if(stringIsWhitespace(c) || c == ';') { - i++; - continue; - } - - state = CONSOLE_EXEC_STATE_PARSE_CMD; - break; - - case CONSOLE_EXEC_STATE_PARSE_CMD: - if(stringIsWhitespace(c) || c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_CMD_PARSED; - continue; - } - - if(c == '"') { - // Can't handle quotes within the command. - consolePrint("Invalid command"); - while(c != '\0' && c != ';') c = line[++i]; - continue; - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - consolePrint("Command too long"); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_CMD_PARSED: - if(j == 0) { - state = CONSOLE_EXEC_STATE_INITIAL; - continue; - } - - // Create exec - assertNull(exec, "Existing command parsing?"); - - exec = &CONSOLE.execBuffer[CONSOLE.execBufferCount]; - memoryZero(exec, sizeof(consolecmdexec_t)); - - buffer[j] = '\0'; - stringCopy(exec->command, buffer, CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FIND_ARG; - - j = 0;// Free up buffer - break; - - case CONSOLE_EXEC_STATE_FIND_ARG: - if(c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_CMD_FINISHED; - continue; - } - - if(stringIsWhitespace(c)) { - i++; - continue; - } - - if(c == '"') { - state = CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED; - i++; - } else { - state = CONSOLE_EXEC_STATE_PARSE_ARG; - } - break; - - case CONSOLE_EXEC_STATE_PARSE_ARG: - if(stringIsWhitespace(c) || c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_ARG_PARSED; - continue; - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - consolePrint("Arg too long"); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED: - if(c == '"') { - state = CONSOLE_EXEC_STATE_ARG_PARSED; - i++; - continue; - } - - if(c == '\0' || c == ';') { - consolePrint("Unterminated quote"); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - - if(c == '\\') { - c = line[++i]; - - if(c == '\0' || c == ';') { - consolePrint("Unterminated quote"); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - consolePrint("Arg too long"); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_ARG_PARSED: - buffer[j] = '\0'; - stringCopy(exec->argv[exec->argc++], buffer, CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FIND_ARG; - j = 0;// Free up buffer - break; - - case CONSOLE_EXEC_STATE_CMD_FINISHED: - assertNotNull(exec, "No command found?"); - - // Now, is there a command that matches? - for(uint32_t k = 0; k < CONSOLE.commandCount; k++) { - consolecmd_t *cmd = &CONSOLE.commands[k]; - if(stringCompare(cmd->name, exec->command) != 0) continue; - exec->cmd = cmd; - break; - } - - if(exec->cmd == NULL) { - // Command wasn't found, is there a variable that matches? - for(uint32_t k = 0; k < CONSOLE.variableCount; k++) { - consolevar_t *var = &CONSOLE.variables[k]; - if(stringCompare(var->name, exec->command) != 0) continue; - - // Matching variable found, is this a GET or a SET? - if(exec->argc == 0) { - exec->cmd = CONSOLE.cmdGet; - stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); - exec->argc = 1; - } else { - exec->cmd = CONSOLE.cmdSet; - stringCopy(exec->argv[1], exec->argv[0], CONSOLE_LINE_MAX); - stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); - exec->argc = 2; - } - break; - } - - if(exec->cmd == NULL) { - consolePrint("Command not found", exec->command); - exec = NULL; - state = CONSOLE_EXEC_STATE_INITIAL; - break; - } - } - - // Prep for next command. - exec = NULL; - state = CONSOLE_EXEC_STATE_INITIAL; - CONSOLE.execBufferCount++; - break; - - default: - assertUnreachable("Invalid state."); - break; - } - } - - pthread_mutex_unlock(&CONSOLE.lock); // Unlock -} - -void consoleProcess() { - pthread_mutex_lock(&CONSOLE.lock); // Lock - for(uint32_t i = 0; i < CONSOLE.execBufferCount; i++) { - consolecmdexec_t *exec = &CONSOLE.execBuffer[i]; - - assertNotNull(exec->cmd, "Command execution has no command."); - - exec->cmd->function(exec); - } - - // Clear the exec buffer - CONSOLE.execBufferCount = 0; - pthread_mutex_unlock(&CONSOLE.lock); // Unlock -} - -void cmdGet(const consolecmdexec_t *exec) { - assertTrue( - exec->argc >= 1, - "Get command requires 1 argument." - ); - - for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { - consolevar_t *var = &CONSOLE.variables[i]; - if(stringCompare(var->name, exec->argv[0]) != 0) continue; - consolePrint("%s", var->value); - return; - } - - consolePrint("Error: Variable '%s' not found.", exec->argv[0]); -} - -void cmdSet(const consolecmdexec_t *exec) { - assertTrue(exec->argc >= 2, "set command requires 2 arguments."); - - for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { - consolevar_t *var = &CONSOLE.variables[i]; - if(stringCompare(var->name, exec->argv[0]) != 0) continue; - consoleVarSetValue(var, exec->argv[1]); - consolePrint("%s %s", var->name, var->value); - for(i = 0; i < var->eventCount; i++) { - assertNotNull(var->events[i], "Event is NULL"); - var->events[i](var); - } - return; - } - - consolePrint("Error: Variable '%s' not found.", exec->argv[0]); -} - -void cmdEcho(const consolecmdexec_t *exec) { - assertTrue( - exec->argc >= 1, - "echo command requires 1 argument." - ); - - consolePrint("%s", exec->argv[0]); -} - -// May move these later -void consoleUpdate() { - if(inputIsPressed(INPUT_TOGGLE_CONSOLE)) { - CONSOLE.open = !CONSOLE.open; - } else if(CONSOLE.open) { - switch(INPUT.keyPressed) { - case 0: - break; - - case KEY_ENTER: - consoleExec(CONSOLE.inputBuffer); - CONSOLE.inputIndex = 0; - CONSOLE.inputBuffer[0] = '\0'; - break; - - case KEY_BACKSPACE: - if(CONSOLE.inputIndex > 0) { - CONSOLE.inputIndex--; - CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; - } - break; - - default: - if( - INPUT.keyPressed >= 32 && - INPUT.keyPressed <= 126 && - CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1 - ) { - CONSOLE.inputBuffer[CONSOLE.inputIndex++] = INPUT.charPressed; - CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; - } - break; - } - } - - consoleProcess(); -} - -void consoleDraw() { - if(!CONSOLE.open) return; - - size_t i = 0; - char_t *line; - int32_t fontSize = 10; - do { - line = CONSOLE.line[i]; - if(line[0] == '\0') { - i++; - continue; - } - DrawText(line, 0, i*fontSize, fontSize, YELLOW); - i++; - } while(i < CONSOLE_HISTORY_MAX); - - DrawText( - CONSOLE.inputBuffer, 0, - (CONSOLE_HISTORY_MAX + 1) * fontSize, - fontSize, - PINK - ); -} \ No newline at end of file diff --git a/src/console/console.h b/src/console/console.h deleted file mode 100644 index 59ee0e8..0000000 --- a/src/console/console.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "consolevar.h" -#include "consolecmd.h" - -typedef enum { - CONSOLE_EXEC_STATE_INITIAL, - CONSOLE_EXEC_STATE_PARSE_CMD, - CONSOLE_EXEC_STATE_CMD_PARSED, - - CONSOLE_EXEC_STATE_FIND_ARG, - CONSOLE_EXEC_STATE_PARSE_ARG, - CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED, - CONSOLE_EXEC_STATE_ARG_PARSED, - - CONSOLE_EXEC_STATE_CMD_FINISHED, - CONSOLE_EXEC_STATE_FULLY_PARSED -} consoleexecstate_t; - -typedef struct { - consolecmd_t commands[CONSOLE_COMMANDS_MAX]; - uint32_t commandCount; - - consolevar_t variables[CONSOLE_VARIABLES_MAX]; - uint32_t variableCount; - - char_t line[CONSOLE_HISTORY_MAX][CONSOLE_LINE_MAX]; - - consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX]; - uint32_t execBufferCount; - - consolecmd_t *cmdGet; - consolecmd_t *cmdSet; - pthread_mutex_t lock; // Mutex for thread safety - - // May move these later - char_t inputBuffer[CONSOLE_LINE_MAX]; - int32_t inputIndex; - - bool_t open; -} console_t; - -extern console_t CONSOLE; - -/** - * Initializes the console. - */ -void consoleInit(); - -/** - * Registers a console command. - * - * @param name The name of the command. - * @param function The function to execute when the command is called. - * @return The registered command. - */ -consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function); - -/** - * Registers a console variable. - * - * @param name The name of the variable. - * @param value The initial value of the variable. - * @param event The event to register. - * @return The registered variable. - */ -consolevar_t * consoleRegVar( - const char_t *name, - const char_t *value, - consolevarchanged_t event -); - -/** - * Sets the value of a console variable. - * - * @param name The name of the variable. - * @param value The new value of the variable. - */ -void consolePrint( - const char_t *message, - ... -); - -/** - * Executes a console command. - * - * @param line The line to execute. - */ -void consoleExec(const char_t *line); - -/** - * Processes the console's pending commands. - */ -void consoleProcess(); - -/** - * Updates the console's input buffer and handles user input. - */ -void consoleUpdate(); - -/** - * Draws the console's output. - */ -void consoleDraw(); - -void cmdGet(const consolecmdexec_t *exec); -void cmdSet(const consolecmdexec_t *exec); -void cmdEcho(const consolecmdexec_t *exec); \ No newline at end of file diff --git a/src/console/consolecmd.c b/src/console/consolecmd.c deleted file mode 100644 index f2923b9..0000000 --- a/src/console/consolecmd.c +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "consolecmd.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" - -void consoleCmdInit( - consolecmd_t *cmd, - const char_t *name, - consolecmdfunc_t function -) { - assertNotNull(cmd, "Command is NULL."); - assertNotNull(name, "Name is NULL."); - assertNotNull(function, "Function is NULL."); - assertStrLenMin(name, 1, "Name is empty."); - assertStrLenMax(name, CONSOLE_CMD_NAME_MAX, "Name is too long."); - - memoryZero(cmd, sizeof(consolecmd_t)); - stringCopy(cmd->name, name, CONSOLE_CMD_NAME_MAX); - cmd->function = function; -} \ No newline at end of file diff --git a/src/console/consolecmd.h b/src/console/consolecmd.h deleted file mode 100644 index 09a3c4f..0000000 --- a/src/console/consolecmd.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "consoledefs.h" - -typedef struct consolecmd_s consolecmd_t; - -typedef struct { - consolecmd_t *cmd; - char_t command[CONSOLE_LINE_MAX]; - char_t argv[CONSOLE_CMD_ARGC_MAX][CONSOLE_LINE_MAX]; - uint32_t argc; -} consolecmdexec_t; - -typedef void (*consolecmdfunc_t)(const consolecmdexec_t *exec); - -typedef struct consolecmd_s { - char_t name[CONSOLE_CMD_NAME_MAX]; - consolecmdfunc_t function; -} consolecmd_t; - -/** - * Initializes a console command. - * - * @param cmd Pointer to the console command. - * @param name The name of the command. - * @param function The function to execute when the command is called. - */ -void consoleCmdInit( - consolecmd_t *cmd, - const char_t *name, - consolecmdfunc_t function -); \ No newline at end of file diff --git a/src/console/consoledefs.h b/src/console/consoledefs.h deleted file mode 100644 index 6e6df0d..0000000 --- a/src/console/consoledefs.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once - -#define CONSOLE_CMD_NAME_MAX 32 -#define CONSOLE_CMD_ARGC_MAX 16 - -#define CONSOLE_COMMANDS_MAX 128 -#define CONSOLE_VARIABLES_MAX 128 -#define CONSOLE_LINE_MAX 256 -#define CONSOLE_HISTORY_MAX 32 -#define CONSOLE_EXEC_BUFFER_MAX 16 - -#define CONSOLE_VAR_NAME_MAX 32 -#define CONSOLE_VAR_VALUE_MAX 128 -#define CONSOLE_VAR_EVENTS_MAX 8 \ No newline at end of file diff --git a/src/console/consolevar.c b/src/console/consolevar.c deleted file mode 100644 index e126c89..0000000 --- a/src/console/consolevar.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "consolevar.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" - -void consoleVarInit( - consolevar_t *var, - const char_t *name, - const char_t *value -) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(name, "name must not be NULL"); - assertNotNull(value, "value must not be NULL"); - - assertStrLenMin(name, 1, "name must not be empty"); - assertStrLenMax(name, CONSOLE_VAR_NAME_MAX, "name is too long"); - assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); - - memoryZero(var, sizeof(consolevar_t)); - stringCopy(var->name, name, CONSOLE_VAR_NAME_MAX); - stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); -} - -void consoleVarInitListener( - consolevar_t *var, - const char_t *name, - const char_t *value, - consolevarchanged_t event -) { - consoleVarInit(var, name, value); - if(event) consoleVarListen(var, event); -} - -void consoleVarSetValue(consolevar_t *var, const char_t *value) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(value, "value must not be NULL"); - assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); - - stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); - - uint8_t i = 0; - while (i < var->eventCount) { - var->events[i](var); - i++; - } -} - -void consoleVarListen(consolevar_t *var, consolevarchanged_t event) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(event, "event must not be NULL"); - assertTrue( - var->eventCount < CONSOLE_VAR_EVENTS_MAX, - "Event count is too high" - ); - var->events[var->eventCount++] = event; -} - diff --git a/src/console/consolevar.h b/src/console/consolevar.h deleted file mode 100644 index af6a9df..0000000 --- a/src/console/consolevar.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "consoledefs.h" - -typedef struct consolevar_s consolevar_t; - -typedef void (*consolevarchanged_t)(const consolevar_t *var); - -typedef struct consolevar_s { - char_t name[CONSOLE_VAR_NAME_MAX]; - char_t value[CONSOLE_VAR_VALUE_MAX]; - consolevarchanged_t events[CONSOLE_VAR_EVENTS_MAX]; - uint8_t eventCount; -} consolevar_t; - -/** - * Initializes a console variable. - * - * @param var Pointer to the console variable. - * @param name The name of the variable. - * @param value The initial value of the variable. - */ -void consoleVarInit( - consolevar_t *var, - const char_t *name, - const char_t *value -); - -/** - * Initializes a console variable with a listener. - * - * @param var Pointer to the console variable. - * @param name The name of the variable. - * @param value The initial value of the variable. - * @param event The event to register. - */ -void consoleVarInitListener( - consolevar_t *var, - const char_t *name, - const char_t *value, - consolevarchanged_t event -); - -/** - * Sets the value of a console variable. - * - * @param var Pointer to the console variable. - * @param value The new value of the variable. - */ -void consoleVarSetValue(consolevar_t *var, const char_t *value); - -/** - * Registers an event to be called when the value of a console variable changes. - * - * @param var Pointer to the console variable. - * @param event The event to register. - */ -void consoleVarListen(consolevar_t *var, consolevarchanged_t event); \ No newline at end of file diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index 7d676c7..b354f11 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -7,6 +7,4 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE render.c -) - -# Subdirs \ No newline at end of file +) \ No newline at end of file diff --git a/src/display/render.c b/src/display/render.c index 8ddc845..0e9dbba 100644 --- a/src/display/render.c +++ b/src/display/render.c @@ -6,31 +6,7 @@ */ #include "render.h" -#include "game/game.h" -#include "assert/assert.h" -#include "console/console.h" void renderInit() { - // Initialize the rendering system - InitWindow(800, 600, "Dusk"); -} - -renderresult_t renderDraw() { - BeginDrawing(); - ClearBackground(BLACK); - - for(uint32_t i = 0; i < GAME.entityCount; i++) { - entityRender(&GAME.entities[i]); - } - - consoleDraw(); - - EndDrawing(); - if(WindowShouldClose()) return RENDER_EXIT; - return RENDER_OK; -} - - -void renderDispose() { - CloseWindow(); + } \ No newline at end of file diff --git a/src/display/render.h b/src/display/render.h index 1663a5c..04f4f00 100644 --- a/src/display/render.h +++ b/src/display/render.h @@ -6,33 +6,8 @@ */ #pragma once -#include "dusk.h" - -#define RENDER_FONT_SIZE 20 - -typedef enum { - RENDER_OK, - RENDER_EXIT, - RENDER_ERROR -} renderresult_t; /** - * Initializes the rendering system. - * - * @return The result of the initialization. + * Init the render system. */ -void renderInit(); - -/** - * Initializes the rendering system. - * - * @return The result of the initialization. - */ -renderresult_t renderDraw(); - -/** - * Renders the game. - * - * @return The result of the render operation. - */ -void renderDispose(); \ No newline at end of file +void renderInit(); \ No newline at end of file diff --git a/src/dusk.h b/src/dusk.h index d192615..4761ff8 100644 --- a/src/dusk.h +++ b/src/dusk.h @@ -16,10 +16,8 @@ #include #include #include -#include #include #include -#include typedef bool bool_t; typedef char char_t; diff --git a/src/error/error.c b/src/error/error.c deleted file mode 100644 index 8345db7..0000000 --- a/src/error/error.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "error.h" - -errorstack_t ERROR_STACK; - -errorret_t error(const char_t *message, ...) { - return errorCode(1, message); -} - -errorret_t errorCode(const errorret_t code, const char_t *message, ...) { - if(ERROR_STACK.code != ERROR_OK) { - snprintf( - ERROR_STACK.message, - ERROR_STACK_SIZE, - "Multiple errors encountered." - ); - errorPrint(); - return code; - } - - va_list args; - va_start(args, message); - vsnprintf(ERROR_STACK.message, ERROR_STACK_SIZE, message, args); - va_end(args); - - return ERROR_STACK.code = code; -} - -bool_t errorCheck() { - return ERROR_STACK.code != ERROR_OK; -} - -const char_t * errorString() { - if(!errorCheck()) return NULL; - return ERROR_STACK.message; -} - -void errorFlush() { - if(!errorCheck()) return; - ERROR_STACK.code = ERROR_OK; - ERROR_STACK.message[0] = '\0'; -} - -errorret_t errorPrint() { - if(!errorCheck()) return ERROR_OK; - printf("Error: %s\n", errorString()); - errorret_t code = ERROR_STACK.code; - errorFlush(); - return code; -} \ No newline at end of file diff --git a/src/error/error.h b/src/error/error.h deleted file mode 100644 index 45ca04f..0000000 --- a/src/error/error.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef int32_t errorret_t; -#define ERROR_OK 0 - -#define ERROR_STACK_SIZE 256 - -typedef struct { - char_t message[ERROR_STACK_SIZE + 1]; - errorret_t code; -} errorstack_t; - -extern errorstack_t ERROR_STACK; - -/** - * Pushes an error message to the error stack. - * - * @param message Message to push to the error stack. - * @param ... Arguments to format the message with. - */ -errorret_t error(const char_t *message, ...); - -/** - * Pushes an error message to the error stack with a given error code. - * - * @param code Error code to push to the error stack. - * @param message Message to push to the error stack. - * @param ... Arguments to format the message with. - */ -errorret_t errorCode(const errorret_t code, const char_t *message, ...); - -/** - * Checks if an error has been pushed to the error stack. - * - * @return True if an error has been pushed to the error stack. - */ -bool_t errorCheck(); - -/** - * Retrieves the error message from the error stack. - */ -const char_t * errorString(); - -/** - * Clears the error stack. - */ -void errorFlush(); - -/** - * Prints the error stack to the console. This also clears the error stack. - */ -errorret_t errorPrint(); \ No newline at end of file diff --git a/src/game/direction.h b/src/game/direction.h deleted file mode 100644 index 417ba7d..0000000 --- a/src/game/direction.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once - -typedef enum { - DIRECTION_SOUTH = 0, - DIRECTION_NORTH = 1, - DIRECTION_EAST = 2, - DIRECTION_WEST = 3, - - DIRECTION_DOWN = 0, - DIRECTION_UP = 1, - DIRECTION_RIGHT = 2, - DIRECTION_LEFT = 3, -} direction_t; \ No newline at end of file diff --git a/src/game/entity/entity.c b/src/game/entity/entity.c deleted file mode 100644 index d9c8b5a..0000000 --- a/src/game/entity/entity.c +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" -#include "game/game.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "display/render.h" -#include "input.h" - -void entityInit(entity_t *entity, const entitytype_t type) { - memoryZero(entity, sizeof(entity_t)); - - entity->type = type; - switch(type) { - case ENTITY_TYPE_PLAYER: - break; - - default: - assertUnreachable("Unknown entity type."); - break; - } -} - -void entityTest(entity_t *ent) { - if(inputIsPressed(INPUT_DOWN)) { - ent->direction = DIRECTION_DOWN; - if(ent->y < GAME.map.height - 1) ent->y++; - } else if(inputIsPressed(INPUT_UP)) { - ent->direction = DIRECTION_UP; - if(ent->y > 0) ent->y--; - } else if(inputIsPressed(INPUT_LEFT)) { - ent->direction = DIRECTION_LEFT; - if(ent->x > 0) ent->x--; - } else if(inputIsPressed(INPUT_RIGHT)) { - ent->direction = DIRECTION_RIGHT; - if(ent->x < GAME.map.width - 1) ent->x++; - } -} - -void entityRender(const entity_t *ent) { - // Draw the entity - int32_t fontSize = 20; - char_t str[1]; - switch(ent->direction) { - case DIRECTION_NORTH: - str[0] = '^'; - break; - case DIRECTION_EAST: - str[0] = '>'; - break; - case DIRECTION_SOUTH: - str[0] = 'v'; - break; - case DIRECTION_WEST: - str[0] = '<'; - break; - default: - assertUnreachable("Invalid entity direction."); - break; - } - - DrawTextEx( - GetFontDefault(), - str, - (struct Vector2){ - ent->x * RENDER_FONT_SIZE, - ent->y * RENDER_FONT_SIZE - }, - RENDER_FONT_SIZE, - (float)(RENDER_FONT_SIZE / 10), - WHITE - ); -} \ No newline at end of file diff --git a/src/game/entity/entity.h b/src/game/entity/entity.h deleted file mode 100644 index 0950c68..0000000 --- a/src/game/entity/entity.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "game/direction.h" - -typedef enum { - ENTITY_TYPE_NULL = 0, - ENTITY_TYPE_PLAYER, -} entitytype_t; - - -typedef struct { - entitytype_t type; - uint8_t x, y; - direction_t direction; -} entity_t; - -/** - * Initializes a given entity. - * - * @param entity The entity to initialize. - * @param type The type of the entity. - */ -void entityInit(entity_t *entity, const entitytype_t type); - -void entityTest(entity_t *entity); - -/** - * Renders a given entity. - * - * @param entity The entity to render. - */ -void entityRender(const entity_t *entity); \ No newline at end of file diff --git a/src/game/game.c b/src/game/game.c deleted file mode 100644 index 724fbc0..0000000 --- a/src/game/game.c +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "game.h" -#include "util/memory.h" - -game_t GAME; - -void gameInit(void) { - memoryZero(&GAME, sizeof(game_t)); - - GAME.map.width = 10; - GAME.map.height = 10; -} \ No newline at end of file diff --git a/src/game/game.h b/src/game/game.h deleted file mode 100644 index 81822ef..0000000 --- a/src/game/game.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "game/entity/entity.h" -#include "game/map/map.h" - -#define GAME_ENTITIES_MAX 256 - -typedef struct { - entity_t entities[GAME_ENTITIES_MAX]; - uint32_t entityCount; - map_t map; -} game_t; - -extern game_t GAME; - -/** - * Initializes the game. - */ -void gameInit(void); \ No newline at end of file diff --git a/src/input.c b/src/input.c index 49928d1..386a993 100644 --- a/src/input.c +++ b/src/input.c @@ -9,20 +9,6 @@ #include "util/memory.h" #include "assert/assert.h" -inputbindmap_t INPUT_BIND_MAPS[] = { - { KEY_W, INPUT_UP }, - { KEY_S, INPUT_DOWN }, - { KEY_A, INPUT_LEFT }, - { KEY_D, INPUT_RIGHT }, - { KEY_ENTER, INPUT_ACCEPT }, - { KEY_ESCAPE, INPUT_CANCEL }, - { KEY_UP, INPUT_UP }, - { KEY_DOWN, INPUT_DOWN }, - { KEY_LEFT, INPUT_LEFT }, - { KEY_RIGHT, INPUT_RIGHT }, - { KEY_GRAVE, INPUT_TOGGLE_CONSOLE } -}; - #define INPUT_BIND_MAP_COUNT (sizeof(INPUT_BIND_MAPS) / sizeof(inputbindmap_t)) input_t INPUT; @@ -32,48 +18,4 @@ void inputInit(void) { } void inputUpdate(void) { - memoryCopy( - INPUT.previous, - INPUT.current, - sizeof(INPUT.previous) - ); - - memoryZero( - INPUT.current, - sizeof(INPUT.current) - ); - - for(uint32_t i = 0; i < INPUT_BIND_MAP_COUNT; i++) { - const inputbindmap_t *map = &INPUT_BIND_MAPS[i]; - if(IsKeyDown(map->key)) INPUT.current[map->bind] = true; - } - - INPUT.keyPressed = GetKeyPressed(); - INPUT.charPressed = GetCharPressed(); -} - -bool_t inputIsDown(const inputbind_t input) { - assertTrue(input < INPUT_BIND_COUNT, "Input out of range"); - return INPUT.current[input]; -} - -bool_t inputIsUp(const inputbind_t input) { - return !inputIsDown(input); -} - -bool_t inputWasDown(const inputbind_t input) { - assertTrue(input < INPUT_BIND_COUNT, "Input out of range"); - return INPUT.previous[input]; -} - -bool_t inputWasUp(const inputbind_t input) { - return !inputWasDown(input); -} - -bool_t inputIsPressed(const inputbind_t input) { - return inputIsDown(input) && inputWasUp(input); -} - -bool_t inputIsReleased(const inputbind_t input) { - return inputIsUp(input) && inputWasDown(input); } \ No newline at end of file diff --git a/src/input.h b/src/input.h index a998565..727e1be 100644 --- a/src/input.h +++ b/src/input.h @@ -8,28 +8,8 @@ #pragma once #include "dusk.h" -typedef enum { - INPUT_UP, - INPUT_DOWN, - INPUT_LEFT, - INPUT_RIGHT, - INPUT_ACCEPT, - INPUT_CANCEL, - INPUT_TOGGLE_CONSOLE, -} inputbind_t; - -#define INPUT_BIND_COUNT INPUT_TOGGLE_CONSOLE + 1 - typedef struct { - const int32_t key; - const inputbind_t bind; -} inputbindmap_t; - -typedef struct { - bool_t current[INPUT_BIND_COUNT]; - bool_t previous[INPUT_BIND_COUNT]; - int32_t keyPressed; - char_t charPressed; + char_t input; } input_t; extern input_t INPUT; @@ -42,52 +22,4 @@ void inputInit(void); /** * Updates the input system. */ -void inputUpdate(void); - -/** - * Returns whether a given input is currently pressed. - * - * @param input The input to check. - * @return True if the input is pressed, false otherwise. - */ -bool_t inputIsDown(const inputbind_t input); - -/** - * Returns whether a given input is currently up. - * - * @param input The input to check. - * @return True if the input is up, false otherwise. - */ -bool_t inputIsUp(const inputbind_t input); - -/** - * Returns whether a given input was just pressed. - * - * @param input The input to check. - * @return True if the input was just pressed, false otherwise. - */ -bool_t inputWasDown(const inputbind_t input); - -/** - * Returns whether a given input was just released. - * - * @param input The input to check. - * @return True if the input was just released, false otherwise. - */ -bool_t inputWasUp(const inputbind_t input); - -/** - * Returns whether a given input was just pressed. - * - * @param input The input to check. - * @return True if the input was just pressed, false otherwise. - */ -bool_t inputIsPressed(const inputbind_t input); - -/** - * Returns whether a given input was just released. - * - * @param input The input to check. - * @return True if the input was just released, false otherwise. - */ -bool_t inputIsReleased(const inputbind_t input); \ No newline at end of file +void inputUpdate(void); \ No newline at end of file diff --git a/src/main.c b/src/main.c index 7a18a90..7c9a82b 100644 --- a/src/main.c +++ b/src/main.c @@ -5,70 +5,17 @@ * https://opensource.org/licenses/MIT */ -#include "assert/assert.h" -#include "game/game.h" -#include "display/render.h" -#include "input.h" -#include "console/console.h" -#include "network/client/client.h" -#include "network/server/server.h" #include "util/random.h" - -bool_t exitRequested = false; - -void cmdExit(const consolecmdexec_t *exec) { - exitRequested = true; -} +#include "display/render.h" int32_t main(const int32_t argc, const char **argv) { - assertInit(); randomInit(); - gameInit(); - inputInit(); renderInit(); - consoleInit(); - clientInit(); - serverInit(); - consoleRegCmd("exit", cmdExit); - - entityInit(&GAME.entities[GAME.entityCount++], ENTITY_TYPE_PLAYER); - - float_t lastPing = -1; - float_t time = 0; - - while(true) { - inputUpdate(); - consoleUpdate(); - serverUpdate(); - clientUpdate(); - - if(!CONSOLE.open) { - for(uint32_t i = 0; i < GAME.entityCount; i++) { - entity_t *ent = &GAME.entities[i]; - entityTest(ent); - } - } + while(1) { - renderresult_t result = renderDraw(); - if(result != RENDER_OK) break; - if(exitRequested) break; - - time += GetFrameTime(); - if(time - lastPing > 1.0f) { - lastPing = time; - - if(CLIENT.state != CLIENT_STATE_CONNECTED) continue; - packet_t packet; - packetPingCreate(&packet); - packetQueuePushOut(&CLIENT.packetQueue, &packet); - lastPing = time; - } + usleep(16 * 1000); // Sleep for 16 milliseconds (60 FPS) } - serverDispose(); - clientDispose(); - renderDispose(); - return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt deleted file mode 100644 index 713c29b..0000000 --- a/src/network/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources - -# Subdirs -add_subdirectory(client) -add_subdirectory(packet) -add_subdirectory(server) \ No newline at end of file diff --git a/src/network/client/CMakeLists.txt b/src/network/client/CMakeLists.txt deleted file mode 100644 index e2217ee..0000000 --- a/src/network/client/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - client.c -) - -# Subdirs \ No newline at end of file diff --git a/src/network/client/client.c b/src/network/client/client.c deleted file mode 100644 index aafec49..0000000 --- a/src/network/client/client.c +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "client.h" -#include "util/memory.h" -#include "assert/assert.h" - -client_t CLIENT; - -void clientInit() { - memoryZero(&CLIENT, sizeof(client_t)); -} - -void clientConnect(const clientconnect_t connect) { - int32_t error; - - assertTrue( - CLIENT.state == CLIENT_STATE_DISCONNECTED, - "Client is not in a disconnected state." - ); - - // Reset state - packetQueueInit(&CLIENT.queue); - CLIENT.error = CLIENT_ERROR_NO_ERROR; - CLIENT.state = CLIENT_STATE_CONNECTING; - CLIENT.type = connect.type; - - // Init the properties based on the type of client. - switch(connect.type) { - case CLIENT_TYPE_NETWORKED: - networkClientConnect(&CLIENT, connect); - break; - - case CLIENT_TYPE_SINGLE_PLAYER: - break; - - default: - assertUnreachable("Invalid client connection type."); - break; - } - - // Spawn the connect thread which will be responsible from here on out. - error = pthread_create( - &CLIENT.connectThread, - NULL, - (void *(*)(void *))clientThreadConnect, - &CLIENT - ); - if(error != 0) { - CLIENT.state = CLIENT_STATE_DISCONNECTED; - CLIENT.error = CLIENT_ERROR_CONNECT_THREAD_SPAWN_FAILED; - } -} - -void clientDisconnect() { - if(CLIENT.state == CLIENT_STATE_DISCONNECTED) return; - if(CLIENT.state == CLIENT_STATE_DISCONNECTING) return; -} - -void clientUpdate() { - assertIsMainThread("Client update called from non-main thread."); -} - -void clientDispose() { - if(CLIENT.state != CLIENT_STATE_DISCONNECTED) { - clientDisconnect(); - } -} - -void * clientThreadConnect(void *arg) { - assertNotNull(arg, "Client thread connect argument is null."); - assertNotMainThread("Client thread connect called from main thread."); - - client_t *client = (client_t *)arg; - assertTrue(client == &CLIENT, "Invalid client thread arg."); - - if(client->state) return NULL; - - switch(client->type) { - case CLIENT_TYPE_NETWORKED: - break; - - case CLIENT_TYPE_SINGLE_PLAYER: - break; - - default: - assertUnreachable("Invalid client type."); - break; - } - - // -} \ No newline at end of file diff --git a/src/network/client/client.h b/src/network/client/client.h deleted file mode 100644 index aec8898..0000000 --- a/src/network/client/client.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "network/packet/packetqueue.h" -#include "networkclient.h" - -/** - * Type of connection used for a client. - */ -typedef enum { - CLIENT_TYPE_SINGLE_PLAYER = 0, - CLIENT_TYPE_NETWORKED = 1, -} clienttype_t; - -/** - * The state of the client and what it is doing. - */ -typedef enum { - CLIENT_STATE_DISCONNECTED = 0, - CLIENT_STATE_CONNECTING, - CLIENT_STATE_CONNECTED, - CLIENT_STATE_DISCONNECTING, -} clientstate_t; - -/** - * Information used to connect to a server. - */ -typedef struct clientconnect_s { - clienttype_t type; -} clientconnect_t; - -/** - * Error codes for the client. - */ -typedef enum { - CLIENT_ERROR_NO_ERROR = 0, - CLIENT_ERROR_CONNECT_THREAD_SPAWN_FAILED, -} clienterror_t; - -/** - * The clients state and information. - */ -typedef struct client_s { - clientstate_t state; - clienttype_t type; - packetqueue_t queue; - clienterror_t error; - - pthread_t connectThread; - - union { - networkclient_t network; - }; -} client_t; - -extern client_t CLIENT; - -/** - * Initializes the client object, does not perform any connection. - */ -void clientInit(); - -/** - * Initiates a client connection, this function will not block and will return - * immediately even if a connection issue occurs. It is up to the caller to - * handle the connection state and any errors that occur. - * - * Client must be already disconnected before calling this function. - * - * @param connect The connection information to use. - */ -void clientConnect(const clientconnect_t connect); - -/** - * Requests the client to disconnect from the server. This will not block and - * will return immediately. The client will handle the disconnection in the - * background. - */ -void clientDisconnect(); - -/** - * Internal method that writes a packet to the client immediately. - */ -clienterror_t clientWritePacket(const packet_t *packet); - -/** - * Internal method that reads a packet from the client immediately. - * - * @param packet The packet to read into. - * @return Error code indicating success or failure. - */ -clienterror_t clientReadPacket(const packet_t *packet); - -/** - * Main update loop for the client, this will handle all incoming packets and - * update the client state. - */ -void clientUpdate(); - -/** - * Disposes of the client, cleans up any resources and will force disconnect if - * not already disconnected. - */ -void clientDispose(); - -/** - * Thread function responsible for initiating and handshaking the connection. - * - * @param arg The client connection information. - * @return Returns NULL, unless an error occurs. - */ -void * clientThreadConnect(void *arg); \ No newline at end of file diff --git a/src/network/client/networkclient.h b/src/network/client/networkclient.h deleted file mode 100644 index 93ff7c5..0000000 --- a/src/network/client/networkclient.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct client_s client_t; -typedef struct clientconnect_s clientconnect_t; - -typedef struct { - void *nothing; -} networkclient_t; - -/** - * Initialize the client. - * - * @param client The client to initialize. - * @param connect The connection information. - */ -void networkClientConnect(client_t *client, const clientconnect_t connect); \ No newline at end of file diff --git a/src/network/packet/CMakeLists.txt b/src/network/packet/CMakeLists.txt deleted file mode 100644 index 2b6cdf6..0000000 --- a/src/network/packet/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - packet.c - packetwelcome.c - packetdisconnect.c - packetqueue.c - packetping.c -) \ No newline at end of file diff --git a/src/network/packet/packet.c b/src/network/packet/packet.c deleted file mode 100644 index c9c7be3..0000000 --- a/src/network/packet/packet.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "packet.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "network/client/client.h" -#include "network/server/server.h" - -packethandler_t PACKET_HANDLERS[] = { - { NULL, NULL }, - { packetWelcomeClientProcess, NULL }, - { packetDisconnectClientProcess, NULL }, - { packetPingClientProcess, packetPingServerProcess }, -}; - -void packetInit( - packet_t *packet, - const packettype_t type, - const uint32_t length -) { - assertNotNull(packet, "Packet is NULL"); - - memoryZero(packet, sizeof(packet_t)); - - assertTrue(length > 0, "Packet length is 0"); - assertTrue( - length <= sizeof(packetdata_t), - "Packet length is too large" - ); - - packet->type = type; - packet->length = length; -} - -errorret_t packetClientProcess( - const packet_t *packet, - client_t *client -) { - assertNotNull(packet, "Packet is NULL"); - assertNotNull(client, "Client is NULL"); - assertTrue( - client->type == CLIENT_TYPE_NETWORKED, - "Client is not networked" - ); - assertIsMainThread("Client process must be on main thread"); - - if(packet->type >= PACKET_TYPE_COUNT) { - return error("Unknown packet type %d", packet->type); - } - - if(PACKET_HANDLERS[packet->type].client == NULL) { - return error("Packet type %d has no client handler", packet->type); - } - - return PACKET_HANDLERS[packet->type].client(packet, client); -} - -errorret_t packetServerProcess( - const packet_t *packet, - serverclient_t *client -) { - assertNotNull(packet, "Packet is NULL"); - assertNotNull(client, "Client is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - assertIsMainThread("Server client process must be on main thread"); - - if(packet->type >= PACKET_TYPE_COUNT) { - return error("Unknown packet type %d", packet->type); - } - - if(PACKET_HANDLERS[packet->type].server == NULL) { - return error("Packet type %d has no server handler", packet->type); - } - - return PACKET_HANDLERS[packet->type].server(packet, client); -} \ No newline at end of file diff --git a/src/network/packet/packet.h b/src/network/packet/packet.h deleted file mode 100644 index d1d34c0..0000000 --- a/src/network/packet/packet.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "packetwelcome.h" -#include "packetdisconnect.h" -#include "packetping.h" - -typedef enum { - PACKET_TYPE_INVALID = 0, - PACKET_TYPE_WELCOME = 1, - PACKET_TYPE_DISCONNECT = 2, - PACKET_TYPE_PING = 3, -} packettype_t; - -#define PACKET_TYPE_COUNT 4 - -typedef union { - packetwelcome_t welcome; - packetdisconnect_t disconnect; - packetping_t ping; -} packetdata_t; - -typedef struct packet_s { - packettype_t type; - uint32_t length; - packetdata_t data; -} packet_t; - -typedef struct { - errorret_t (*client)(const packet_t *packet, client_t *client); - errorret_t (*server)(const packet_t *packet, serverclient_t *client); -} packethandler_t; - -extern packethandler_t PACKET_HANDLERS[]; - -/** - * Initializes a packet with the given type. This is only to be used by sub - * initializers, such as packetWelcomeCreate for example. - * - * @param packet Pointer to the packet structure to initialize. - * @param type The type of the packet. - * @param length The length of the packet data. - */ -void packetInit( - packet_t *packet, - const packettype_t type, - const uint32_t length -); - -/** - * Processes a packet for a given client. Will auto-decide the correct method to - * handle the process - * - * @param packet Pointer to the packet structure to process. - * @param client Pointer to the client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetClientProcess( - const packet_t *packet, - client_t *client -); - -/** - * Processes a packet for a given server client. Will auto-decide the correct - * method to handle the process - * - * @param packet Pointer to the packet structure to process. - * @param client Pointer to the server client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetServerProcess( - const packet_t *packet, - serverclient_t *client -); \ No newline at end of file diff --git a/src/network/packet/packetdisconnect.c b/src/network/packet/packetdisconnect.c deleted file mode 100644 index d34ec72..0000000 --- a/src/network/packet/packetdisconnect.c +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "packet.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "network/client/client.h" - -void packetDisconnectCreate( - packet_t *packet, - const packetdisconnectreason_t reason -) { - packetInit(packet, PACKET_TYPE_DISCONNECT, sizeof(packetdisconnect_t)); - packet->data.disconnect.reason = reason; -} - -errorret_t packetDisconnectClientProcess( - const packet_t *packet, - client_t *client -) { - assertTrue( - packet->type == PACKET_TYPE_DISCONNECT, - "Packet type is not DISCONNECT" - ); - - if(packet->length != sizeof(packetdisconnect_t)) { - return error("Disconnect packet length is not correct"); - } - - // TODO: Handle disconnect reasons better. - packetdisconnect_t *data = (packetdisconnect_t *)&packet->data; - // switch(data->reason) { - // case PACKET_DISCONNECT_REASON_UNKNOWN: - // return error("Server disconnected: Unknown reason"); - // case PACKET_DISCONNECT_REASON_INVALID_VERSION: - // return error("Server disconnected: Invalid version"); - // case PACKET_DISCONNECT_REASON_MALFORMED_PACKET: - // return error("Server disconnected: Malformed packet"); - // case PACKET_DISCONNECT_REASON_SERVER_FULL: - // return error("Server disconnected: Server full"); - // case PACKET_DISCONNECT_REASON_SERVER_SHUTDOWN: - // return error("Server disconnected: Server shutdown"); - // default: - // return error("Server disconnected: Unknown reason"); - // } - - return ERROR_OK; -} \ No newline at end of file diff --git a/src/network/packet/packetdisconnect.h b/src/network/packet/packetdisconnect.h deleted file mode 100644 index 998fce0..0000000 --- a/src/network/packet/packetdisconnect.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "packetbase.h" - -typedef enum { - PACKET_DISCONNECT_REASON_UNKNOWN = 0, - PACKET_DISCONNECT_REASON_INVALID_VERSION = 1, - PACKET_DISCONNECT_REASON_MALFORMED_PACKET = 2, - PACKET_DISCONNECT_REASON_SERVER_FULL = 3, - PACKET_DISCONNECT_REASON_SERVER_SHUTDOWN = 4, -} packetdisconnectreason_t; - -typedef struct { - packetdisconnectreason_t reason; -} packetdisconnect_t; - -/** - * Creates a disconnect packet. - * - * @param packet Pointer to the packet structure to initialize. - * @param reason The reason for the disconnect. - */ -void packetDisconnectCreate( - packet_t *packet, - const packetdisconnectreason_t reason -); - -/** - * Handles disconnect packet client side. - * - * @param packet Pointer to the packet structure to handle. - * @param client Pointer to the client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetDisconnectClientProcess( - const packet_t *packet, client_t *client -); \ No newline at end of file diff --git a/src/network/packet/packetping.c b/src/network/packet/packetping.c deleted file mode 100644 index 00260f7..0000000 --- a/src/network/packet/packetping.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "packet.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "network/server/server.h" - -void packetPingCreate(packet_t *packet) { - packetInit(packet, PACKET_TYPE_PING, sizeof(packetping_t)); - packet->data.ping.number = GetRandomValue(0, INT32_MAX); -} - -errorret_t packetPingClientProcess( - const packet_t *packet, - client_t *client -) { - assertTrue( - packet->type == PACKET_TYPE_PING, - "Packet type is not PING" - ); - - printf("Client got Pong!\n"); - - return ERROR_OK; -} - -errorret_t packetPingServerProcess( - const packet_t *packet, - serverclient_t *client -) { - assertTrue( - packet->type == PACKET_TYPE_PING, - "Packet type is not PING" - ); - - if(packet->length != sizeof(packetping_t)) { - return error("Ping packet length is not %d", sizeof(packetping_t)); - } - - printf("Server got Ping!\n"); - - // Send ping back to the client. - packet_t pong; - packetPingCreate(&pong); - packetQueuePushOut(&client->packetQueue, &pong); - - return ERROR_OK; -} \ No newline at end of file diff --git a/src/network/packet/packetping.h b/src/network/packet/packetping.h deleted file mode 100644 index aec495d..0000000 --- a/src/network/packet/packetping.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "packetbase.h" - -typedef struct { - int32_t number; -} packetping_t; - -/** - * Creates a ping packet. - * - * @param packet Pointer to the packet structure to initialize. - */ -void packetPingCreate(packet_t *packet); - -/** - * Validates a ping packet received FROM a client INTO a server. - * - * @param packet Pointer to the packet structure to validate. - * @param client Pointer to the server client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetPingClientProcess( - const packet_t *packet, - client_t *client -); - -/** - * Handles a ping packet received FROM a client INTO a server. - * - * @param packet Pointer to the packet structure to handle. - * @param client Pointer to the server client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetPingServerProcess( - const packet_t *packet, - serverclient_t *client -); \ No newline at end of file diff --git a/src/network/packet/packetqueue.c b/src/network/packet/packetqueue.c deleted file mode 100644 index df89e27..0000000 --- a/src/network/packet/packetqueue.c +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "packetqueue.h" -#include "assert/assert.h" -#include "util/memory.h" - -void packetQueueInit(packetqueue_t *queue) { - assertNotNull(queue, "Packet queue is NULL"); - memoryZero(queue, sizeof(packetqueue_t)); - pthread_mutex_init(&queue->lock, NULL); -} - -void packetQueuePushIn(packetqueue_t *queue, const packet_t *packet) { - assertNotNull(queue, "Packet queue is NULL"); - assertNotNull(packet, "Packet is NULL"); - pthread_mutex_lock(&queue->lock); - assertTrue( - queue->packetsInCount < PACKET_QUEUE_MAX_SIZE, "Inbound packet queue is full" - ); - - queue->packetsIn[queue->packetsInCount++] = *packet; - pthread_mutex_unlock(&queue->lock); -} - -void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet) { - assertNotNull(queue, "Packet queue is NULL"); - assertNotNull(packet, "Packet is NULL"); - pthread_mutex_lock(&queue->lock); - assertTrue( - queue->packetsOutCount < PACKET_QUEUE_MAX_SIZE, "Outbound packet queue is full" - ); - - queue->packetsOut[queue->packetsOutCount++] = *packet; - pthread_mutex_unlock(&queue->lock); -} - -int32_t packetQueuePopIn(packetqueue_t *queue, packet_t *packet) { - assertNotNull(queue, "Packet queue is NULL"); - assertNotNull(packet, "Packet is NULL"); - - pthread_mutex_lock(&queue->lock); - if(queue->packetsInCount == 0) { - pthread_mutex_unlock(&queue->lock); - return 0; - } - - *packet = queue->packetsIn[0]; - if(queue->packetsInCount > 1) { - memoryCopy( - &queue->packetsIn[0], - &queue->packetsIn[1], - (queue->packetsInCount - 1) * sizeof(packet_t) - ); - } - queue->packetsInCount--; - pthread_mutex_unlock(&queue->lock); - return 1; -} - -int32_t packetQueuePopOut(packetqueue_t *queue, packet_t *packet) { - assertNotNull(queue, "Packet queue is NULL"); - assertNotNull(packet, "Packet is NULL"); - - pthread_mutex_lock(&queue->lock); - if(queue->packetsOutCount == 0) { - pthread_mutex_unlock(&queue->lock); - return 0; - } - - *packet = queue->packetsOut[0]; - if(queue->packetsOutCount > 1) { - memoryCopy( - &queue->packetsOut[0], - &queue->packetsOut[1], - (queue->packetsOutCount - 1) * sizeof(packet_t) - ); - } - queue->packetsOutCount--; - pthread_mutex_unlock(&queue->lock); - return 1; -} \ No newline at end of file diff --git a/src/network/packet/packetqueue.h b/src/network/packet/packetqueue.h deleted file mode 100644 index b445305..0000000 --- a/src/network/packet/packetqueue.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "network/packet/packet.h" - -#define PACKET_QUEUE_MAX_SIZE 512 - -typedef struct { - packet_t packetsIn[PACKET_QUEUE_MAX_SIZE]; - uint32_t packetsInCount; - packet_t packetsOut[PACKET_QUEUE_MAX_SIZE]; - uint32_t packetsOutCount; - pthread_mutex_t lock; -} packetqueue_t; - -/** - * Initializes the packet queue. - * - * @param queue Pointer to the packet queue structure. - */ -void packetQueueInit(packetqueue_t *queue); - -/** - * Pushes a packet into the inbound packet queue. - * - * @param queue Pointer to the packet queue structure. - * @param packet Pointer to the packet to be pushed. - */ -void packetQueuePushIn(packetqueue_t *queue, const packet_t *packet); - -/** - * Pushes a packet into the outbound packet queue. - * - * @param queue Pointer to the packet queue structure. - * @param packet Pointer to the packet to be pushed. - */ -void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet); - -/** - * Pops a packet from the inbound packet queue. - * - * @param queue Pointer to the packet queue structure. - * @param packet Pointer to the packet to store the popped packet. - * @return 1 if a packet was popped, 0 otherwise. - */ -int32_t packetQueuePopIn(packetqueue_t *queue, packet_t *packet); - -/** - * Pops a packet from the outbound packet queue. - * - * @param queue Pointer to the packet queue structure. - * @param packet Pointer to the packet to store the popped packet. - * @return 1 if a packet was popped, 0 otherwise. - */ -int32_t packetQueuePopOut(packetqueue_t *queue, packet_t *packet); \ No newline at end of file diff --git a/src/network/packet/packetwelcome.c b/src/network/packet/packetwelcome.c deleted file mode 100644 index b124590..0000000 --- a/src/network/packet/packetwelcome.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "packet.h" -#include "util/memory.h" -#include "assert/assert.h" - -void packetWelcomeCreate(packet_t *packet) { - packetInit(packet, PACKET_TYPE_WELCOME, PACKET_WELCOME_SIZE); - memoryCopy( - packet->data.welcome.dusk, PACKET_WELCOME_STRING, PACKET_WELCOME_SIZE - ); -} - -errorret_t packetWelcomeClientProcess( - const packet_t *packet, - client_t *client -) { - assertNotNull(packet, "Packet is NULL"); - assertNotNull(client, "Client is NULL"); - assertTrue(packet->type == PACKET_TYPE_WELCOME, "Packet type is not WELCOME"); - - if(packet->length != PACKET_WELCOME_SIZE) { - return error("Welcome packet length is not %d", PACKET_WELCOME_SIZE); - } - - if( - memoryCompare( - packet->data.welcome.dusk, PACKET_WELCOME_STRING, PACKET_WELCOME_SIZE - ) != 0 - ) { - return error("Welcome packet data is not %s", PACKET_WELCOME_STRING); - } - - return ERROR_OK; -} \ No newline at end of file diff --git a/src/network/packet/packetwelcome.h b/src/network/packet/packetwelcome.h deleted file mode 100644 index 69400f8..0000000 --- a/src/network/packet/packetwelcome.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "packetbase.h" - -#define PACKET_WELCOME_STRING "DUSK" -#define PACKET_WELCOME_SIZE 4 - -typedef struct { - char_t dusk[PACKET_WELCOME_SIZE]; -} packetwelcome_t; - -/** - * Creates a welcome packet. - * - * @param packet Pointer to the packet structure to initialize. - */ -void packetWelcomeCreate(packet_t *packet); - -/** - * Handles a welcome packet received FROM a server INTO a client. - * - * @param packet Pointer to the packet structure to handle. - * @param client Pointer to the client structure. - * @return ERROR_OK on success, or an error code on failure. - */ -errorret_t packetWelcomeClientProcess( - const packet_t *packet, - client_t *client -); \ No newline at end of file diff --git a/src/network/server/CMakeLists.txt b/src/network/server/CMakeLists.txt deleted file mode 100644 index 1913faf..0000000 --- a/src/network/server/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - server.c - serverclient.c -) - -# Subdirs -add_subdirectory(networked) -add_subdirectory(singleplayer) \ No newline at end of file diff --git a/src/network/server/networked/CMakeLists.txt b/src/network/server/networked/CMakeLists.txt deleted file mode 100644 index 3d440ea..0000000 --- a/src/network/server/networked/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - networkedserverclient.c - networkedserver.c -) \ No newline at end of file diff --git a/src/network/server/networked/networkedserver.c b/src/network/server/networked/networkedserver.c deleted file mode 100644 index f957bca..0000000 --- a/src/network/server/networked/networkedserver.c +++ /dev/null @@ -1,224 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "network/server/server.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "console/console.h" - -errorret_t networkedServerStart( - server_t *server, - const serverstart_t start -) { - assertNotNull(server, "Server is null"); - assertTrue(start.type == SERVER_TYPE_NETWORKED, "Invalid server type"); - assertTrue(server->state == SERVER_STATE_STOPPED,"Server is already running"); - assertIsMainThread("Server start must be on main thread"); - - // Initialize the networked server. - consolePrint("Starting server on port %d...", start.networked.port); - memoryZero(&server->networked, sizeof(server->networked)); - - // Initialize the server socket - server->networked.socket = socket(AF_INET, SOCK_STREAM, 0); - if(server->networked.socket < 0) { - return error("Failed to create socket"); - } - - // Setup the socket options - server->networked.address.sin_addr.s_addr = INADDR_ANY; - server->networked.address.sin_family = AF_INET; - server->networked.address.sin_port = htons(start.networked.port); - - // Set the socket to reuse the address - int opt = 1; - setsockopt( - server->networked.socket, - SOL_SOCKET, - SO_REUSEADDR, - &opt, - sizeof(opt) - ); - - // Set the socket to non-blocking - int flags = fcntl(server->networked.socket, F_GETFL, 0); - if( - flags < 0 || - fcntl(server->networked.socket, F_SETFL, flags | O_NONBLOCK) < 0 - ) { - close(server->networked.socket); - return error("Failed to set socket to non-blocking %s", strerror(errno)); - } - - // Bind the socket to the address and port - int32_t res = bind( - server->networked.socket, - (struct sockaddr *)&server->networked.address, - sizeof(server->networked.address) - ); - if(res != 0) { - close(server->networked.socket); - return error( - "Socket bind to port %d failed: %s", - start.networked.port, - strerror(errno) - ); - } - - // Set the socket to listen for incoming connections - res = listen(server->networked.socket, SERVER_MAX_CLIENTS); - if(res != 0) { - close(server->networked.socket); - return error( - "Failed to listen on port %d: %s", - start.networked.port, - strerror(errno) - ); - } - - - // Start the server thread. - pthread_mutex_init(&server->networked.lock, NULL); - server->state = SERVER_STATE_STARTING; - - res = pthread_create(&server->thread, NULL, networkedServerThread, server); - if(res != 0) { - close(server->networked.socket); - pthread_mutex_destroy(&server->networked.lock); - server->state = SERVER_STATE_STOPPED; - return error("Failed to create server thread"); - } - - // Server started, hand back. - consolePrint("Server started."); - return ERROR_OK; -} - -void networkedServerStop(server_t *server) { - assertNotNull(server, "Server is null"); - assertTrue(server->state != SERVER_STATE_STOPPED,"Server is already stopped"); - assertTrue(server->state != SERVER_STATE_STARTING, "Server is starting"); - assertIsMainThread("Server stop must be on main thread"); - - // Notify thread to stop - pthread_mutex_lock(&server->networked.lock); - server->state = SERVER_STATE_STOPPING; - pthread_mutex_unlock(&server->networked.lock); - - // Disconnect clients - uint8_t i = 0; - do { - serverclient_t *client = &server->clients[i++]; - if(client->state == SERVER_CLIENT_STATE_DISCONNECTED) continue; - serverClientClose(client); - } while(i < SERVER_MAX_CLIENTS); - - // Wait for the server thread to finish - pthread_join(server->thread, NULL); - pthread_mutex_destroy(&server->networked.lock); - - close(server->networked.socket); - - server->networked.socket = -1; - server->state = SERVER_STATE_STOPPED; - consolePrint("Server stopped."); -} - -void * networkedServerThread(void *arg) { - assertNotNull(arg, "Server is null"); - assertNotMainThread("Server thread must not be main thread"); - - server_t *server = (server_t *)arg; - - // Set server state to running - pthread_mutex_lock(&server->networked.lock); - server->state = SERVER_STATE_RUNNING; - pthread_mutex_unlock(&server->networked.lock); - - fd_set readfds; - struct timeval timeout; - - // Main server loop - while (1) { - // Check if the server should continue running - pthread_mutex_lock(&server->networked.lock); - if (server->state != SERVER_STATE_RUNNING) { - pthread_mutex_unlock(&server->networked.lock); - break; - } - pthread_mutex_unlock(&server->networked.lock); - - // Prepare the select call to wait for new connections - FD_ZERO(&readfds); - FD_SET(server->networked.socket, &readfds); - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - // Wait for incoming connections - int activity = select( - server->networked.socket + 1, - &readfds, - NULL, - NULL, - &timeout - ); - if (activity <= 0) continue; - if (!FD_ISSET(server->networked.socket, &readfds)) continue; - - // Accept incoming connection - int32_t clientSocket = accept(server->networked.socket, NULL, NULL); - if (clientSocket < 0) { - consolePrint("Failed to accept connection"); - continue; - } - - // Find an available client slot - serverclient_t *client = NULL; - for (uint8_t i = 0; i < SERVER_MAX_CLIENTS; i++) { - if(server->clients[i].state != SERVER_CLIENT_STATE_DISCONNECTED) { - continue; - } - client = &server->clients[i]; - break; - } - - // Server full, send disconnect packet - if (!client) { - packet_t packet; - serverclient_t tempClient = { - .networked = { .socket = clientSocket }, - .server = server, - .state = SERVER_CLIENT_STATE_ACCEPTING - }; - packetDisconnectCreate(&packet, PACKET_DISCONNECT_REASON_SERVER_FULL); - networkedServerClientWritePacket(&tempClient, &packet); - if (errorCheck()) errorPrint(); - consolePrint("Client disconnected: Server full."); - close(clientSocket); - continue; - } - - // Accept the client into the server - errorret_t ret = serverClientAccept(client, (serverclientaccept_t){ - .server = server, - .networked = { .socket = clientSocket } - }); - if (ret != ERROR_OK) { - consolePrint("Failed to accept client connection: %s", errorString()); - errorFlush(); - close(clientSocket); - } - } - - // Cleanup and signal server stop - pthread_mutex_lock(&server->networked.lock); - server->state = SERVER_STATE_STOPPED; - pthread_mutex_unlock(&server->networked.lock); - - consolePrint("Server thread exiting."); - return NULL; -} diff --git a/src/network/server/networked/networkedserver.h b/src/network/server/networked/networkedserver.h deleted file mode 100644 index 32c5563..0000000 --- a/src/network/server/networked/networkedserver.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include -#include - -typedef struct { - uint16_t port; -} networkedserverstart_t; - -typedef struct { - int socket; - struct sockaddr_in address; - pthread_mutex_t lock; -} networkedserver_t; - -typedef struct server_s server_t; -typedef struct serverstart_s serverstart_t; - -/** -* Initialize the networked server -* -* This function initializes the networked server by setting up the ENet library -* and creating a server host. -* -* @param server Pointer to the server structure. -* @param start Information about how to start the server. -* @return Returns an error code if the server fails to start. -*/ -errorret_t networkedServerStart(server_t *server, const serverstart_t start); - -/** - * Stop the networked server - * - * This function stops the networked server by shutting down the ENet library - * and closing the server host. - * - * @param server Pointer to the server structure. - */ -void networkedServerStop(server_t *server); - -/** - * Server thread function - * - * This function runs in a separate thread and handles incoming connections, - * messages, and disconnections. - * - * @param arg Pointer to the argument passed to the thread. - */ -void * networkedServerThread(void *arg); \ No newline at end of file diff --git a/src/network/server/networked/networkedserverclient.c b/src/network/server/networked/networkedserverclient.c deleted file mode 100644 index b52ae5b..0000000 --- a/src/network/server/networked/networkedserverclient.c +++ /dev/null @@ -1,382 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "network/server/server.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "console/console.h" -#include - -errorret_t networkedServerClientAccept( - serverclient_t *client, - const serverclientaccept_t accept -) { - assertNotNull(client, "Client is NULL"); - assertNotNull(accept.server, "Server is NULL"); - assertTrue( - accept.server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - - client->state = SERVER_CLIENT_STATE_ACCEPTING; - client->networked.socket = accept.networked.socket; - - // Set timeout to 8 seconds - client->networked.timeout.tv_sec = 8; - client->networked.timeout.tv_usec = 0; - - // Initialize mutexs - pthread_mutex_init(&client->networked.readLock, NULL); - pthread_mutex_init(&client->networked.writeLock, NULL); - - // Create a read thread for the client - int32_t ret = pthread_create( - &client->networked.readThread, - NULL, - networkedServerClientReadThread, - client - ); - if(ret != 0) { - client->state = SERVER_CLIENT_STATE_DISCONNECTED; - return error("Failed to create client read thread"); - } - - // Set socket timeout - if(setsockopt( - client->networked.socket, - SOL_SOCKET, - SO_RCVTIMEO, - &client->networked.timeout, - sizeof(client->networked.timeout) - ) < 0) { - networkedServerClientCloseOnThread(client, "Failed to set socket timeout"); - return error("Failed to set socket timeout"); - } - - return ERROR_OK; -} - -void networkedServerClientClose(serverclient_t *client) { - assertIsMainThread("Server client close must be on main thread."); - assertNotNull(client, "Client is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - - // Mark client as disconnecting - client->state = SERVER_CLIENT_STATE_DISCONNECTING; - - // Wait for the read thread to finish - pthread_mutex_lock(&client->networked.readLock); - pthread_mutex_unlock(&client->networked.readLock); - pthread_join(client->networked.readThread, NULL); - client->networked.readThread = 0; - pthread_mutex_destroy(&client->networked.readLock); - - // Signal and wait for the write thread to finish - pthread_mutex_lock(&client->networked.writeLock); - pthread_mutex_unlock(&client->networked.writeLock); - pthread_join(client->networked.writeThread, NULL); - client->networked.writeThread = 0; - pthread_mutex_destroy(&client->networked.writeLock); - - // Close the socket - if(client->networked.socket != -1) { - close(client->networked.socket); - client->networked.socket = -1; - } - - client->state = SERVER_CLIENT_STATE_DISCONNECTED; - consolePrint("Client %d disconnected.", client->networked.socket); -} - -void networkedServerClientCloseOnThread( - serverclient_t *client, - const char_t *reason -) { - assertNotNull(client, "Client is NULL"); - assertNotNull(reason, "Reason is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - assertNotMainThread("Client close must not be main thread"); - - client->state = SERVER_CLIENT_STATE_DISCONNECTING; - - // Terminate the socket - close(client->networked.socket); - client->networked.socket = -1; - client->networked.readThread = 0; - consolePrint("Client %d disconnected: %s", client->networked.socket, reason); - - // Mark this client as disconnected so it can be used again. - client->state = SERVER_CLIENT_STATE_DISCONNECTED; - pthread_exit(NULL); -} - -ssize_t networkedServerClientRead( - const serverclient_t * client, - uint8_t *buffer, - const size_t len -) { - assertNotNull(client, "Client is NULL"); - assertNotNull(buffer, "Buffer is NULL"); - assertNotNull(client->server, "Server is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - assertTrue(len > 0, "Buffer length is 0"); - - assertTrue( - client->state == SERVER_CLIENT_STATE_CONNECTED || - client->state == SERVER_CLIENT_STATE_ACCEPTING || - client->state == SERVER_CLIENT_STATE_DISCONNECTING, - "Client is not connected, accepting or disconnecting" - ); - - return recv(client->networked.socket, buffer, len, 0); -} - -errorret_t networkedServerClientReadPacket( - const serverclient_t * client, - packet_t *packet -) { - uint8_t buffer[sizeof(packet_t)]; - ssize_t read; - - assertNotNull(client, "Client is NULL"); - assertNotNull(packet, "Packet is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - - // Read packet ID - read = networkedServerClientRead(client, buffer, sizeof(packettype_t)); - if(read != sizeof(packettype_t)) { - return error("Failed to read packet ID"); - } - - packet->type = *(packettype_t *)buffer; - if(packet->type == PACKET_TYPE_INVALID) { - return error("Invalid packet type"); - } - - // Read length - read = networkedServerClientRead( - client, - buffer, - sizeof(uint32_t) - ); - - if(read != sizeof(uint32_t)) { - return error("Failed to read packet length"); - } - - packet->length = *(uint32_t *)buffer; - if(packet->length > sizeof(packetdata_t)) { - return error("Packet length is too large"); - } - - // Read data - read = networkedServerClientRead( - client, - (uint8_t *)&packet->data, - packet->length - ); - if(read != packet->length) { - return error("Failed to read packet data"); - } - - return ERROR_OK; -} - -errorret_t networkedServerClientWrite( - serverclient_t * client, - const uint8_t *data, - const size_t len -) { - assertNotNull(client, "Client is NULL"); - assertNotNull(data, "Data is NULL"); - assertTrue(len > 0, "Data length is 0"); - assertNotNull(client->server, "Server is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - - if(client->state == SERVER_CLIENT_STATE_DISCONNECTED) { - return error("Client is disconnected"); - } - ssize_t sent = send(client->networked.socket, data, len, 0); - if(sent < 0) return error("Failed to send data"); - return ERROR_OK; -} - -errorret_t networkedServerClientWritePacket( - serverclient_t * client, - const packet_t *packet -) { - assertNotNull(packet, "Packet is NULL"); - assertTrue(packet->type != PACKET_TYPE_INVALID, "Packet type is INVALID"); - assertTrue(packet->length > 0, "Packet length is 0"); - assertTrue( - packet->length <= sizeof(packetdata_t), - "Packet length is too large (1)" - ); - - size_t fullSize = sizeof(packet_t) - sizeof(packet->data) + packet->length; - assertTrue(fullSize <= sizeof(packet_t), "Packet size is too large (2)"); - return networkedServerClientWrite(client, (const uint8_t *)packet, fullSize); -} - -void * networkedServerClientReadThread(void *arg) { - assertNotNull(arg, "Client is NULL"); - assertNotMainThread("Client thread must not be main thread"); - - serverclient_t *client = (serverclient_t *)arg; - char_t buffer[1024]; - ssize_t read; - errorret_t err; - packet_t packet; - - assertNotNull(client->server, "Server is NULL"); - assertTrue( - client->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - assertTrue( - client->state == SERVER_CLIENT_STATE_ACCEPTING, - "Client is not accepting?" - ); - - // First message from the client should always be "DUSK|VERSION" to match - // the server version. - { - const char_t *expecting = "DUSK|"DUSK_VERSION; - read = networkedServerClientRead(client, buffer, sizeof(buffer)); - if(read <= 0) { - packetDisconnectCreate(&packet, PACKET_DISCONNECT_REASON_INVALID_VERSION); - err = networkedServerClientWritePacket(client, &packet); - networkedServerClientCloseOnThread(client, "Failed to receive version"); - return NULL; - } - - buffer[read] = '\0'; // Null-terminate the string - if(strncmp(buffer, expecting, strlen(expecting)) != 0) { - packetDisconnectCreate(&packet, PACKET_DISCONNECT_REASON_INVALID_VERSION); - err = networkedServerClientWritePacket(client, &packet); - networkedServerClientCloseOnThread(client, "Invalid version"); - return NULL; - } - } - - // Send DUSK back! - packetWelcomeCreate(&packet); - err = networkedServerClientWritePacket(client, &packet); - if(err != ERROR_OK) { - networkedServerClientCloseOnThread( - client, "Failed to send welcome message" - ); - return NULL; - } - - // Client is connected. - client->state = SERVER_CLIENT_STATE_CONNECTED; - - // Start the write thread after the handshake - int32_t ret = pthread_create( - &client->networked.writeThread, - NULL, - networkedServerClientWriteThread, - client - ); - if(ret != 0) { - networkedServerClientCloseOnThread(client, "Failed to create write thread"); - return NULL; - } - - // Start listening for packets. - while(client->state == SERVER_CLIENT_STATE_CONNECTED) { - pthread_mutex_lock(&client->networked.readLock); - - err = networkedServerClientReadPacket(client, &packet); - if(err != ERROR_OK) { - consolePrint("Failed to read packet %s", errorString()); - errorFlush(); - pthread_mutex_unlock(&client->networked.readLock); - break; - } - - packetQueuePushIn(&client->packetQueue, &packet); - - pthread_mutex_unlock(&client->networked.readLock); - } - - pthread_mutex_lock(&client->networked.readLock); - client->state = SERVER_CLIENT_STATE_DISCONNECTED; - pthread_mutex_unlock(&client->networked.readLock); - - return NULL; -} - -void * networkedServerClientWriteThread(void *arg) { - packet_t packet; - int32_t ret; - errorret_t err; - - assertNotNull(arg, "Client is NULL"); - assertNotMainThread("Client thread must not be main thread"); - assertTrue( - ((serverclient_t *)arg)->server->type == SERVER_TYPE_NETWORKED, - "Server is not networked" - ); - assertTrue( - ((serverclient_t *)arg)->state == SERVER_CLIENT_STATE_CONNECTED, - "Client is not connected" - ); - - serverclient_t *client = (serverclient_t *)arg; - - while(client->state == SERVER_CLIENT_STATE_CONNECTED) { - pthread_mutex_lock(&client->networked.writeLock); - - ret = packetQueuePopOut( - &client->packetQueue, - &packet - ); - - if(ret == 0) { - pthread_mutex_unlock(&client->networked.writeLock); - continue; - } - - if(ret < 0) { - consolePrint("Failed to pop packet %s", errorString()); - errorFlush(); - client->state = SERVER_CLIENT_STATE_DISCONNECTING; - pthread_mutex_unlock(&client->networked.writeLock); - break; - } - - err = networkedServerClientWritePacket(client, &packet); - if(err != ERROR_OK) { - consolePrint("Failed to write packet %s", errorString()); - errorFlush(); - client->state = SERVER_CLIENT_STATE_DISCONNECTING; - pthread_mutex_unlock(&client->networked.writeLock); - break; - } - - pthread_mutex_unlock(&client->networked.writeLock); - } - - return NULL; -} \ No newline at end of file diff --git a/src/network/server/networked/networkedserverclient.h b/src/network/server/networked/networkedserverclient.h deleted file mode 100644 index e1538b5..0000000 --- a/src/network/server/networked/networkedserverclient.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -typedef struct serverclient_s serverclient_t; -typedef struct serverclientaccept_s serverclientaccept_t; - -typedef struct { - int32_t socket; -} networkedserverclientaccept_t; - -typedef struct { - int32_t socket; - pthread_t readThread; - pthread_t writeThread; - struct timeval timeout; - pthread_mutex_t readLock; - pthread_mutex_t writeLock; -} networkedserverclient_t; - -/** - * Accepts an incoming connection from a networked server client. - * - * @param client Pointer to the server client structure. - * @param accept Accept structure containing client information. - * @return Error code indicating success or failure. - */ -errorret_t networkedServerClientAccept( - serverclient_t *client, - const serverclientaccept_t accept -); - -/** - * Closes the connection to a networked server client. Waits for the thread to finish. - * - * @param client Pointer to the server client structure. - */ -void networkedServerClientClose(serverclient_t *client); - -/** - * Closes the connection to a networked server client on the thread. - * - * @param client Pointer to the server client structure. - * @param reason Reason for closing the connection. - */ -void networkedServerClientCloseOnThread( - serverclient_t *client, - const char_t *reason -); - -/** - * Receives data from a server client. - * - * @param client Pointer to the server client structure. - * @param buffer Pointer to the buffer to store received data. - * @param len Max length of the buffer. - * @return Number of bytes received. 0 or less indicates an error. - */ -ssize_t networkedServerClientRead( - const serverclient_t * client, - uint8_t *buffer, - const size_t len -); - -/** - * Writes data to a server client. - * - * @param client Pointer to the server client structure. - * @param data Pointer to the data to send. - * @param len Length of the data to send. - * @return Error code indicating success or failure. - */ -errorret_t networkedServerClientWrite( - serverclient_t * client, - const uint8_t *data, - const size_t len -); - -/** - * Writes a packet to a server client. - * - * @param client Pointer to the server client structure. - * @param packet Pointer to the packet to send. - * @return Error code indicating success or failure. - */ -errorret_t networkedServerClientWritePacket( - serverclient_t * client, - const packet_t *packet -); - -/** - * Thread function for handling reading from a networked server client. - * - * @param arg Pointer to the server client structure. - * @return NULL. - */ -void * networkedServerClientReadThread(void *arg); - -/** - * Thread function for handling writing to a networked server client. - * - * @param arg Pointer to the server client structure. - * @return NULL. - */ -void * networkedServerClientWriteThread(void *arg); \ No newline at end of file diff --git a/src/network/server/server.c b/src/network/server/server.c deleted file mode 100644 index 99d744a..0000000 --- a/src/network/server/server.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "server.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "console/console.h" -#include "util/string.h" - -server_t SERVER; - -void cmdStart(const consolecmdexec_t *exec) { - serverstart_t start; - - if(exec->argc > 0) { - if(stringCompare(exec->argv[0], "0") == 0) { - start.type = SERVER_TYPE_SINGLE_PLAYER; - } else if(stringCompare(exec->argv[0], "1") == 0) { - start.type = SERVER_TYPE_NETWORKED; - } else { - consolePrint("Invalid server type: %s", exec->argv[0]); - return; - } - } else { - start.type = SERVER_TYPE_NETWORKED; - } - - if(exec->argc > 1) { - if(start.type == SERVER_TYPE_NETWORKED) { - if(!stringToU16(exec->argv[1], &start.networked.port)) { - consolePrint("Invalid port number: %s", exec->argv[0]); - return; - } - } - } else { - if(start.type == SERVER_TYPE_NETWORKED) { - start.networked.port = SERVER_DEFAULT_PORT; - } - } - - errorret_t ret = serverStart(start); - if(ret != ERROR_OK) { - consolePrint("Failed to start server: %s", errorString()); - errorFlush(); - return; - } -} - -void cmdClose(const consolecmdexec_t *exec) { - serverStop(); -} - -void serverInit() { - memoryZero(&SERVER, sizeof(server_t)); - SERVER.state = SERVER_STATE_STOPPED; - - consoleRegCmd("start", cmdStart); - consoleRegCmd("close", cmdClose); -} - -errorret_t serverStart(const serverstart_t start) { - errorret_t ret; - assertIsMainThread("Server start must be on main thread"); - - // Do not start a running server. - if(SERVER.state != SERVER_STATE_STOPPED) { - return error("Server is already running"); - } - - SERVER.type = start.type; - - // Hand off to relevant server type to start. - switch(start.type) { - case SERVER_TYPE_NETWORKED: - ret = networkedServerStart(&SERVER, start); - break; - - default: - assertUnreachable("Invalid server type"); - } - - if(ret != ERROR_OK) SERVER.state = SERVER_STATE_STOPPED; - return ret; -} - -uint8_t serverGetClientCount() { - uint8_t i = 0, clientCount = 0; - do { - if(SERVER.clients[i++].state == SERVER_CLIENT_STATE_DISCONNECTED) continue; - clientCount++; - } while(i < SERVER_MAX_CLIENTS); - return clientCount; -} - -void serverUpdate() { - assertIsMainThread("Server update must be on main thread"); - if(SERVER.state != SERVER_STATE_RUNNING) return; - - // Update all clients - for(uint8_t i = 0; i < SERVER_MAX_CLIENTS; i++) { - serverClientUpdate(&SERVER.clients[i]); - } -} - -void serverStop() { - assertIsMainThread("Server stop must be on main thread"); - if(SERVER.state == SERVER_STATE_STOPPED) return; - - consolePrint("Stopping server..."); - switch(SERVER.type) { - case SERVER_TYPE_NETWORKED: - networkedServerStop(&SERVER); - break; - - default: - assertUnreachable("Invalid server type"); - } - consolePrint("Server stopped."); -} - -void serverDispose() { - serverStop(); -} \ No newline at end of file diff --git a/src/network/server/server.h b/src/network/server/server.h deleted file mode 100644 index 36ef2e0..0000000 --- a/src/network/server/server.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "serverclient.h" -#include "network/server/networked/networkedserver.h" - -#define SERVER_MAX_CLIENTS 32 -#define SERVER_DEFAULT_PORT 3030 - -typedef enum { - SERVER_STATE_STOPPED, - SERVER_STATE_STARTING, - SERVER_STATE_RUNNING, - SERVER_STATE_STOPPING -} serverstate_t; - -typedef enum { - SERVER_TYPE_SINGLE_PLAYER, - SERVER_TYPE_NETWORKED -} servertype_t; - -typedef struct serverstart_s { - servertype_t type; - union { - networkedserverstart_t networked; - }; -} serverstart_t; - -typedef struct server_s { - serverstate_t state; - servertype_t type; - pthread_t thread; - serverclient_t clients[SERVER_MAX_CLIENTS]; - - union { - networkedserver_t networked; - }; -} server_t; - -extern server_t SERVER; - -/** - * Initialize the server - * - * This function initializes the server by setting up the ENet library and - * creating a server host. - */ -void serverInit(); - -/** - * Start the server - * - * This function starts the server by creating a host, binding it to the - * specified address and port, and starting the server thread. - * - * @param port The port number to bind the server to. - * @return Returns an error code if the server fails to start. - */ -errorret_t serverStart(const serverstart_t start); - -/** - * Get the client count - * - * This function returns the number of connected clients to the server. - * - * @return The number of connected clients. - */ -uint8_t serverGetClientCount(); - -/** - * Performs a (main thread) update to process clients on the server. - */ -void serverUpdate(); - -/** - * Stop the server - * - * This function stops the server by destroying the host and cleaning up - * resources. - */ -void serverStop(); - -/** - * Dispose of the server - * - * This function disposes of the server by deinitializing the ENet library. - */ -void serverDispose(); \ No newline at end of file diff --git a/src/network/server/serverclient.c b/src/network/server/serverclient.c deleted file mode 100644 index 2054c5c..0000000 --- a/src/network/server/serverclient.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "server.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "console/console.h" - -errorret_t serverClientAccept( - serverclient_t *client, - const serverclientaccept_t accept -) { - errorret_t ret; - memoryZero(client, sizeof(serverclient_t)); - assertNotNull(accept.server, "Server is NULL"); - assertNotMainThread("Server client accept must not be main thread"); - - client->server = accept.server; - packetQueueInit(&client->packetQueue); - - switch(accept.server->type) { - case SERVER_TYPE_NETWORKED: - ret = networkedServerClientAccept(client, accept); - break; - - default: - assertUnreachable("Unknown server type"); - } - - if(ret != ERROR_OK) memoryZero(client, sizeof(serverclient_t)); - return ret; -} - -void serverClientUpdate(serverclient_t *client) { - assertNotNull(client, "Client is NULL"); - assertIsMainThread("Server client update must be on main thread"); - - if(client->state != SERVER_CLIENT_STATE_CONNECTED) return; - - packet_t packet; - int32_t ret = 1; - - // Process packets - do { - ret = packetQueuePopIn( - &client->packetQueue, - &packet - ); - - if(ret == 0) break; - - if(ret < 0) { - serverClientClose(client); - consolePrint("Failed to pop packet"); - return; - } - - packetServerProcess(&packet, client); - } while(true); -} - -void serverClientClose(serverclient_t *client) { - assertNotNull(client, "Client is NULL"); - assertIsMainThread("Server client close must be on main thread"); - if(client->state == SERVER_CLIENT_STATE_DISCONNECTED) return; - - switch(client->server->type) { - case SERVER_TYPE_NETWORKED: - networkedServerClientClose(client); - break; - - default: - assertUnreachable("Unknown server type"); - } -} \ No newline at end of file diff --git a/src/network/server/serverclient.h b/src/network/server/serverclient.h deleted file mode 100644 index 8a8e13c..0000000 --- a/src/network/server/serverclient.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "network/packet/packet.h" -#include "network/server/networked/networkedserverclient.h" -#include "network/packet/packetqueue.h" - -typedef struct server_s server_t; - -typedef enum { - SERVER_CLIENT_STATE_DISCONNECTED, - SERVER_CLIENT_STATE_ACCEPTING, - SERVER_CLIENT_STATE_CONNECTED, - SERVER_CLIENT_STATE_DISCONNECTING, -} serverclientstate_t; - -typedef struct serverclientaccept_s { - server_t *server; - union { - networkedserverclientaccept_t networked; - }; -} serverclientaccept_t; - -typedef struct serverclient_s { - server_t *server; - serverclientstate_t state; - packetqueue_t packetQueue; - - union { - networkedserverclient_t networked; - }; -} serverclient_t; - -/** - * Accepts an incoming connection from a server client. - * - * @param client Pointer to the server client structure. - * @param accept Accept structure containing client information. - * @return Error code indicating success or failure. - */ -errorret_t serverClientAccept( - serverclient_t *client, - const serverclientaccept_t accept -); - -/** - * Handles the main thread updating of this server client. This is where all - * the packets will be handled and processed. - * - * @param client Pointer to the server client structure. - */ -void serverClientUpdate(serverclient_t *client); - -/** - * Closes the connection to a server client. Waits for the thread to finish. - * - * @param client Pointer to the server client structure. - */ -void serverClientClose(serverclient_t *client); \ No newline at end of file diff --git a/src/game/CMakeLists.txt b/src/rpg/CMakeLists.txt similarity index 73% rename from src/game/CMakeLists.txt rename to src/rpg/CMakeLists.txt index f507c91..418fd16 100644 --- a/src/game/CMakeLists.txt +++ b/src/rpg/CMakeLists.txt @@ -6,8 +6,9 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - game.c ) # Subdirs -add_subdirectory(entity) \ No newline at end of file +add_subdirectory(entity) +add_subdirectory(item) +add_subdirectory(quest) \ No newline at end of file diff --git a/src/game/entity/CMakeLists.txt b/src/rpg/entity/CMakeLists.txt similarity index 93% rename from src/game/entity/CMakeLists.txt rename to src/rpg/entity/CMakeLists.txt index ebbd7cb..c54f1d4 100644 --- a/src/game/entity/CMakeLists.txt +++ b/src/rpg/entity/CMakeLists.txt @@ -7,4 +7,5 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE entity.c + player.c ) \ No newline at end of file diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c new file mode 100644 index 0000000..d2e0b8c --- /dev/null +++ b/src/rpg/entity/entity.c @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assert/assert.h" +#include "util/memory.h" +#include "entity.h" + +entity_t ENTITIES[ENTITY_COUNT]; + +entitycallbacks_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { + [ENTITY_TYPE_NULL] = { + .init = NULL + }, + + [ENTITY_TYPE_PLAYER] = { + .init = playerInit + }, +}; + + + +void entityInit(entity_t *entity, const entitytype_t type) { + assertNotNull(entity, "Entity is NULL"); + assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type"); + assertNotNull(ENTITY_CALLBACKS[type].init, "Entity type has no init"); + + memoryZero(entity, sizeof(entity_t)); + entity->type = type; + ENTITY_CALLBACKS[type].init(entity); +} \ No newline at end of file diff --git a/src/rpg/entity/entity.h b/src/rpg/entity/entity.h new file mode 100644 index 0000000..62dd8e9 --- /dev/null +++ b/src/rpg/entity/entity.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "player.h" + +typedef enum { + ENTITY_DIR_UP = 0, + ENTITY_DIR_DOWN = 1, + ENTITY_DIR_LEFT = 2, + ENTITY_DIR_RIGHT = 3, + + ENTITY_DIR_NORTH = ENTITY_DIR_UP, + ENTITY_DIR_SOUTH = ENTITY_DIR_DOWN, + ENTITY_DIR_WEST = ENTITY_DIR_LEFT, + ENTITY_DIR_EAST = ENTITY_DIR_RIGHT +} entitydir_t; + +typedef enum { + ENTITY_TYPE_NULL = 0, + ENTITY_TYPE_PLAYER = 1, +} entitytype_t; +#define ENTITY_TYPE_COUNT (ENTITY_TYPE_PLAYER + 1) + +typedef struct _entity_t { + entitytype_t type; + uint8_t x, y; + entitydir_t dir; + + // Per type data + union { + player_t player; + }; +} entity_t; + +#define ENTITY_COUNT 16 +extern entity_t ENTITIES[ENTITY_COUNT]; + +typedef struct { + void (*init)(entity_t *entity); +} entitycallbacks_t; +extern entitycallbacks_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT]; + +/** + * Initializes an entity with the given type. + * + * @param entity Pointer to the entity to initialize. + * @param type The type of the entity to initialize. + */ +void entityInit(entity_t *entity, const entitytype_t type); \ No newline at end of file diff --git a/src/rpg/entity/player.c b/src/rpg/entity/player.c new file mode 100644 index 0000000..ffa37b4 --- /dev/null +++ b/src/rpg/entity/player.c @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entity.h" +#include "assert/assert.h" + +void playerInit(entity_t *player) { + assertNotNull(player, "Player entity is NULL"); + assertTrue(player->type == ENTITY_TYPE_PLAYER, "Entity is not a player"); +} \ No newline at end of file diff --git a/src/rpg/entity/player.h b/src/rpg/entity/player.h new file mode 100644 index 0000000..f43c78a --- /dev/null +++ b/src/rpg/entity/player.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct _entity_t entity_t; + +typedef struct { + uint8_t nothing; +} player_t; + +/** + * Initializes a player entity. + * + * @param ent Pointer to the player entity to initialize. + */ +void playerInit(entity_t *ent); \ No newline at end of file diff --git a/src/game/map/map.h b/src/rpg/event/event.h similarity index 79% rename from src/game/map/map.h rename to src/rpg/event/event.h index b9fde1a..33fd85e 100644 --- a/src/game/map/map.h +++ b/src/rpg/event/event.h @@ -9,6 +9,5 @@ #include "dusk.h" typedef struct { - void *nothing; - uint8_t width, height; -} map_t; \ No newline at end of file + +} event_t; \ No newline at end of file diff --git a/src/error/CMakeLists.txt b/src/rpg/item/CMakeLists.txt similarity index 92% rename from src/error/CMakeLists.txt rename to src/rpg/item/CMakeLists.txt index b246fdb..613b1ca 100644 --- a/src/error/CMakeLists.txt +++ b/src/rpg/item/CMakeLists.txt @@ -6,5 +6,5 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - error.c + itemtype.c ) \ No newline at end of file diff --git a/src/rpg/item/item.h b/src/rpg/item/item.h new file mode 100644 index 0000000..33ebcfc --- /dev/null +++ b/src/rpg/item/item.h @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "itemtype.h" \ No newline at end of file diff --git a/src/rpg/item/itemtype.c b/src/rpg/item/itemtype.c new file mode 100644 index 0000000..4b2f07f --- /dev/null +++ b/src/rpg/item/itemtype.c @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "itemtype.h" + +iteminfo_t ITEM_INFO[ITEM_TYPE_COUNT] = { + [ITEM_TYPE_NULL] = { 0 }, + + // Consumables + [ITEM_TYPE_POTION] = { .stackable = true }, + + // Ingredients + [ITEM_TYPE_ONION] = { .stackable = true }, + [ITEM_TYPE_SWEET_POTATO] = { .stackable = true }, + + // Cooked Items + [ITEM_TYPE_BAKED_SWEET_POTATO] = { .stackable = true }, +}; \ No newline at end of file diff --git a/src/rpg/item/itemtype.h b/src/rpg/item/itemtype.h new file mode 100644 index 0000000..c8e605f --- /dev/null +++ b/src/rpg/item/itemtype.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef enum { + ITEM_TYPE_NULL, + + // Consumables + ITEM_TYPE_POTION, + + // Ingredients + ITEM_TYPE_ONION, + ITEM_TYPE_SWEET_POTATO, + + // Cooked Items + ITEM_TYPE_BAKED_SWEET_POTATO, +} itemtype_t; + +#define ITEM_TYPE_COUNT (ITEM_TYPE_BAKED_SWEET_POTATO + 1) + +typedef struct { + bool_t stackable; +} iteminfo_t; +extern iteminfo_t ITEM_INFO[ITEM_TYPE_COUNT]; \ No newline at end of file diff --git a/src/network/server/singleplayer/CMakeLists.txt b/src/rpg/quest/CMakeLists.txt similarity index 93% rename from src/network/server/singleplayer/CMakeLists.txt rename to src/rpg/quest/CMakeLists.txt index fb0e252..785cca9 100644 --- a/src/network/server/singleplayer/CMakeLists.txt +++ b/src/rpg/quest/CMakeLists.txt @@ -6,4 +6,5 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE + quest.c ) \ No newline at end of file diff --git a/src/network/client/networkclient.c b/src/rpg/quest/quest.c similarity index 84% rename from src/network/client/networkclient.c rename to src/rpg/quest/quest.c index 6a96b64..aeeb9f6 100644 --- a/src/network/client/networkclient.c +++ b/src/rpg/quest/quest.c @@ -5,4 +5,4 @@ * https://opensource.org/licenses/MIT */ -#include "networkclient.h" \ No newline at end of file +#include "quest.h" \ No newline at end of file diff --git a/src/network/packet/packetbase.h b/src/rpg/quest/quest.h similarity index 53% rename from src/network/packet/packetbase.h rename to src/rpg/quest/quest.h index 1622f67..52b433b 100644 --- a/src/network/packet/packetbase.h +++ b/src/rpg/quest/quest.h @@ -6,8 +6,8 @@ */ #pragma once -#include "error/error.h" +#include "dusk.h" -typedef struct client_s client_t; -typedef struct serverclient_s serverclient_t; -typedef struct packet_s packet_t; \ No newline at end of file +typedef struct { + +} quest_t; \ No newline at end of file diff --git a/src/util/memory.c b/src/util/memory.c index 8387b48..97bf35a 100644 --- a/src/util/memory.c +++ b/src/util/memory.c @@ -8,17 +8,6 @@ #include "memory.h" #include "assert/assert.h" -void * memoryAllocate(const size_t size) { - void *ptr = malloc(size); - assertNotNull(ptr, "Failed to allocate memory."); - return ptr; -} - -void memoryFree(void *ptr) { - assertNotNull(ptr, "Cannot free NULL memory."); - free(ptr); -} - void memoryCopy(void *dest, const void *src, const size_t size) { assertNotNull(dest, "Cannot copy to NULL memory."); assertNotNull(src, "Cannot copy from NULL memory."); diff --git a/src/util/random.c b/src/util/random.c index e79242d..0f28ba7 100644 --- a/src/util/random.c +++ b/src/util/random.c @@ -9,19 +9,4 @@ #include "assert/assert.h" void randomInit() { - randomSeed(time(NULL)); -} - -void randomSeed(const uint32_t seed) { - srand(seed); -} - -int32_t randomI32(const int32_t min, const int32_t max) { - assertTrue(min < max, "Min is not less than max"); - return (rand() % (max - min)) + min; -} - -float_t randomF32(const float_t min, const float_t max) { - assertTrue(min < max, "Min is not less than max"); - return ((float_t)rand() / (float_t)RAND_MAX) * (max - min) + min; } \ No newline at end of file diff --git a/src/util/random.h b/src/util/random.h index fff612f..a738425 100644 --- a/src/util/random.h +++ b/src/util/random.h @@ -15,29 +15,4 @@ * initialize the random number generator with a random seed. It uses * the current time to generate a seed. */ -void randomInit(); - -/** - * Sets the random seed for the random number generator. - * - * @param seed The seed to set. - */ -void randomSeed(const uint32_t seed); - -/** - * Generates a random integer between min and max. - * - * @param min The minimum value (inclusive). - * @param max The maximum value (exclusive). - * @return A random integer between min and max. - */ -int32_t randomI32(const int32_t min, const int32_t max); - -/** - * Generates a random float between min and max. - * - * @param min The minimum value (inclusive). - * @param max The maximum value (exclusive). - * @return A random float between min and max. - */ -float_t randomF32(const float_t min, const float_t max); \ No newline at end of file +void randomInit(); \ No newline at end of file