About to make the processing queue lock properly
This commit is contained in:
@ -27,5 +27,6 @@ add_subdirectory(assert)
|
|||||||
add_subdirectory(client)
|
add_subdirectory(client)
|
||||||
add_subdirectory(console)
|
add_subdirectory(console)
|
||||||
add_subdirectory(error)
|
add_subdirectory(error)
|
||||||
|
add_subdirectory(packet)
|
||||||
add_subdirectory(server)
|
add_subdirectory(server)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
@ -75,6 +75,12 @@ void clientDisconnect() {
|
|||||||
default:
|
default:
|
||||||
assertUnreachable("Invalid client type");
|
assertUnreachable("Invalid client type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consolePrint("Client disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientProcess() {
|
||||||
|
if(CLIENT.state == CLIENT_STATE_DISCONNECTED) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clientDispose() {
|
void clientDispose() {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "client/networked/networkedclient.h"
|
#include "client/networked/networkedclient.h"
|
||||||
|
#include "packet/packetqueue.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CLIENT_TYPE_NETWORKED,
|
CLIENT_TYPE_NETWORKED,
|
||||||
@ -30,6 +31,7 @@ typedef struct clientconnect_s {
|
|||||||
typedef struct client_s {
|
typedef struct client_s {
|
||||||
clientstate_t state;
|
clientstate_t state;
|
||||||
clienttype_t type;
|
clienttype_t type;
|
||||||
|
packetqueue_t packetQueue;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
networkedclient_t networked;
|
networkedclient_t networked;
|
||||||
|
@ -96,7 +96,7 @@ errorret_t networkedClientConnect(
|
|||||||
ret = pthread_create(
|
ret = pthread_create(
|
||||||
&client->networked.thread,
|
&client->networked.thread,
|
||||||
NULL,
|
NULL,
|
||||||
clientThread,
|
networkedClientThread,
|
||||||
client
|
client
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -123,9 +123,9 @@ void networkedClientDisconnect(client_t *client) {
|
|||||||
|
|
||||||
int32_t maxAttempts = 0;
|
int32_t maxAttempts = 0;
|
||||||
while(client->state == CLIENT_STATE_DISCONNECTING) {
|
while(client->state == CLIENT_STATE_DISCONNECTING) {
|
||||||
usleep(1000);
|
usleep(100 * 1000);// Sleep for 100ms
|
||||||
maxAttempts++;
|
maxAttempts++;
|
||||||
if(maxAttempts > 15) {
|
if(maxAttempts > 5) {
|
||||||
consolePrint("Client disconnect timed out, force closing");
|
consolePrint("Client disconnect timed out, force closing");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -142,8 +142,6 @@ void networkedClientDisconnect(client_t *client) {
|
|||||||
close(client->networked.socket);
|
close(client->networked.socket);
|
||||||
client->networked.socket = 0;
|
client->networked.socket = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
consolePrint("Client disconnected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t networkedClientWrite(
|
errorret_t networkedClientWrite(
|
||||||
@ -237,10 +235,11 @@ errorret_t networkedClientReadPacket(
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * clientThread(void *arg) {
|
void * networkedClientThread(void *arg) {
|
||||||
assertNotNull(arg, "Client thread argument is NULL");
|
assertNotNull(arg, "Client thread argument is NULL");
|
||||||
assertNotMainThread("Client thread must not be on main thread");
|
assertNotMainThread("Client thread must not be on main thread");
|
||||||
|
|
||||||
|
packet_t packet;
|
||||||
client_t *client = (client_t *)arg;
|
client_t *client = (client_t *)arg;
|
||||||
assertTrue(
|
assertTrue(
|
||||||
client->type == CLIENT_TYPE_NETWORKED,
|
client->type == CLIENT_TYPE_NETWORKED,
|
||||||
@ -254,8 +253,14 @@ void * clientThread(void *arg) {
|
|||||||
client->state = CLIENT_STATE_CONNECTED;
|
client->state = CLIENT_STATE_CONNECTED;
|
||||||
|
|
||||||
while(client->state == CLIENT_STATE_CONNECTED) {
|
while(client->state == CLIENT_STATE_CONNECTED) {
|
||||||
usleep(1000 * 1000);
|
usleep(1000*1000);// Sleep for 1 second
|
||||||
|
|
||||||
|
packetPingCreate(&packet);
|
||||||
|
packetQueuePushOutbound(
|
||||||
|
&client->packetQueue,
|
||||||
|
&packet
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Client thread exiting\n");
|
client->state = CLIENT_STATE_DISCONNECTED;
|
||||||
}
|
}
|
@ -8,7 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include "server/packet/packet.h"
|
#include "packet/packet.h"
|
||||||
|
|
||||||
typedef struct client_s client_t;
|
typedef struct client_s client_t;
|
||||||
typedef struct clientconnect_s clientconnect_t;
|
typedef struct clientconnect_s clientconnect_t;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
#include "server/server.h"
|
#include "server/server.h"
|
||||||
|
#include "util/random.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ void cmdExit(const consolecmdexec_t *exec) {
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
assertInit();
|
assertInit();
|
||||||
consoleInit();
|
consoleInit();
|
||||||
|
randomInit();
|
||||||
clientInit();
|
clientInit();
|
||||||
serverInit();
|
serverInit();
|
||||||
|
|
||||||
|
@ -9,4 +9,6 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
packet.c
|
packet.c
|
||||||
packetwelcome.c
|
packetwelcome.c
|
||||||
packetdisconnect.c
|
packetdisconnect.c
|
||||||
|
packetqueue.c
|
||||||
|
packetping.c
|
||||||
)
|
)
|
@ -9,16 +9,19 @@
|
|||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
#include "packetwelcome.h"
|
#include "packetwelcome.h"
|
||||||
#include "packetdisconnect.h"
|
#include "packetdisconnect.h"
|
||||||
|
#include "packetping.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PACKET_TYPE_INVALID = 0,
|
PACKET_TYPE_INVALID = 0,
|
||||||
PACKET_TYPE_WELCOME = 1,
|
PACKET_TYPE_WELCOME = 1,
|
||||||
PACKET_TYPE_DISCONNECT = 2,
|
PACKET_TYPE_DISCONNECT = 2,
|
||||||
|
PACKET_TYPE_PING = 3,
|
||||||
} packettype_t;
|
} packettype_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
packetwelcome_t welcome;
|
packetwelcome_t welcome;
|
||||||
packetdisconnect_t disconnect;
|
packetdisconnect_t disconnect;
|
||||||
|
packetping_t ping;
|
||||||
} packetdata_t;
|
} packetdata_t;
|
||||||
|
|
||||||
typedef struct packet_s {
|
typedef struct packet_s {
|
26
src/packet/packetping.c
Normal file
26
src/packet/packetping.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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 packetPingCreate(packet_t *packet) {
|
||||||
|
packetInit(packet, PACKET_TYPE_PING, sizeof(packetping_t));
|
||||||
|
packet->data.ping.number = GetRandomValue(0, INT32_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t packetPingClient(packet_t *packet) {
|
||||||
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
28
src/packet/packetping.h
Normal file
28
src/packet/packetping.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
int32_t number;
|
||||||
|
} packetping_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ping packet.
|
||||||
|
*
|
||||||
|
* @param packet Pointer to the packet structure to initialize.
|
||||||
|
*/
|
||||||
|
void packetPingCreate(packet_t *packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a ping packet received FROM a server INTO a client.
|
||||||
|
*
|
||||||
|
* @param packet Pointer to the packet structure to handle.
|
||||||
|
* @return ERROR_OK on success, or an error code on failure.
|
||||||
|
*/
|
||||||
|
errorret_t packetPingClient(packet_t *packet);
|
35
src/packet/packetqueue.c
Normal file
35
src/packet/packetqueue.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void packetQueuePushIn(packetqueue_t *queue, const packet_t *packet) {
|
||||||
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
assertTrue(
|
||||||
|
queue->packetsInCount < PACKET_QUEUE_MAX_SIZE, "Packet queue is full"
|
||||||
|
);
|
||||||
|
|
||||||
|
queue->packetsIn[queue->packetsInCount++] = *packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet) {
|
||||||
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
assertTrue(
|
||||||
|
queue->packetsOutCount < PACKET_QUEUE_MAX_SIZE, "Packet queue is full"
|
||||||
|
);
|
||||||
|
|
||||||
|
queue->packetsOut[queue->packetsOutCount++] = *packet;
|
||||||
|
}
|
49
src/packet/packetqueue.h
Normal file
49
src/packet/packetqueue.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "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;
|
||||||
|
|
||||||
|
// Mutex for thread safety
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
// Condition variables for signaling
|
||||||
|
pthread_cond_t condIn;
|
||||||
|
pthread_cond_t condOut;
|
||||||
|
// Thread ID of the thread that owns the queue
|
||||||
|
|
||||||
|
} 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 from 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);
|
@ -11,6 +11,5 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(packet)
|
|
||||||
add_subdirectory(networked)
|
add_subdirectory(networked)
|
||||||
add_subdirectory(singleplayer)
|
add_subdirectory(singleplayer)
|
@ -113,7 +113,7 @@ void networkedServerClientCloseOnThread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t networkedServerClientRead(
|
ssize_t networkedServerClientRead(
|
||||||
serverclient_t * client,
|
const serverclient_t * client,
|
||||||
uint8_t *buffer,
|
uint8_t *buffer,
|
||||||
const size_t len
|
const size_t len
|
||||||
) {
|
) {
|
||||||
@ -136,6 +136,60 @@ ssize_t networkedServerClientRead(
|
|||||||
return recv(client->networked.socket, buffer, len, 0);
|
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(
|
errorret_t networkedServerClientWrite(
|
||||||
serverclient_t * client,
|
serverclient_t * client,
|
||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
@ -225,18 +279,17 @@ void * networkedServerClientThread(void *arg) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start listening for packets.
|
||||||
client->state = SERVER_CLIENT_STATE_CONNECTED;
|
client->state = SERVER_CLIENT_STATE_CONNECTED;
|
||||||
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
||||||
read = networkedServerClientRead(client, buffer, sizeof(buffer));
|
err = networkedServerClientReadPacket(client, &packet);
|
||||||
|
if(err != ERROR_OK) {
|
||||||
if(read <= 0) {
|
errorPrint();
|
||||||
networkedServerClientCloseOnThread(client, "Failed to receive data");
|
networkedServerClientCloseOnThread(client, "Failed to read packet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[read] = '\0'; // Null-terminate the string
|
printf("Received packet type %d\n", packet.type);
|
||||||
consolePrint("Received: %s", buffer);
|
|
||||||
|
|
||||||
|
|
||||||
if(SERVER.state != SERVER_STATE_RUNNING) {
|
if(SERVER.state != SERVER_STATE_RUNNING) {
|
||||||
packetDisconnectCreate(
|
packetDisconnectCreate(
|
||||||
|
@ -60,7 +60,7 @@ void networkedServerClientCloseOnThread(
|
|||||||
* @return Number of bytes received. 0 or less indicates an error.
|
* @return Number of bytes received. 0 or less indicates an error.
|
||||||
*/
|
*/
|
||||||
ssize_t networkedServerClientRead(
|
ssize_t networkedServerClientRead(
|
||||||
serverclient_t * client,
|
const serverclient_t * client,
|
||||||
uint8_t *buffer,
|
uint8_t *buffer,
|
||||||
const size_t len
|
const size_t len
|
||||||
);
|
);
|
||||||
|
@ -20,10 +20,12 @@ errorret_t serverClientAccept(
|
|||||||
assertNotMainThread("Server client accept must not be main thread");
|
assertNotMainThread("Server client accept must not be main thread");
|
||||||
|
|
||||||
client->server = accept.server;
|
client->server = accept.server;
|
||||||
|
packetQueueInit(&client->packetQueue);
|
||||||
|
|
||||||
switch(accept.server->type) {
|
switch(accept.server->type) {
|
||||||
case SERVER_TYPE_NETWORKED:
|
case SERVER_TYPE_NETWORKED:
|
||||||
ret = networkedServerClientAccept(client, accept);
|
ret = networkedServerClientAccept(client, accept);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assertUnreachable("Unknown server type");
|
assertUnreachable("Unknown server type");
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "server/packet/packet.h"
|
#include "packet/packet.h"
|
||||||
#include "server/networked/networkedserverclient.h"
|
#include "server/networked/networkedserverclient.h"
|
||||||
|
#include "packet/packetqueue.h"
|
||||||
|
|
||||||
typedef struct server_s server_t;
|
typedef struct server_s server_t;
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ typedef struct serverclientaccept_s {
|
|||||||
typedef struct serverclient_s {
|
typedef struct serverclient_s {
|
||||||
server_t *server;
|
server_t *server;
|
||||||
serverclientstate_t state;
|
serverclientstate_t state;
|
||||||
|
packetqueue_t packetQueue;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
networkedserverclient_t networked;
|
networkedserverclient_t networked;
|
||||||
};
|
};
|
||||||
|
@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
memory.c
|
memory.c
|
||||||
string.c
|
string.c
|
||||||
|
random.c
|
||||||
)
|
)
|
27
src/util/random.c
Normal file
27
src/util/random.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "random.h"
|
||||||
|
#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;
|
||||||
|
}
|
43
src/util/random.h
Normal file
43
src/util/random.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the random number generator with a random seed.
|
||||||
|
*
|
||||||
|
* This function should be called once at the start of the program to
|
||||||
|
* 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);
|
Reference in New Issue
Block a user