Working on client code.
This commit is contained in:
@ -3,6 +3,12 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Libs
|
||||||
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
cglm
|
||||||
|
)
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
target_include_directories(${DUSK_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@ -20,4 +26,7 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(assert)
|
add_subdirectory(assert)
|
||||||
add_subdirectory(console)
|
add_subdirectory(console)
|
||||||
|
add_subdirectory(client)
|
||||||
|
add_subdirectory(server)
|
||||||
|
add_subdirectory(entity)
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
@ -54,6 +54,10 @@ void assertNotNullImpl(
|
|||||||
pointer != NULL,
|
pointer != NULL,
|
||||||
message
|
message
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure we can touch it
|
||||||
|
volatile char temp;
|
||||||
|
temp = *((char*)pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertNullImpl(
|
void assertNullImpl(
|
||||||
|
13
src/dusk/client/CMakeLists.txt
Normal file
13
src/dusk/client/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# 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
|
||||||
|
clientremote.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
71
src/dusk/client/client.c
Normal file
71
src/dusk/client/client.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void clientInit(
|
||||||
|
client_t *client,
|
||||||
|
const clientinit_t init
|
||||||
|
) {
|
||||||
|
assertNotNull(client, "Client cannot be NULL.");
|
||||||
|
memset(client, 0, sizeof(client_t));
|
||||||
|
|
||||||
|
client->type = init.type;
|
||||||
|
client->state = CLIENT_STATE_CONNECTING;
|
||||||
|
|
||||||
|
// Perform connection
|
||||||
|
switch(init.type) {
|
||||||
|
case CLIENT_TYPE_REMOTE:
|
||||||
|
clientRemoteInit(client, init.remote);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid client type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin exchanging.
|
||||||
|
// clientSend(client, (packet_t){
|
||||||
|
// .type = PACKET_TYPE_HELLO
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientSend(
|
||||||
|
client_t *client,
|
||||||
|
const packet_t packet
|
||||||
|
) {
|
||||||
|
assertNotNull(client, "Client cannot be NULL.");
|
||||||
|
assertTrue(
|
||||||
|
client->state == CLIENT_STATE_CONNECTED,
|
||||||
|
"Client must be connected to send packets."
|
||||||
|
);
|
||||||
|
|
||||||
|
switch(client->type) {
|
||||||
|
case CLIENT_TYPE_REMOTE:
|
||||||
|
clientRemoteSend(client, packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid client type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientDispose(client_t *client) {
|
||||||
|
assertNotNull(client, "Client cannot be NULL.");
|
||||||
|
client->state = CLIENT_STATE_DISCONNECTING;
|
||||||
|
|
||||||
|
switch(client->type) {
|
||||||
|
case CLIENT_TYPE_REMOTE:
|
||||||
|
clientRemoteDispose(client);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid client type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
client->state = CLIENT_STATE_DISCONNECTED;
|
||||||
|
}
|
51
src/dusk/client/client.h
Normal file
51
src/dusk/client/client.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "clientremote.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLIENT_TYPE_SINGLE_PLAYER,
|
||||||
|
CLIENT_TYPE_LOCAL,
|
||||||
|
CLIENT_TYPE_REMOTE
|
||||||
|
} clienttype_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLIENT_STATE_DISCONNECTED,
|
||||||
|
CLIENT_STATE_DISCONNECTING,
|
||||||
|
CLIENT_STATE_CONNECTING,
|
||||||
|
CLIENT_STATE_CONNECTED
|
||||||
|
} clientstate_t;
|
||||||
|
|
||||||
|
typedef struct _client_t {
|
||||||
|
clienttype_t type;
|
||||||
|
clientstate_t state;
|
||||||
|
|
||||||
|
union {
|
||||||
|
clientremote_t remote;
|
||||||
|
};
|
||||||
|
} client_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
clienttype_t type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
clientremoteinit_t remote;
|
||||||
|
};
|
||||||
|
} clientinit_t;
|
||||||
|
|
||||||
|
void clientInit(
|
||||||
|
client_t *client,
|
||||||
|
const clientinit_t init
|
||||||
|
);
|
||||||
|
|
||||||
|
void clientSend(
|
||||||
|
client_t *client,
|
||||||
|
const packet_t packet
|
||||||
|
);
|
||||||
|
|
||||||
|
void clientDispose(client_t *client);
|
45
src/dusk/client/clientremote.c
Normal file
45
src/dusk/client/clientremote.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
|
void* clientRemoteThreadFunc(void* arg) {
|
||||||
|
client_t *client = (client_t*)arg;
|
||||||
|
assertNotNull(client, "Client is NULL");
|
||||||
|
|
||||||
|
client->state = CLIENT_STATE_CONNECTED;
|
||||||
|
|
||||||
|
// Send some data
|
||||||
|
write(client->remote.clientSockDesc, "Hello, World!", 13);
|
||||||
|
|
||||||
|
printf("Thread func\n");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientRemoteInit(
|
||||||
|
client_t *client,
|
||||||
|
const clientremoteinit_t init
|
||||||
|
) {
|
||||||
|
client->remote.clientSockDesc = init.clientSockDesc;
|
||||||
|
consolePrint("Accepted a new connection.");
|
||||||
|
|
||||||
|
pthread_create(&client->remote.thread, NULL, clientRemoteThreadFunc, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientRemoteSend(client_t *client, const packet_t packet) {
|
||||||
|
printf("send pack\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientRemoteDispose(client_t *client) {
|
||||||
|
pthread_join(client->remote.thread, NULL);
|
||||||
|
|
||||||
|
close(client->remote.clientSockDesc);
|
||||||
|
consolePrint("Client disconnected.");
|
||||||
|
}
|
26
src/dusk/client/clientremote.h
Normal file
26
src/dusk/client/clientremote.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
#include "net/packet.h"
|
||||||
|
|
||||||
|
typedef struct _client_t client_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t clientSockDesc;
|
||||||
|
} clientremoteinit_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t clientSockDesc;
|
||||||
|
pthread_t thread;
|
||||||
|
} clientremote_t;
|
||||||
|
|
||||||
|
void clientRemoteInit(client_t *client, const clientremoteinit_t init);
|
||||||
|
void clientRemoteSend(client_t *client, const packet_t packet);
|
||||||
|
void * clientRemoteThread(void *arg);
|
||||||
|
void clientRemoteDispose(client_t *client);
|
@ -6,6 +6,7 @@
|
|||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
camera.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
44
src/dusk/display/camera.c
Normal file
44
src/dusk/display/camera.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
void cameraInit(camera_t *camera) {
|
||||||
|
glm_mat4_identity(camera->projection);
|
||||||
|
glm_mat4_identity(camera->view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraLookAt(
|
||||||
|
camera_t *camera,
|
||||||
|
const vec3 eye,
|
||||||
|
const vec3 center,
|
||||||
|
const vec3 up
|
||||||
|
) {
|
||||||
|
glm_lookat(eye, center, up, camera->view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraPerspective(
|
||||||
|
camera_t *camera,
|
||||||
|
float aspect,
|
||||||
|
float fovy,
|
||||||
|
float zNear,
|
||||||
|
float zFar
|
||||||
|
) {
|
||||||
|
glm_perspective(fovy, aspect, zNear, zFar, camera->projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraOrtho(
|
||||||
|
camera_t *camera,
|
||||||
|
float left,
|
||||||
|
float right,
|
||||||
|
float bottom,
|
||||||
|
float top,
|
||||||
|
float near,
|
||||||
|
float far
|
||||||
|
) {
|
||||||
|
glm_ortho(left, right, bottom, top, near, far, camera->projection);
|
||||||
|
}
|
74
src/dusk/display/camera.h
Normal file
74
src/dusk/display/camera.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
mat4 projection;
|
||||||
|
mat4 view;
|
||||||
|
} camera_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the camera.
|
||||||
|
*
|
||||||
|
* @param camera The camera to initialize.
|
||||||
|
*/
|
||||||
|
void cameraInit(camera_t *camera);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes a camera to look at a specific point.
|
||||||
|
*
|
||||||
|
* @param camera The camera to modify.
|
||||||
|
* @param eye The position of the camera.
|
||||||
|
* @param center The point to look at.
|
||||||
|
* @param up The up vector.
|
||||||
|
*/
|
||||||
|
void cameraLookAt(
|
||||||
|
camera_t *camera,
|
||||||
|
const vec3 eye,
|
||||||
|
const vec3 center,
|
||||||
|
const vec3 up
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the camera's perspective.
|
||||||
|
*
|
||||||
|
* @param camera The camera to modify.
|
||||||
|
* @param fovy The field of view in the y direction.
|
||||||
|
* @param aspect The aspect ratio.
|
||||||
|
* @param zNear The near plane.
|
||||||
|
* @param zFar The far plane.
|
||||||
|
*/
|
||||||
|
void cameraPerspective(
|
||||||
|
camera_t *camera,
|
||||||
|
const float fovy,
|
||||||
|
const float aspect,
|
||||||
|
const float zNear,
|
||||||
|
const float zFar
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the camera's orthographic perspective.
|
||||||
|
*
|
||||||
|
* @param camera The camera to modify.
|
||||||
|
* @param left The left plane.
|
||||||
|
* @param right The right plane.
|
||||||
|
* @param bottom The bottom plane.
|
||||||
|
* @param top The top plane.
|
||||||
|
* @param near The near plane.
|
||||||
|
* @param far The far plane.
|
||||||
|
*/
|
||||||
|
void cameraOrtho(
|
||||||
|
camera_t *camera,
|
||||||
|
const float left,
|
||||||
|
const float right,
|
||||||
|
const float bottom,
|
||||||
|
const float top,
|
||||||
|
const float near,
|
||||||
|
const float far
|
||||||
|
);
|
@ -14,6 +14,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <cglm/cglm.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef float float_t;
|
||||||
|
typedef double double_t;
|
||||||
typedef bool bool_t;
|
typedef bool bool_t;
|
||||||
typedef char char_t;
|
typedef char char_t;
|
12
src/dusk/entity/CMakeLists.txt
Normal file
12
src/dusk/entity/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# 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
|
||||||
|
entity.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
17
src/dusk/entity/entity.c
Normal file
17
src/dusk/entity/entity.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
entity_t ENTITY_TEST;
|
||||||
|
|
||||||
|
void entityInit(entity_t *ent) {
|
||||||
|
assertNotNull(ent, "Entity cannot be NULL");
|
||||||
|
|
||||||
|
memset(ent, 0, sizeof(entity_t));
|
||||||
|
}
|
17
src/dusk/entity/entity.h
Normal file
17
src/dusk/entity/entity.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
vec3 position;
|
||||||
|
} entity_t;
|
||||||
|
|
||||||
|
extern entity_t ENTITY_TEST;
|
||||||
|
|
||||||
|
void entityInit(entity_t *entity);
|
@ -9,14 +9,32 @@
|
|||||||
#include "gametime.h"
|
#include "gametime.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
|
#include "server/server.h"
|
||||||
|
|
||||||
|
#include "entity/entity.h"
|
||||||
|
|
||||||
void gameInit() {
|
void gameInit() {
|
||||||
consoleInit();
|
consoleInit();
|
||||||
gameTimeInit();
|
gameTimeInit();
|
||||||
inputInit();
|
inputInit();
|
||||||
|
|
||||||
|
serverInit();
|
||||||
|
serverStart((serverstart_t){
|
||||||
|
.type = SERVER_TYPE_LOCAL,
|
||||||
|
.local = {
|
||||||
|
.port = SERVER_LOCAL_PORT_DEFAULT
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
entityInit(&ENTITY_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameUpdate(const float delta) {
|
void gameUpdate(const float delta) {
|
||||||
gameTimeUpdate(delta);
|
gameTimeUpdate(delta);
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
|
serverUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gameDispose() {
|
||||||
|
serverDispose();
|
||||||
}
|
}
|
@ -18,4 +18,9 @@ void gameInit();
|
|||||||
*
|
*
|
||||||
* @param delta Game time update delta since last tick.
|
* @param delta Game time update delta since last tick.
|
||||||
*/
|
*/
|
||||||
void gameUpdate(const float_t delta);
|
void gameUpdate(const float_t delta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes the game.
|
||||||
|
*/
|
||||||
|
void gameDispose();
|
18
src/dusk/net/packet.h
Normal file
18
src/dusk/net/packet.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
PACKET_TYPE_HELLO,
|
||||||
|
PACKET_TYPE_PING
|
||||||
|
} packettype_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
packettype_t type;
|
||||||
|
} packet_t;
|
14
src/dusk/server/CMakeLists.txt
Normal file
14
src/dusk/server/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# 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
|
||||||
|
serverlocal.c
|
||||||
|
serversingleplayer.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
77
src/dusk/server/server.c
Normal file
77
src/dusk/server/server.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
server_t SERVER;
|
||||||
|
|
||||||
|
void serverInit() {
|
||||||
|
memset(&SERVER, 0, sizeof(server_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverStart(const serverstart_t start) {
|
||||||
|
assertTrue(SERVER.state==SERVER_STATE_STOPPED, "Server is already running.");
|
||||||
|
|
||||||
|
SERVER.type = start.type;
|
||||||
|
SERVER.clientCount = 0;
|
||||||
|
|
||||||
|
switch(start.type) {
|
||||||
|
case SERVER_TYPE_SINGLE_PLAYER:
|
||||||
|
serverSinglePlayerStart(start.singlePlayer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVER_TYPE_LOCAL:
|
||||||
|
serverLocalStart(start.local);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVER_TYPE_REMOTE:
|
||||||
|
assertUnreachable("Remote server not implemented.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unknown server type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SERVER.state = SERVER_STATE_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverStop() {
|
||||||
|
assertTrue(SERVER.state == SERVER_STATE_RUNNING,"Server is already stopped.");
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < SERVER.clientCount; i++) {
|
||||||
|
clientDispose(&SERVER.clients[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(SERVER.type) {
|
||||||
|
case SERVER_TYPE_SINGLE_PLAYER:
|
||||||
|
assertUnreachable("Single player server not implemented.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVER_TYPE_LOCAL:
|
||||||
|
serverLocalStop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVER_TYPE_REMOTE:
|
||||||
|
assertUnreachable("Remote server not implemented.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unknown server type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SERVER.state = SERVER_STATE_STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverUpdate() {
|
||||||
|
if(SERVER.state == SERVER_STATE_STOPPED) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverDispose() {
|
||||||
|
if(SERVER.state == SERVER_STATE_RUNNING) serverStop();
|
||||||
|
}
|
53
src/dusk/server/server.h
Normal file
53
src/dusk/server/server.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "client/client.h"
|
||||||
|
#include "serversingleplayer.h"
|
||||||
|
#include "serverlocal.h"
|
||||||
|
|
||||||
|
#define SERVER_CLIENT_COUNT_MAX 4
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SERVER_TYPE_SINGLE_PLAYER = 0,
|
||||||
|
SERVER_TYPE_LOCAL = 1,
|
||||||
|
SERVER_TYPE_REMOTE = 2
|
||||||
|
} servertype_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SERVER_STATE_STOPPED = 0,
|
||||||
|
SERVER_STATE_RUNNING = 1
|
||||||
|
} serverstate_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
servertype_t type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
serversingleplayerstart_t singlePlayer;
|
||||||
|
serverlocalstart_t local;
|
||||||
|
};
|
||||||
|
} serverstart_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
serverstate_t state;
|
||||||
|
servertype_t type;
|
||||||
|
|
||||||
|
client_t clients[SERVER_CLIENT_COUNT_MAX];
|
||||||
|
uint8_t clientCount;
|
||||||
|
|
||||||
|
union {
|
||||||
|
serverlocal_t local;
|
||||||
|
};
|
||||||
|
} server_t;
|
||||||
|
|
||||||
|
extern server_t SERVER;
|
||||||
|
|
||||||
|
void serverInit();
|
||||||
|
void serverStart(const serverstart_t start);
|
||||||
|
void serverStop();
|
||||||
|
void serverUpdate();
|
||||||
|
void serverDispose();
|
127
src/dusk/server/serverlocal.c
Normal file
127
src/dusk/server/serverlocal.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* 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 "console/console.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
void serverLocalStart(const serverlocalstart_t start) {
|
||||||
|
//Create the socket
|
||||||
|
SERVER.local.sockDesc = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(SERVER.local.sockDesc < 0) {
|
||||||
|
assertUnreachable("Failed to create socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the socket to non-blocking mode
|
||||||
|
int flags = fcntl(SERVER.local.sockDesc, F_GETFL, 0);
|
||||||
|
fcntl(SERVER.local.sockDesc, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
|
||||||
|
//Bind the socket
|
||||||
|
SERVER.local.sockAddr.sin_family = AF_INET;
|
||||||
|
SERVER.local.sockAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
SERVER.local.sockAddr.sin_port = htons(start.port);
|
||||||
|
|
||||||
|
if(bind(
|
||||||
|
SERVER.local.sockDesc,
|
||||||
|
(struct sockaddr*)&SERVER.local.sockAddr,
|
||||||
|
sizeof(SERVER.local.sockAddr)
|
||||||
|
) < 0) {
|
||||||
|
assertUnreachable("Failed to bind socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Listen on the socket
|
||||||
|
if(listen(SERVER.local.sockDesc, 5) < 0) {
|
||||||
|
assertUnreachable("Failed to listen on socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin the server thread.
|
||||||
|
consolePrint("Server started.");
|
||||||
|
|
||||||
|
// Start the server thread
|
||||||
|
SERVER.local.threadState = SERVER_LOCAL_THREAD_STATE_STARTING;
|
||||||
|
pthread_create(&SERVER.local.thread, NULL, serverLocalThread, NULL);
|
||||||
|
|
||||||
|
while(SERVER.local.threadState == SERVER_LOCAL_THREAD_STATE_STARTING) {
|
||||||
|
usleep(SERVER_LOCAL_THREAD_SLEEP_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverLocalStop() {
|
||||||
|
SERVER.local.threadState = SERVER_LOCAL_THREAD_STATE_STOPPING;
|
||||||
|
while(SERVER.local.threadState == SERVER_LOCAL_THREAD_STATE_STOPPING) {
|
||||||
|
usleep(SERVER_LOCAL_THREAD_SLEEP_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the server thread.
|
||||||
|
pthread_cancel(SERVER.local.thread);
|
||||||
|
|
||||||
|
//Close the socket
|
||||||
|
close(SERVER.local.sockDesc);
|
||||||
|
|
||||||
|
// End the server thread.
|
||||||
|
consolePrint("Server stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void * serverLocalThread(void *arg) {
|
||||||
|
SERVER.local.threadState = SERVER_LOCAL_THREAD_STATE_RUNNING;
|
||||||
|
|
||||||
|
fd_set readfds;
|
||||||
|
int32_t activity;
|
||||||
|
int32_t error;
|
||||||
|
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = SERVER_LOCAL_THREAD_ACCEPT_SLEEP_TIME;
|
||||||
|
|
||||||
|
while(SERVER.local.threadState == SERVER_LOCAL_THREAD_STATE_RUNNING) {
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(SERVER.local.sockDesc, &readfds);
|
||||||
|
|
||||||
|
activity = select(
|
||||||
|
SERVER.local.sockDesc + 1,
|
||||||
|
&readfds,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
if(activity < 0) assertUnreachable("Select error");
|
||||||
|
|
||||||
|
if(!FD_ISSET(SERVER.local.sockDesc, &readfds)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept incoming connections
|
||||||
|
int32_t clientSockDesc = accept(SERVER.local.sockDesc, NULL, NULL);
|
||||||
|
if(clientSockDesc < 0) {
|
||||||
|
printf("Failed to accept connection\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, is the server full?
|
||||||
|
if(SERVER.clientCount >= SERVER_CLIENT_COUNT_MAX) {
|
||||||
|
consolePrint("Server is full, rejecting connection.");
|
||||||
|
// TODO: Write a reason to client.
|
||||||
|
close(clientSockDesc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create client.
|
||||||
|
client_t *client = &SERVER.clients[SERVER.clientCount];
|
||||||
|
clientInit(client, (clientinit_t){
|
||||||
|
.type = CLIENT_TYPE_REMOTE,
|
||||||
|
.remote = {
|
||||||
|
.clientSockDesc = clientSockDesc
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SERVER.clientCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SERVER.local.threadState = SERVER_LOCAL_THREAD_STATE_STOPPED;
|
||||||
|
return NULL;
|
||||||
|
}
|
36
src/dusk/server/serverlocal.h
Normal file
36
src/dusk/server/serverlocal.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#define SERVER_LOCAL_PORT_DEFAULT 8080
|
||||||
|
#define SERVER_LOCAL_THREAD_SLEEP_TIME 1000
|
||||||
|
#define SERVER_LOCAL_THREAD_ACCEPT_SLEEP_TIME 60000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SERVER_LOCAL_THREAD_STATE_STOPPED = 0,
|
||||||
|
SERVER_LOCAL_THREAD_STATE_STARTING = 1,
|
||||||
|
SERVER_LOCAL_THREAD_STATE_RUNNING = 2,
|
||||||
|
SERVER_LOCAL_THREAD_STATE_STOPPING = 3
|
||||||
|
} serverlocalthreadstate_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t port;
|
||||||
|
} serverlocalstart_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t sockDesc;
|
||||||
|
struct sockaddr_in sockAddr;
|
||||||
|
pthread_t thread;
|
||||||
|
uint8_t threadState;
|
||||||
|
} serverlocal_t;
|
||||||
|
|
||||||
|
void serverLocalStart(const serverlocalstart_t start);
|
||||||
|
void serverLocalStop();
|
||||||
|
void * serverLocalThread(void *arg);
|
12
src/dusk/server/serversingleplayer.c
Normal file
12
src/dusk/server/serversingleplayer.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
void serverSinglePlayerStart(const serversingleplayerstart_t start) {
|
||||||
|
|
||||||
|
}
|
15
src/dusk/server/serversingleplayer.h
Normal file
15
src/dusk/server/serversingleplayer.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
int32_t nothing;
|
||||||
|
} serversingleplayerstart_t;
|
||||||
|
|
||||||
|
void serverSinglePlayerStart(const serversingleplayerstart_t start);
|
@ -6,7 +6,6 @@
|
|||||||
# Libs
|
# Libs
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
cglm
|
|
||||||
archive_static
|
archive_static
|
||||||
m
|
m
|
||||||
spng_static
|
spng_static
|
||||||
|
@ -9,12 +9,7 @@
|
|||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
#include "duskglimpl.h"
|
#include "duskglimpl.h"
|
||||||
|
|
||||||
#include <cglm/cglm.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <float.h>
|
|
||||||
|
|
||||||
typedef float float_t;
|
|
||||||
typedef double double_t;
|
|
||||||
|
|
||||||
extern char_t EXECUTABLE_PATH[];
|
extern char_t EXECUTABLE_PATH[];
|
||||||
extern char_t EXECUTABLE_DIRECTORY[];
|
extern char_t EXECUTABLE_DIRECTORY[];
|
@ -64,6 +64,7 @@ int32_t main(int32_t argc, char_t **argv) {
|
|||||||
renderDispose();
|
renderDispose();
|
||||||
windowDispose();
|
windowDispose();
|
||||||
assetDispose();
|
assetDispose();
|
||||||
|
gameDispose();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Reference in New Issue
Block a user