Implemented proper thread sleeping and additional output thread
- Replaced previous inefficient "spin-waiting" with proper thread sleeping. - Added threading primitives to the queue type to enable this. - Added additional thread for output management. - Miscellanous cleanup and restructuring.
This commit is contained in:
parent
15d82f59ee
commit
6a653c75b9
|
@ -14,6 +14,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
#include "../queue.h"
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
#include "../playerdata.h"
|
#include "../playerdata.h"
|
||||||
#include "../texteffects.h"
|
#include "../texteffects.h"
|
||||||
|
@ -225,7 +226,7 @@ int main(int argc, char ** argv)
|
||||||
serverAddress.sin_port = htons(port);
|
serverAddress.sin_port = htons(port);
|
||||||
|
|
||||||
// Connect the server and client sockets, Kronk:
|
// Connect the server and client sockets, Kronk:
|
||||||
if (connect(socketFileDesc, (sockaddr*)&serverAddress, sizeof(serverAddress)) != 0)
|
if (connect(socketFileDesc, (sockaddr*)&serverAddress, sizeof(serverAddress)) != 0)
|
||||||
{
|
{
|
||||||
slowPrint("Connection with the Silverkin Industries Comm-Link Server Failed:\nPlease contact your service representative.\n", characterDelay);
|
slowPrint("Connection with the Silverkin Industries Comm-Link Server Failed:\nPlease contact your service representative.\n", characterDelay);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// =======================
|
// =======================
|
||||||
|
|
||||||
// Thread function which runs the main game loop, given the needed parameters:
|
// Thread function which runs the main game loop, given the needed parameters:
|
||||||
void * gameLogicLoop(void * parameters)
|
void * gameLogicHandler(void * parameters)
|
||||||
{
|
{
|
||||||
gameLogicParameters * threadParameters = parameters;
|
gameLogicParameters * threadParameters = parameters;
|
||||||
inputMessage * currentInput = NULL;
|
inputMessage * currentInput = NULL;
|
||||||
|
@ -25,11 +25,17 @@ void * gameLogicLoop(void * parameters)
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// Evaluate remaining commands:
|
// Evaluate remaining commands:
|
||||||
if(commandQueue->currentLength != 0)
|
while(commandQueue->currentLength != 0)
|
||||||
{
|
{
|
||||||
evaluateNextCommand(threadParameters, commandQueue);
|
evaluateNextCommand(threadParameters, commandQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait if there is nothing to do:
|
||||||
|
if(threadParameters->inputQueue->itemCount == 0)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&threadParameters->inputQueue->condition, &threadParameters->inputQueue->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for new messages and pop them off the queue:
|
// Check for new messages and pop them off the queue:
|
||||||
if(threadParameters->inputQueue->itemCount != 0)
|
if(threadParameters->inputQueue->itemCount != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,35 +8,10 @@
|
||||||
#include "playerdata.h"
|
#include "playerdata.h"
|
||||||
#include "inputoutput.h"
|
#include "inputoutput.h"
|
||||||
|
|
||||||
// Let the compiler know there will be structs defined elsewhere:
|
// ========================
|
||||||
typedef struct queue queue;
|
// -=[ Data Structures ]=-:
|
||||||
|
// ========================
|
||||||
|
|
||||||
// =======================
|
|
||||||
// -=[ Main Game Loop ]=-:
|
|
||||||
// =======================
|
|
||||||
|
|
||||||
// A data-structure containing the needed parameters for a main game loop:
|
|
||||||
typedef struct gameLogicParameters
|
|
||||||
{
|
|
||||||
// Players:
|
|
||||||
int * playerCount;
|
|
||||||
playerInfo * connectedPlayers;
|
|
||||||
|
|
||||||
// Queues:
|
|
||||||
queue * inputQueue;
|
|
||||||
queue * outputQueue;
|
|
||||||
|
|
||||||
// Lists:
|
|
||||||
list * areaList;
|
|
||||||
list * globalSkillList;
|
|
||||||
} gameLogicParameters;
|
|
||||||
|
|
||||||
// Thread function which runs the main game loop, given the needed parameters:
|
|
||||||
void * gameLogicLoop(void * parameters);
|
|
||||||
|
|
||||||
// ======================
|
|
||||||
// -=[ Command Queue ]=-:
|
|
||||||
// ======================
|
|
||||||
typedef struct commandEvent commandEvent;
|
typedef struct commandEvent commandEvent;
|
||||||
typedef struct commandEvent
|
typedef struct commandEvent
|
||||||
{
|
{
|
||||||
|
@ -56,6 +31,32 @@ typedef struct commandQueue
|
||||||
commandEvent * front;
|
commandEvent * front;
|
||||||
} commandQueue;
|
} commandQueue;
|
||||||
|
|
||||||
|
// A data-structure containing the needed parameters for a main game loop:
|
||||||
|
typedef struct gameLogicParameters
|
||||||
|
{
|
||||||
|
// Players:
|
||||||
|
int * playerCount;
|
||||||
|
playerInfo * connectedPlayers;
|
||||||
|
|
||||||
|
// Queues:
|
||||||
|
queue * inputQueue;
|
||||||
|
queue * outputQueue;
|
||||||
|
|
||||||
|
// Lists:
|
||||||
|
list * areaList;
|
||||||
|
list * globalSkillList;
|
||||||
|
} gameLogicParameters;
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// -=[ Functions ]=-:
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
// Player movement:
|
||||||
|
int movePlayerToArea(playerInfo * player, char * requestedPath);
|
||||||
|
|
||||||
|
// Thread function which runs the main game loop, given the needed parameters:
|
||||||
|
void * gameLogicHandler(void * parameters);
|
||||||
|
|
||||||
// Create a commandQueue:
|
// Create a commandQueue:
|
||||||
commandQueue * createCommandQueue(void);
|
commandQueue * createCommandQueue(void);
|
||||||
|
|
||||||
|
@ -82,9 +83,6 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue);
|
||||||
// -=[ Gameplay Primitives ]=-:
|
// -=[ Gameplay Primitives ]=-:
|
||||||
// ============================
|
// ============================
|
||||||
|
|
||||||
// Player movement:
|
|
||||||
int movePlayerToArea(playerInfo * player, char * requestedPath);
|
|
||||||
|
|
||||||
typedef enum outcome
|
typedef enum outcome
|
||||||
{
|
{
|
||||||
CRITICAL_FAILURE,
|
CRITICAL_FAILURE,
|
||||||
|
@ -94,6 +92,9 @@ typedef enum outcome
|
||||||
ERROR
|
ERROR
|
||||||
} outcome;
|
} outcome;
|
||||||
|
|
||||||
|
// Player movement:
|
||||||
|
int movePlayerToArea(playerInfo * player, char * requestedPath);
|
||||||
|
|
||||||
// Run a stat check:
|
// Run a stat check:
|
||||||
outcome statCheck(playerInfo * player, int chance, coreStat statToCheck);
|
outcome statCheck(playerInfo * player, int chance, coreStat statToCheck);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "playerdata.h"
|
#include "playerdata.h"
|
||||||
#include "inputoutput.h"
|
#include "inputoutput.h"
|
||||||
|
@ -46,6 +49,7 @@ int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToM
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate and initialize an outputMessage targeted to a variable amount of players:
|
||||||
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientsCount)
|
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientsCount)
|
||||||
{
|
{
|
||||||
// Allocate a new output message:
|
// Allocate a new output message:
|
||||||
|
@ -64,10 +68,72 @@ outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, player
|
||||||
return newOutputMessage;
|
return newOutputMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A function for the output thread, which sends queued messages:
|
||||||
|
void * outputThreadHandler(void * parameters)
|
||||||
|
{
|
||||||
|
outputThreadParameters * variables = parameters;
|
||||||
|
queue * outputQueue = variables->outputQueue;
|
||||||
|
gnutls_session_t * tlssessions = variables->tlssessions;
|
||||||
|
playerInfo * connectedPlayers = variables->connectedPlayers;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
if(outputQueue->itemCount == 0)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&outputQueue->condition, &outputQueue->mutex);
|
||||||
|
}
|
||||||
|
// Run through the output queue and send all unused messages:
|
||||||
|
while(outputQueue->itemCount != 0)
|
||||||
|
{
|
||||||
|
// Wait until the queue unlocks:
|
||||||
|
while(outputQueue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
|
outputQueue->lock = true;
|
||||||
|
|
||||||
|
// Get a message off the queue:
|
||||||
|
outputMessage * message = peekQueue(outputQueue)->data.outputMessage;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
|
outputQueue->lock = false;
|
||||||
|
|
||||||
|
// If the first target is set to NULL, it's intended for all connected:
|
||||||
|
if(message->recipientsCount == 0)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
|
{
|
||||||
|
messageSend(tlssessions[index], message->content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, send it only to the targeted players:
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int targetIndex = 0;
|
||||||
|
for(int index = 0; index < PLAYERCOUNT; index++)
|
||||||
|
{
|
||||||
|
if(targetIndex == message->recipientsCount)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(&connectedPlayers[index] == message->recipients[targetIndex])
|
||||||
|
{
|
||||||
|
targetIndex++;
|
||||||
|
messageSend(tlssessions[index], message->content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the output message from the queue:
|
||||||
|
popQueue(outputQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanatize user input to ensure it's okay to process:
|
||||||
void userInputSanatize(char * inputString, int length)
|
void userInputSanatize(char * inputString, int length)
|
||||||
{
|
{
|
||||||
for(int index = 0; index <= length; index++)
|
for(int index = 0; index <= length; index++)
|
||||||
{
|
{
|
||||||
|
// If it's not a printable character, it has no buisness being here:
|
||||||
if(!isprint(inputString[index]))
|
if(!isprint(inputString[index]))
|
||||||
{
|
{
|
||||||
inputString[index] = '\n';
|
inputString[index] = '\n';
|
||||||
|
@ -75,18 +141,22 @@ void userInputSanatize(char * inputString, int length)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make sure it's null-terminated:
|
||||||
inputString[length - 1] = '\0';
|
inputString[length - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanatize user names so they display correctly;
|
||||||
void userNameSanatize(char * inputString, int length)
|
void userNameSanatize(char * inputString, int length)
|
||||||
{
|
{
|
||||||
for(int index = 0; index <= length; index++)
|
for(int index = 0; index <= length; index++)
|
||||||
{
|
{
|
||||||
|
// If it's not a printable character, it has no buisness being here:
|
||||||
if(!isprint(inputString[index]))
|
if(!isprint(inputString[index]))
|
||||||
{
|
{
|
||||||
inputString[index] = '\0';
|
inputString[index] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make sure it's null-terminated:
|
||||||
inputString[length - 1] = '\0';
|
inputString[length - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,33 +4,36 @@
|
||||||
#ifndef INPUTOUTPUT_H
|
#ifndef INPUTOUTPUT_H
|
||||||
#define INPUTOUTPUT_H
|
#define INPUTOUTPUT_H
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "constants.h"
|
#include <stdbool.h>
|
||||||
#include "playerdata.h"
|
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
// A message datastructure containing a user/character name and the content:
|
#include "queue.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "playerdata.h"
|
||||||
|
|
||||||
|
// Let the compiler know there will be structs defined elsewhere:
|
||||||
|
typedef struct queue queue;
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// -=[ Data Structures ]=-:
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
// Contains a character/player name and the content of a message:
|
||||||
typedef struct userMessage
|
typedef struct userMessage
|
||||||
{
|
{
|
||||||
char senderName[32];
|
char senderName[32];
|
||||||
char messageContent[MAX];
|
char messageContent[MAX];
|
||||||
} userMessage;
|
} userMessage;
|
||||||
|
|
||||||
// ==================
|
// Contains a userMessage and a pointer to the playerInfo of the connection which sent it:
|
||||||
// -=[Message I/O]=-:
|
typedef struct inputMessage
|
||||||
// ==================
|
{
|
||||||
|
playerInfo * sender;
|
||||||
|
userMessage * content;
|
||||||
|
} inputMessage;
|
||||||
|
|
||||||
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
// Contains a userMessage and pointers to the playerInfo of the recipients and the number of them:
|
||||||
int messageSend(gnutls_session_t receivingSession, userMessage * messageToSend);
|
|
||||||
|
|
||||||
// Receives a message from a given TLS session, wraps the calls to gnutls_read:
|
|
||||||
int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage);
|
|
||||||
|
|
||||||
// ===================
|
|
||||||
// -=[Output Queue]=-:
|
|
||||||
// ===================
|
|
||||||
typedef struct outputMessage outputMessage;
|
|
||||||
typedef struct outputMessage
|
typedef struct outputMessage
|
||||||
{
|
{
|
||||||
int recipientsCount;
|
int recipientsCount;
|
||||||
|
@ -38,27 +41,34 @@ typedef struct outputMessage
|
||||||
playerInfo ** recipients;
|
playerInfo ** recipients;
|
||||||
} outputMessage;
|
} outputMessage;
|
||||||
|
|
||||||
|
// Contains the relevant parameters for the outputThreadLoop function:
|
||||||
|
typedef struct outputThreadParameters
|
||||||
|
{
|
||||||
|
queue * outputQueue;
|
||||||
|
gnutls_session_t * tlssessions;
|
||||||
|
playerInfo * connectedPlayers;
|
||||||
|
} outputThreadParameters;
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// -=[ Functions ]=-:
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
||||||
|
int messageSend(gnutls_session_t receivingSession, userMessage * messageToSend);
|
||||||
|
|
||||||
|
// Receives a message from a given TLS session, wraps the calls to gnutls_read:
|
||||||
|
int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage);
|
||||||
|
|
||||||
// Create a targetedOutput message to be delivered to the players pointed to in recipients:
|
// Create a targetedOutput message to be delivered to the players pointed to in recipients:
|
||||||
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientCount);
|
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientCount);
|
||||||
|
|
||||||
// ==================
|
// A function for the output thread, which sends queued messages:
|
||||||
// -=[Input Queue]=-:
|
void * outputThreadHandler(void * parameters);
|
||||||
// ==================
|
|
||||||
typedef struct inputMessage inputMessage;
|
|
||||||
typedef struct inputMessage
|
|
||||||
{
|
|
||||||
playerInfo * sender;
|
|
||||||
userMessage * content;
|
|
||||||
} inputMessage;
|
|
||||||
|
|
||||||
// =======================
|
// Sanatize user input to ensure it's okay to process:
|
||||||
// -=[Input Sanitation]=-:
|
|
||||||
// =======================
|
|
||||||
|
|
||||||
// Sanatize user input to ensure it's okay to send to the server:
|
|
||||||
void userInputSanatize(char * inputString, int length);
|
void userInputSanatize(char * inputString, int length);
|
||||||
|
|
||||||
// Sanatize user names so they display correctly;
|
// Sanatize user names so they display correctly:
|
||||||
void userNameSanatize(char * inputString, int length);
|
void userNameSanatize(char * inputString, int length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
15
src/queue.c
15
src/queue.c
|
@ -1,5 +1,6 @@
|
||||||
// queue.c: Implements the queue data type and associated functions for SilverMUD.
|
// queue.c: Implements the queue data type and associated functions for SilverMUD.
|
||||||
// Barry Kane, 2022
|
// Barry Kane, 2022
|
||||||
|
#include <pthread.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
// Allocates and instantiates a queue:
|
// Allocates and instantiates a queue:
|
||||||
|
@ -13,6 +14,10 @@ queue * createQueue(void)
|
||||||
newQueue->front = NULL;
|
newQueue->front = NULL;
|
||||||
newQueue->back = NULL;
|
newQueue->back = NULL;
|
||||||
|
|
||||||
|
// Create the threading constructs:
|
||||||
|
newQueue->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
newQueue->condition = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
// Return the pointer to the new queue:
|
// Return the pointer to the new queue:
|
||||||
return newQueue;
|
return newQueue;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +32,10 @@ void destroyQueue(queue ** queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deallocate the queue:
|
// Deallocate the queue:
|
||||||
free(*queue);
|
free(*queue);
|
||||||
|
|
||||||
|
// Point the queue pointer to NULL;
|
||||||
|
*queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the data at the front of the given queue:
|
// Returns the data at the front of the given queue:
|
||||||
|
@ -41,7 +49,7 @@ void popQueue(queue * queue)
|
||||||
{
|
{
|
||||||
// Check if the queue is locked, and wait:
|
// Check if the queue is locked, and wait:
|
||||||
while (queue->lock);
|
while (queue->lock);
|
||||||
|
|
||||||
// Lock the queue:
|
// Lock the queue:
|
||||||
queue->lock = true;
|
queue->lock = true;
|
||||||
|
|
||||||
|
@ -203,4 +211,7 @@ void pushQueue(queue * queue, void * data, queueDataType type)
|
||||||
|
|
||||||
// Unlock the queue:
|
// Unlock the queue:
|
||||||
queue->lock = false;
|
queue->lock = false;
|
||||||
|
|
||||||
|
// Flag that the queue was modified:
|
||||||
|
pthread_cond_broadcast(&queue->condition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
// -=[ Data Structures ]=-:
|
// -=[ Data Structures ]=-:
|
||||||
// ========================
|
// ========================
|
||||||
|
|
||||||
|
// Let the compiler know there will be structs defined elsewhere:
|
||||||
|
typedef struct queue queue;
|
||||||
|
|
||||||
typedef enum queueDataType
|
typedef enum queueDataType
|
||||||
{
|
{
|
||||||
EVENT,
|
EVENT,
|
||||||
|
@ -38,6 +41,8 @@ typedef struct queue
|
||||||
size_t itemCount;
|
size_t itemCount;
|
||||||
queueNode * front;
|
queueNode * front;
|
||||||
queueNode * back;
|
queueNode * back;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t condition;
|
||||||
} queue;
|
} queue;
|
||||||
|
|
||||||
// ========================
|
// ========================
|
||||||
|
|
|
@ -40,7 +40,7 @@ int main(int argc, char ** argv)
|
||||||
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
||||||
socketCheck, activityCheck, returnVal;
|
socketCheck, activityCheck, returnVal;
|
||||||
fd_set connectedClients;
|
fd_set connectedClients;
|
||||||
pthread_t gameLogicThread;
|
pthread_t gameLogicThread, outputThread;
|
||||||
int clientSockets[PLAYERCOUNT];
|
int clientSockets[PLAYERCOUNT];
|
||||||
userMessage sendBuffer, receiveBuffer;
|
userMessage sendBuffer, receiveBuffer;
|
||||||
playerInfo connectedPlayers[PLAYERCOUNT];
|
playerInfo connectedPlayers[PLAYERCOUNT];
|
||||||
|
@ -54,11 +54,11 @@ int main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
switch(currentopt)
|
switch(currentopt)
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
{
|
{
|
||||||
delay = atoi(optarg);
|
delay = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,6 @@ int main(int argc, char ** argv)
|
||||||
slowPrint("\tSocket Creation is:\t\033[32;40mGREEN.\033[0m\n", delay);
|
slowPrint("\tSocket Creation is:\t\033[32;40mGREEN.\033[0m\n", delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
bzero(&serverAddress, sizeof(serverAddress));
|
bzero(&serverAddress, sizeof(serverAddress));
|
||||||
|
|
||||||
// Assign IP and port:
|
// Assign IP and port:
|
||||||
|
@ -207,11 +206,19 @@ int main(int argc, char ** argv)
|
||||||
gameLogicThreadParameters->outputQueue = outputQueue;
|
gameLogicThreadParameters->outputQueue = outputQueue;
|
||||||
gameLogicThreadParameters->inputQueue = inputQueue;
|
gameLogicThreadParameters->inputQueue = inputQueue;
|
||||||
gameLogicThreadParameters->areaList = areas;
|
gameLogicThreadParameters->areaList = areas;
|
||||||
pthread_create(&gameLogicThread, NULL, &gameLogicLoop, gameLogicThreadParameters);
|
pthread_create(&gameLogicThread, NULL, &gameLogicHandler, gameLogicThreadParameters);
|
||||||
|
|
||||||
slowPrint("\tEvent Thread is:\t\033[32;40mGREEN.\033[0m\n", delay);
|
slowPrint("\tEvent Thread is:\t\033[32;40mGREEN.\033[0m\n", delay);
|
||||||
slowPrint("=====\n", delay);
|
|
||||||
struct timeval timeout = {0, 500};
|
// Prepare the output queue thread:
|
||||||
|
outputThreadParameters * outputParameters = malloc(sizeof(outputThreadParameters));
|
||||||
|
outputParameters->outputQueue = outputQueue;
|
||||||
|
outputParameters->tlssessions = tlssessions;
|
||||||
|
outputParameters->connectedPlayers = connectedPlayers;
|
||||||
|
pthread_create(&outputThread, NULL, &outputThreadHandler, outputParameters);
|
||||||
|
|
||||||
|
slowPrint("\tOutput Thread is:\t\033[32;40mGREEN.\033[0m\n", delay);
|
||||||
|
slowPrint("=====\n", delay);
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
@ -239,7 +246,7 @@ int main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if a connection is ready to be interacted with:
|
// See if a connection is ready to be interacted with:
|
||||||
activityCheck = select((clientsAmount + 1), &connectedClients, NULL, NULL, &timeout);
|
activityCheck = select((clientsAmount + 1), &connectedClients, NULL, NULL, NULL);
|
||||||
|
|
||||||
// Check if select() worked:
|
// Check if select() worked:
|
||||||
if ((activityCheck < 0) && (errno != EINTR))
|
if ((activityCheck < 0) && (errno != EINTR))
|
||||||
|
@ -286,7 +293,6 @@ int main(int argc, char ** argv)
|
||||||
|
|
||||||
// Push the new message onto the queue:
|
// Push the new message onto the queue:
|
||||||
pushQueue(inputQueue, newMessage, INPUT_MESSAGE);
|
pushQueue(inputQueue, newMessage, INPUT_MESSAGE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,52 +346,8 @@ int main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run through the output queue and send all unused messages:
|
|
||||||
while(outputQueue->itemCount != 0)
|
|
||||||
{
|
|
||||||
// Wait until the queue unlocks:
|
|
||||||
while(outputQueue->lock);
|
|
||||||
|
|
||||||
// Lock the queue:
|
|
||||||
outputQueue->lock = true;
|
|
||||||
|
|
||||||
// Get a message off the queue:
|
|
||||||
outputMessage * message = peekQueue(outputQueue)->data.outputMessage;
|
|
||||||
|
|
||||||
// Unlock the queue:
|
|
||||||
outputQueue->lock = false;
|
|
||||||
|
|
||||||
// If the first target is set to NULL, it's intended for all connected:
|
|
||||||
if(message->recipientsCount == 0)
|
|
||||||
{
|
|
||||||
for (int index = 0; index < PLAYERCOUNT; index++)
|
|
||||||
{
|
|
||||||
messageSend(tlssessions[index], message->content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, send it only to the targeted players:
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int targetIndex = 0;
|
|
||||||
for(int index = 0; index < PLAYERCOUNT; index++)
|
|
||||||
{
|
|
||||||
if(targetIndex == message->recipientsCount)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(&connectedPlayers[index] == message->recipients[targetIndex])
|
|
||||||
{
|
|
||||||
targetIndex++;
|
|
||||||
messageSend(tlssessions[index], message->content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Remove the output message from the queue:
|
|
||||||
popQueue(outputQueue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pthread_cancel(gameLogicThread);
|
pthread_cancel(gameLogicThread);
|
||||||
|
pthread_cancel(outputThread);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue