Refactored the outputQueue to use the new queue type
- Patched a bug where I didn't set the correct type for queue nodes. - Removed all traces of the previous outputMessageQueue type. - Removed the pointer "next" in outputMessage. - Rewrote the the main thread and game logic thread to use a queue for output. - Refactored outputMessage to allow for a variable amount of playerInfo pointers.
This commit is contained in:
parent
9b3df5928b
commit
15d82f59ee
134
src/gamelogic.c
134
src/gamelogic.c
|
@ -43,28 +43,40 @@ void * gameLogicLoop(void * parameters)
|
||||||
queueMessagedCommand(commandQueue, currentInput);
|
queueMessagedCommand(commandQueue, currentInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!(currentInput->sender->currentArea == getFromList(threadParameters->areaList, 0)->area))
|
else if (!(currentInput->sender->currentArea == getFromList(threadParameters->areaList, 0)->area) &&
|
||||||
|
currentInput->content->messageContent[0] != '\n')
|
||||||
{
|
{
|
||||||
|
// Copy the correct name into the sender name field:
|
||||||
strncpy(currentInput->content->senderName, currentInput->sender->playerName, 32);
|
strncpy(currentInput->content->senderName, currentInput->sender->playerName, 32);
|
||||||
// Create an array of players in the same area to receive the message:
|
currentInput->content->senderName[31] = '\0';
|
||||||
playerInfo ** recipients = malloc(sizeof(playerInfo*) * *threadParameters->playerCount);
|
|
||||||
for(int index = 0; index < *threadParameters->playerCount; index++)
|
// Allocate an array of playerInfo to store the current players in the area for the output message:
|
||||||
|
playerInfo ** recipients = malloc(sizeof(playerInfo*) * PLAYERCOUNT);
|
||||||
|
|
||||||
|
// Initialize them all to NULL:
|
||||||
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
recipients[index] = NULL;
|
recipients[index] = NULL;
|
||||||
}
|
}
|
||||||
int recipientCount = 0;
|
|
||||||
for(int playerIndex = 0; playerIndex < *threadParameters->playerCount; playerIndex++)
|
// Get the players in the current area and add them to our array:
|
||||||
|
int recipientIndex = 0;
|
||||||
|
for (int playerIndex = 0; playerIndex < *threadParameters->playerCount; playerIndex++)
|
||||||
{
|
{
|
||||||
if(threadParameters->connectedPlayers[playerIndex].currentArea == currentInput->sender->currentArea)
|
if (threadParameters->connectedPlayers[playerIndex].currentArea == currentInput->sender->currentArea)
|
||||||
{
|
{
|
||||||
recipients[recipientCount] = &threadParameters->connectedPlayers[playerIndex];
|
recipients[recipientIndex] = &threadParameters->connectedPlayers[playerIndex];
|
||||||
recipientCount++;
|
recipientIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(currentInput->content->messageContent[0] != '\n')
|
|
||||||
{
|
// Create the outputMessage for the queue:
|
||||||
queueTargetedOutputMessage(threadParameters->outputQueue, currentInput->content, recipients, recipientCount);
|
outputMessage * newOutputMessage = createTargetedOutputMessage(currentInput->content, recipients, recipientIndex);
|
||||||
}
|
|
||||||
|
// Push the message onto the queue:
|
||||||
|
pushQueue(threadParameters->outputQueue, newOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
|
// Free the array;
|
||||||
free(recipients);
|
free(recipients);
|
||||||
}
|
}
|
||||||
currentInput = NULL;
|
currentInput = NULL;
|
||||||
|
@ -320,16 +332,31 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, tryMessage, ¤tCommand->caller, 1);
|
|
||||||
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * tryOutputMessage = createTargetedOutputMessage(tryMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, tryOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
|
// Free the userMessage:
|
||||||
free(tryMessage);
|
free(tryMessage);
|
||||||
}
|
}
|
||||||
// Exit command: Sends an "empty" exit message to disconnect a client:
|
// Exit command: Sends an "empty" exit message to disconnect a client:
|
||||||
if(strncmp(currentCommand->command, "exit", 4) == 0)
|
if(strncmp(currentCommand->command, "exit", 4) == 0)
|
||||||
{
|
{
|
||||||
|
// Allocate a userMessage containing null characters as the first char in both fields:
|
||||||
userMessage * exitMessage = malloc(sizeof(userMessage));
|
userMessage * exitMessage = malloc(sizeof(userMessage));
|
||||||
exitMessage->senderName[0] = '\0';
|
exitMessage->senderName[0] = '\0';
|
||||||
exitMessage->messageContent[0] = '\0';
|
exitMessage->messageContent[0] = '\0';
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, exitMessage, ¤tCommand->caller, 1);
|
|
||||||
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * exitOutputMessage = createTargetedOutputMessage(exitMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, exitOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
|
// Free the userMessage
|
||||||
free(exitMessage);
|
free(exitMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +389,14 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaName, 33);
|
strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaName, 33);
|
||||||
strncat(lookMessage->messageContent, "\n", 2);
|
strncat(lookMessage->messageContent, "\n", 2);
|
||||||
strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaDescription, MAX - 35);
|
strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaDescription, MAX - 35);
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, lookMessage, ¤tCommand->caller, 1);
|
|
||||||
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
|
//queueTargetedOutputMessage(parameters->outputQueue, lookMessage, ¤tCommand->caller, 1);
|
||||||
bzero(lookMessage, sizeof(userMessage));
|
bzero(lookMessage, sizeof(userMessage));
|
||||||
|
|
||||||
// Loop through the paths and send the appropriate amount of messages:
|
// Loop through the paths and send the appropriate amount of messages:
|
||||||
|
@ -375,7 +409,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
{
|
{
|
||||||
if((charCount + 64) >= MAX)
|
if((charCount + 64) >= MAX)
|
||||||
{
|
{
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, lookMessage, ¤tCommand->caller, 1);
|
lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
bzero(lookMessage, sizeof(userMessage));
|
bzero(lookMessage, sizeof(userMessage));
|
||||||
charCount = 0;
|
charCount = 0;
|
||||||
}
|
}
|
||||||
|
@ -384,7 +422,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
strncat(lookMessage->messageContent, formattedString, 64);
|
strncat(lookMessage->messageContent, formattedString, 64);
|
||||||
charCount += 64;
|
charCount += 64;
|
||||||
}
|
}
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, lookMessage, ¤tCommand->caller, 1);
|
// Allocate another outputMessage for the queue:
|
||||||
|
lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE);
|
||||||
}
|
}
|
||||||
free(lookMessage);
|
free(lookMessage);
|
||||||
}
|
}
|
||||||
|
@ -423,14 +465,6 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
{
|
{
|
||||||
// TODO: Implement.
|
// TODO: Implement.
|
||||||
}
|
}
|
||||||
if(strncmp(currentCommand->command, "skillissue", 10) == 0)
|
|
||||||
{
|
|
||||||
userMessage * statMessage = calloc(1, sizeof(userMessage));
|
|
||||||
statMessage->senderName[0] = '\0';
|
|
||||||
strcpy(statMessage->messageContent, "Have you tried getting good?");
|
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, statMessage, ¤tCommand->caller, 1);
|
|
||||||
free(statMessage);
|
|
||||||
}
|
|
||||||
// Stat command: Displays the current character's sheet.
|
// Stat command: Displays the current character's sheet.
|
||||||
if(strncmp(currentCommand->command, "stat", 4) == 0)
|
if(strncmp(currentCommand->command, "stat", 4) == 0)
|
||||||
{
|
{
|
||||||
|
@ -462,8 +496,13 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
snprintf(formattedString, 120, "Current Experience: %ld", currentCommand->caller->stats->experience);
|
snprintf(formattedString, 120, "Current Experience: %ld", currentCommand->caller->stats->experience);
|
||||||
}
|
}
|
||||||
strncat(statMessage->messageContent, formattedString, 120);
|
strncat(statMessage->messageContent, formattedString, 120);
|
||||||
|
|
||||||
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, statMessage, ¤tCommand->caller, 1);
|
|
||||||
bzero(statMessage->messageContent, sizeof(char) * MAX);
|
bzero(statMessage->messageContent, sizeof(char) * MAX);
|
||||||
if(currentCommand->caller->skills->head != NULL)
|
if(currentCommand->caller->skills->head != NULL)
|
||||||
{
|
{
|
||||||
|
@ -480,8 +519,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
strncat(statMessage->messageContent, formattedString, 120);
|
strncat(statMessage->messageContent, formattedString, 120);
|
||||||
if((charCount + 43) >= MAX)
|
if((charCount + 43) >= MAX)
|
||||||
{
|
{
|
||||||
// strncat(statMessage->messageContent, "\n", 2);
|
// Allocate an outputMessage for the queue:
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, statMessage, ¤tCommand->caller, 1);
|
statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE);
|
||||||
bzero(statMessage, sizeof(userMessage));
|
bzero(statMessage, sizeof(userMessage));
|
||||||
charCount = 0;
|
charCount = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -497,7 +539,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
addNewline = true;
|
addNewline = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, statMessage, ¤tCommand->caller, 1);
|
// Allocate an outputMessage for the queue:
|
||||||
|
statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE);
|
||||||
}
|
}
|
||||||
free(statMessage);
|
free(statMessage);
|
||||||
free(formattedString);
|
free(formattedString);
|
||||||
|
@ -570,8 +616,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
strncat(specMessage->messageContent, "You have no spec points available.", 35);
|
strncat(specMessage->messageContent, "You have no spec points available.", 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the message:
|
// Allocate an outputMessage for the queue:
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, specMessage, ¤tCommand->caller, 1);
|
outputMessage * specOutputMessage = createTargetedOutputMessage(specMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, specOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
// Show the new stat sheet:
|
// Show the new stat sheet:
|
||||||
queue->lock = false;
|
queue->lock = false;
|
||||||
|
@ -611,7 +660,13 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
{
|
{
|
||||||
strcpy(skillMessage->messageContent, "You don't have enough skill points to take this skill.\n");
|
strcpy(skillMessage->messageContent, "You don't have enough skill points to take this skill.\n");
|
||||||
}
|
}
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, skillMessage, ¤tCommand->caller, 1);
|
|
||||||
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * skillOutputMessage = createTargetedOutputMessage(skillMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, skillOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
free(skillMessage);
|
free(skillMessage);
|
||||||
}
|
}
|
||||||
if(strncmp(currentCommand->command, "listskills", 10) == 0)
|
if(strncmp(currentCommand->command, "listskills", 10) == 0)
|
||||||
|
@ -630,7 +685,12 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
strncat(listMessage->messageContent, formattedString, 120);
|
strncat(listMessage->messageContent, formattedString, 120);
|
||||||
if((charCount + 46) >= MAX)
|
if((charCount + 46) >= MAX)
|
||||||
{
|
{
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, listMessage, ¤tCommand->caller, 1);
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * listOutputMessage = createTargetedOutputMessage(listMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, listOutputMessage, OUTPUT_MESSAGE);
|
||||||
|
|
||||||
bzero(listMessage, sizeof(userMessage));
|
bzero(listMessage, sizeof(userMessage));
|
||||||
charCount = 0;
|
charCount = 0;
|
||||||
addNewline = false;
|
addNewline = false;
|
||||||
|
@ -647,7 +707,11 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
|
||||||
}
|
}
|
||||||
skillIndex++;
|
skillIndex++;
|
||||||
}
|
}
|
||||||
queueTargetedOutputMessage(parameters->outputQueue, listMessage, ¤tCommand->caller, 1);
|
// Allocate an outputMessage for the queue:
|
||||||
|
outputMessage * listOutputMessage = createTargetedOutputMessage(listMessage, ¤tCommand->caller, 1);
|
||||||
|
|
||||||
|
// Queue the outputMessage:
|
||||||
|
pushQueue(parameters->outputQueue, listOutputMessage, OUTPUT_MESSAGE);
|
||||||
free(listMessage);
|
free(listMessage);
|
||||||
free(formattedString);
|
free(formattedString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,16 @@ typedef struct queue queue;
|
||||||
// A data-structure containing the needed parameters for a main game loop:
|
// A data-structure containing the needed parameters for a main game loop:
|
||||||
typedef struct gameLogicParameters
|
typedef struct gameLogicParameters
|
||||||
{
|
{
|
||||||
|
// Players:
|
||||||
int * playerCount;
|
int * playerCount;
|
||||||
list * areaList;
|
|
||||||
playerInfo * connectedPlayers;
|
playerInfo * connectedPlayers;
|
||||||
|
|
||||||
|
// Queues:
|
||||||
queue * inputQueue;
|
queue * inputQueue;
|
||||||
outputMessageQueue * outputQueue;
|
queue * outputQueue;
|
||||||
|
|
||||||
|
// Lists:
|
||||||
|
list * areaList;
|
||||||
list * globalSkillList;
|
list * globalSkillList;
|
||||||
} gameLogicParameters;
|
} gameLogicParameters;
|
||||||
|
|
||||||
|
|
|
@ -46,170 +46,22 @@ int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToM
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputMessageQueue * createOutputMessageQueue(void)
|
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientsCount)
|
||||||
{
|
{
|
||||||
outputMessageQueue * newQueue = malloc(sizeof(outputMessageQueue));
|
// Allocate a new output message:
|
||||||
newQueue->front = NULL;
|
|
||||||
newQueue->back = NULL;
|
|
||||||
newQueue->currentLength = 0;
|
|
||||||
newQueue->lock = false;
|
|
||||||
return newQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int queueOutputMessage(outputMessageQueue * queue, userMessage messageToQueue)
|
|
||||||
{
|
|
||||||
// Copy the message into a new output message:
|
|
||||||
outputMessage * newOutputMessage = malloc(sizeof(outputMessage));
|
outputMessage * newOutputMessage = malloc(sizeof(outputMessage));
|
||||||
|
|
||||||
// Allocate the internal userMessage to store the message:
|
|
||||||
newOutputMessage->content = malloc(sizeof(userMessage));
|
|
||||||
|
|
||||||
// Copy the userMessage to the internal userMessage:
|
|
||||||
strncpy(newOutputMessage->content->senderName, messageToQueue.senderName, 32);
|
|
||||||
strncpy(newOutputMessage->content->messageContent, messageToQueue.messageContent, MAX);
|
|
||||||
|
|
||||||
// We have no targets, NULL sends to all players in an area:
|
|
||||||
newOutputMessage->targets[0] = NULL;
|
|
||||||
|
|
||||||
// Wait for the queue to unlock:
|
|
||||||
while (queue->lock);
|
|
||||||
|
|
||||||
// Lock the queue:
|
|
||||||
queue->lock = true;
|
|
||||||
|
|
||||||
// Check that we're not overflowing the queue:
|
|
||||||
if ((queue->currentLength + 1) > MAXQUEUELENGTH)
|
|
||||||
{
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the queue is empty, set the first message as both the front and back of the queue:
|
|
||||||
if(queue->front == NULL)
|
|
||||||
{
|
|
||||||
queue->front = newOutputMessage;
|
|
||||||
queue->back = newOutputMessage;
|
|
||||||
queue->currentLength++;
|
|
||||||
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queue->back->next = newOutputMessage;
|
|
||||||
queue->back = newOutputMessage;
|
|
||||||
queue->currentLength++;
|
|
||||||
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int queueTargetedOutputMessage(outputMessageQueue * queue,
|
|
||||||
userMessage * messageToQueue, playerInfo ** targets, int numberOfTargets)
|
|
||||||
{
|
|
||||||
// Copy the message into a new output message:
|
|
||||||
outputMessage * newOutputMessage = malloc(sizeof(outputMessage));
|
|
||||||
|
|
||||||
// Allocate the internal userMessage to store the message:
|
|
||||||
newOutputMessage->content = malloc(sizeof(userMessage));
|
newOutputMessage->content = malloc(sizeof(userMessage));
|
||||||
|
|
||||||
// Set the appropriate recipients:
|
// Allocate an array of playerInfo for the output message recepients:
|
||||||
for(int index = 0; index < numberOfTargets && index < PLAYERCOUNT; index++)
|
newOutputMessage->recipients = malloc(sizeof(playerInfo*) * recipientsCount);
|
||||||
{
|
|
||||||
newOutputMessage->targets[index] = targets[index];
|
|
||||||
}
|
|
||||||
for(int index = numberOfTargets; index < PLAYERCOUNT; index++)
|
|
||||||
{
|
|
||||||
newOutputMessage->targets[index] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the userMessage to the internal userMessage:
|
|
||||||
strncpy(newOutputMessage->content->senderName, messageToQueue->senderName, 32);
|
|
||||||
strncpy(newOutputMessage->content->messageContent, messageToQueue->messageContent, MAX);
|
|
||||||
|
|
||||||
// Wait for the queue to unlock:
|
|
||||||
while (queue->lock);
|
|
||||||
|
|
||||||
// Lock the queue:
|
// Copy in the appropriate data:
|
||||||
queue->lock = true;
|
memcpy(newOutputMessage->recipients, recipients, sizeof(playerInfo *) * recipientsCount);
|
||||||
|
memcpy(newOutputMessage->content, messageToQueue, sizeof(userMessage));
|
||||||
|
newOutputMessage->recipientsCount = recipientsCount;
|
||||||
|
|
||||||
// Check that we're not overflowing the queue:
|
// Return a pointer to the new outputMessage:
|
||||||
if ((queue->currentLength + 1) > MAXQUEUELENGTH)
|
return newOutputMessage;
|
||||||
{
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the queue is empty, set the first message as both the front and back of the queue:
|
|
||||||
if(queue->front == NULL)
|
|
||||||
{
|
|
||||||
queue->front = newOutputMessage;
|
|
||||||
queue->back = newOutputMessage;
|
|
||||||
queue->currentLength++;
|
|
||||||
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queue->back->next = newOutputMessage;
|
|
||||||
queue->back = newOutputMessage;
|
|
||||||
queue->currentLength++;
|
|
||||||
|
|
||||||
// Unlock the queue:
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dequeueOutputMessage(outputMessageQueue * queue)
|
|
||||||
{
|
|
||||||
// Wait for the queue to unlock:
|
|
||||||
while (queue->lock);
|
|
||||||
|
|
||||||
// Lock the queue:
|
|
||||||
queue->lock = true;
|
|
||||||
|
|
||||||
// Check the list isn't empty:
|
|
||||||
if(queue->front == NULL)
|
|
||||||
{
|
|
||||||
queue->lock = false;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is only one item in the queue:
|
|
||||||
else if(queue->front == queue->back)
|
|
||||||
{
|
|
||||||
free(queue->front->content);
|
|
||||||
free(queue->front);
|
|
||||||
queue->front = NULL;
|
|
||||||
queue->back = NULL;
|
|
||||||
queue->currentLength--;
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the front item:
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outputMessage * messageToDelete = queue->front;
|
|
||||||
queue->front = queue->front->next;
|
|
||||||
free(messageToDelete->content);
|
|
||||||
free(messageToDelete);
|
|
||||||
queue->currentLength--;
|
|
||||||
queue->lock = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void userInputSanatize(char * inputString, int length)
|
void userInputSanatize(char * inputString, int length)
|
||||||
|
@ -238,8 +90,3 @@ void userNameSanatize(char * inputString, int length)
|
||||||
}
|
}
|
||||||
inputString[length - 1] = '\0';
|
inputString[length - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
outputMessage * peekOutputMessage(outputMessageQueue * queue)
|
|
||||||
{
|
|
||||||
return queue->front;
|
|
||||||
}
|
|
||||||
|
|
|
@ -33,33 +33,13 @@ int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToM
|
||||||
typedef struct outputMessage outputMessage;
|
typedef struct outputMessage outputMessage;
|
||||||
typedef struct outputMessage
|
typedef struct outputMessage
|
||||||
{
|
{
|
||||||
outputMessage * next;
|
int recipientsCount;
|
||||||
playerInfo * targets[PLAYERCOUNT];
|
|
||||||
userMessage * content;
|
userMessage * content;
|
||||||
|
playerInfo ** recipients;
|
||||||
} outputMessage;
|
} outputMessage;
|
||||||
|
|
||||||
// A first-in first-out queue for message output to players:
|
// Create a targetedOutput message to be delivered to the players pointed to in recipients:
|
||||||
typedef struct outputMessageQueue
|
outputMessage * createTargetedOutputMessage(userMessage * messageToQueue, playerInfo ** recipients, int recipientCount);
|
||||||
{
|
|
||||||
bool lock;
|
|
||||||
int currentLength;
|
|
||||||
outputMessage * back;
|
|
||||||
outputMessage * front;
|
|
||||||
} outputMessageQueue;
|
|
||||||
|
|
||||||
// Creates and initializes a outputMessageQueue:
|
|
||||||
outputMessageQueue * createOutputMessageQueue(void);
|
|
||||||
|
|
||||||
// Enqueue a userMessage to an outputMessageQueue:
|
|
||||||
int queueOutputMessage(outputMessageQueue * queue, userMessage messageToQueue);
|
|
||||||
int queueTargetedOutputMessage(outputMessageQueue * queue, userMessage * messageToQueue,
|
|
||||||
playerInfo ** targets, int numberOfTargets);
|
|
||||||
|
|
||||||
// Dequeue the front outputMessage from an outputMessageQueue:
|
|
||||||
int dequeueOutputMessage(outputMessageQueue * queue);
|
|
||||||
|
|
||||||
// Return the front outputMessage from an outputMessageQueue:
|
|
||||||
outputMessage * peekOutputMessage(outputMessageQueue * queue);
|
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// -=[Input Queue]=-:
|
// -=[Input Queue]=-:
|
||||||
|
|
|
@ -151,7 +151,7 @@ void pushQueue(queue * queue, void * data, queueDataType type)
|
||||||
{
|
{
|
||||||
// Create a new node:
|
// Create a new node:
|
||||||
queueNode * newNode = malloc(sizeof(queueNode));
|
queueNode * newNode = malloc(sizeof(queueNode));
|
||||||
|
newNode->type = type;
|
||||||
// Copy the data into the correct slot for the type:
|
// Copy the data into the correct slot for the type:
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,8 +46,7 @@ int main(int argc, char ** argv)
|
||||||
playerInfo connectedPlayers[PLAYERCOUNT];
|
playerInfo connectedPlayers[PLAYERCOUNT];
|
||||||
char testString[32] = "Hehe.";
|
char testString[32] = "Hehe.";
|
||||||
struct sockaddr_in serverAddress, clientAddress;
|
struct sockaddr_in serverAddress, clientAddress;
|
||||||
queue * inputQueue = createQueue();
|
queue * inputQueue = createQueue(), * outputQueue = createQueue();
|
||||||
outputMessageQueue * outputQueue = createOutputMessageQueue();
|
|
||||||
|
|
||||||
// Parse command-line options:
|
// Parse command-line options:
|
||||||
int currentopt = 0;
|
int currentopt = 0;
|
||||||
|
@ -343,38 +342,47 @@ int main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run through the output queue and send all unused messages:
|
// Run through the output queue and send all unused messages:
|
||||||
while(outputQueue->currentLength != 0)
|
while(outputQueue->itemCount != 0)
|
||||||
{
|
{
|
||||||
|
// Wait until the queue unlocks:
|
||||||
while(outputQueue->lock);
|
while(outputQueue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
outputQueue->lock = true;
|
outputQueue->lock = true;
|
||||||
outputMessage * message = peekOutputMessage(outputQueue);
|
|
||||||
|
// Get a message off the queue:
|
||||||
|
outputMessage * message = peekQueue(outputQueue)->data.outputMessage;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
outputQueue->lock = false;
|
outputQueue->lock = false;
|
||||||
|
|
||||||
// If the first target is set to NULL, it's intended for all connected:
|
// If the first target is set to NULL, it's intended for all connected:
|
||||||
if(message->targets[0] == NULL)
|
if(message->recipientsCount == 0)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < PLAYERCOUNT; index++)
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
messageSend(tlssessions[index], message->content);
|
messageSend(tlssessions[index], message->content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Otherwise, send it only to the targeted players:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int targetIndex = 0;
|
int targetIndex = 0;
|
||||||
for(int index = 0; index < PLAYERCOUNT; index++)
|
for(int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
if(message->targets[targetIndex] == NULL)
|
if(targetIndex == message->recipientsCount)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(&connectedPlayers[index] == message->targets[targetIndex])
|
if(&connectedPlayers[index] == message->recipients[targetIndex])
|
||||||
{
|
{
|
||||||
targetIndex++;
|
targetIndex++;
|
||||||
messageSend(tlssessions[index], message->content);
|
messageSend(tlssessions[index], message->content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dequeueOutputMessage(outputQueue);
|
// Remove the output message from the queue:
|
||||||
|
popQueue(outputQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_cancel(gameLogicThread);
|
pthread_cancel(gameLogicThread);
|
||||||
|
|
Loading…
Reference in New Issue