From afedf15c63750b9da205b6c0d96e6a7d18865d91 Mon Sep 17 00:00:00 2001 From: Barry Kane Date: Sun, 19 Feb 2023 00:32:03 +0000 Subject: [PATCH] Updated the evaluateNextCommand to use a hash instead of strncmp - Added hashCommand. - Refactored evaluateNextCommand to use hashCommand to jump to the correct functionality with a switch. --- src/gamelogic.c | 761 +++++++++++++++++++++++++----------------------- src/gamelogic.h | 3 + 2 files changed, 406 insertions(+), 358 deletions(-) diff --git a/src/gamelogic.c b/src/gamelogic.c index 1929ff8..a612ea9 100644 --- a/src/gamelogic.c +++ b/src/gamelogic.c @@ -108,7 +108,7 @@ void queueMessagedCommand(queue * queue, inputMessage * messageToQueue) // Copy the command and arguments to the new commandEvent: memcpy(newCommand->command, &messageToQueue->content->messageContent[1], 16); memcpy(newCommand->arguments, &messageToQueue->content->messageContent[strlen(newCommand->command) + 2], - MAX - (strlen(newCommand->command) + 2)); + MAX - (strlen(newCommand->command) + 2)); // Ensure the arguments are safe to parse, without adding newlines: userNameSanatize(newCommand->command, 16); @@ -158,410 +158,442 @@ int evaluateNextCommand(gameLogicParameters * parameters, queue * queue) { return -1; } - // Try command: Attempt to use a stat or skill on an object: - if (strncmp(currentCommand->command, "try", 3) == 0) + + // Hash the command and execute the relevant functionality: + switch (hashCommand(currentCommand->command, strlen(currentCommand->command))) { - userMessage * tryMessage = malloc(sizeof(userMessage)); - tryMessage->senderName[0] = '\0'; - - // Temporary message until we can implement objects, events, and challenges. - strcpy(tryMessage->messageContent, "The try command is currently not implemented. Implement it if you want to use it.\n"); - - // 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); - } - // Exit command: Sends an "empty" exit message to disconnect a client: - 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)); - exitMessage->senderName[0] = '\0'; - exitMessage->messageContent[0] = '\0'; - - // 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); - } - - // Move command: Moves the caller to a different area given a path name or number: - if (strncmp(currentCommand->command, "move", 4) == 0) - { - char requestedPath[32]; - if (strlen(currentCommand->arguments) > 0 && currentCommand->caller->currentArea != getFromList(parameters->areaList, 0)->area) + // Look command: Returns the description of the current area and paths: + case 5626697: { - memcpy(requestedPath, currentCommand->arguments, 32); - userNameSanatize(requestedPath, 32); - requestedPath[31] = '\0'; - if (movePlayerToArea(currentCommand->caller, requestedPath) == 0) - { - // Call the look command after moving. It's fine to unlock, because the loop won't - // continue until the command is queued: - queue->lock = false; - queueCommand(queue, "look", "", 5, 0, currentCommand->caller); - queue->lock = true; - } - } - } + char formattedString[64]; + userMessage * lookMessage = calloc(1, sizeof(userMessage)); + lookMessage->senderName[0] = '\0'; + strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaName, 33); + strncat(lookMessage->messageContent, "\n", 2); + strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaDescription, MAX - 35); - // Look command: Returns the description of the current area and paths: - if (strncmp(currentCommand->command, "look", 4) == 0) - { - char formattedString[64]; - userMessage * lookMessage = calloc(1, sizeof(userMessage)); - lookMessage->senderName[0] = '\0'; - strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaName, 33); - strncat(lookMessage->messageContent, "\n", 2); - strncat(lookMessage->messageContent, currentCommand->caller->currentArea->areaDescription, MAX - 35); + // Allocate an outputMessage for the queue: + outputMessage * lookOutputMessage = createTargetedOutputMessage(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)); - - // Loop through the paths and send the appropriate amount of messages: - int charCount = 13; - strncat(lookMessage->messageContent, "You can go:", 13); - - if (currentCommand->caller->currentArea->pathList->itemCount > 0) - { - for(size_t index = 0; index < currentCommand->caller->currentArea->pathList->itemCount; index++) - { - if ((charCount + 64) >= MAX) - { - lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1); - - // Queue the outputMessage: - pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE); - - bzero(lookMessage, sizeof(userMessage)); - charCount = 0; - } - snprintf(formattedString, 64, "\n\t%ld. %s", index + 1, - getFromList(currentCommand->caller->currentArea->pathList, index)->path->pathName); - strncat(lookMessage->messageContent, formattedString, 64); - charCount += 64; - } - // Allocate another outputMessage for the queue: - lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1); - // Queue the outputMessage: pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE); - } - free(lookMessage); - } - // Join command: Allows the player to join the game given a name: - // TODO: Implement login/character creation. Will be a while: - if (strncmp(currentCommand->command, "join", 4) == 0) - { - if (currentCommand->caller->currentArea == getFromList(parameters->areaList, 0)->area) - { - bool validName = true; - for(int index = 0; index < *parameters->playerCount; index++) + + //queueTargetedOutputMessage(parameters->outputQueue, lookMessage, ¤tCommand->caller, 1); + bzero(lookMessage, sizeof(userMessage)); + + // Loop through the paths and send the appropriate amount of messages: + int charCount = 13; + strncat(lookMessage->messageContent, "You can go:", 13); + + if (currentCommand->caller->currentArea->pathList->itemCount > 0) { - if (currentCommand->arguments[0] == '\0') + for(size_t index = 0; index < currentCommand->caller->currentArea->pathList->itemCount; index++) { - validName = false; + if ((charCount + 64) >= MAX) + { + lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE); + + bzero(lookMessage, sizeof(userMessage)); + charCount = 0; + } + snprintf(formattedString, 64, "\n\t%ld. %s", index + 1, + getFromList(currentCommand->caller->currentArea->pathList, index)->path->pathName); + strncat(lookMessage->messageContent, formattedString, 64); + charCount += 64; + } + // Allocate another outputMessage for the queue: + lookOutputMessage = createTargetedOutputMessage(lookMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, lookOutputMessage, OUTPUT_MESSAGE); + } + free(lookMessage); + + break; + } + + // Stat command: Displays the current character's sheet. + case 5987604: + { + char * formattedString = calloc(121, sizeof(char)); + userMessage * statMessage = calloc(1, sizeof(userMessage)); + statMessage->senderName[0] = '\0'; + // Basic status: Name, level, location. + snprintf(formattedString, 120, "%s, Level %d | %s\n", currentCommand->caller->playerName, + currentCommand->caller->stats->level, currentCommand->caller->currentArea->areaName); + strncat(statMessage->messageContent, formattedString, 120); + + // Current stats: Health and WISED. + snprintf(formattedString, 120, + "Health: %d/%d\nStats:\n\tWits: %2d | Intellect: %2d | Strength: %2d | Endurance: %2d | Dexerity: %2d \n", + currentCommand->caller->stats->currentHealth, currentCommand->caller->stats->maxHealth, + currentCommand->caller->stats->wits, currentCommand->caller->stats->intellect, + currentCommand->caller->stats->strength, currentCommand->caller->stats->endurance, + currentCommand->caller->stats->dexerity); + strncat(statMessage->messageContent, formattedString, 120); + + // Levelling stats: Current XP, and spec points. + if (currentCommand->caller->stats->specPoints > 0 || currentCommand->caller->stats->skillPoints > 0) + { + snprintf(formattedString, 120, "Current Experience: %ld | Spec Points Available: %d | Skill Points Available: %d", + currentCommand->caller->stats->experience, currentCommand->caller->stats->specPoints, currentCommand->caller->stats->skillPoints); + } + else + { + snprintf(formattedString, 120, "Current Experience: %ld", currentCommand->caller->stats->experience); + } + 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); + + bzero(statMessage->messageContent, sizeof(char) * MAX); + if (currentCommand->caller->skills->head != NULL) + { + size_t skillIndex = 0; + int charCount = 0; + bool addNewline = false; + playerSkill * skill; + while (skillIndex < currentCommand->caller->skills->itemCount) + { + skill = getFromList(currentCommand->caller->skills, skillIndex)->skill; + skillIndex++; + snprintf(formattedString, 120, "| %2d | %31s ", skill->skillPoints, skill->skillName); + charCount += 43; + strncat(statMessage->messageContent, formattedString, 120); + if ((charCount + 43) >= MAX) + { + // Allocate an outputMessage for the queue: + statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE); + bzero(statMessage, sizeof(userMessage)); + charCount = 0; + break; + } + else if (addNewline) + { + strncat(statMessage->messageContent, "|\n", 3); + charCount++; + addNewline = false; + } + else + { + addNewline = true; + } } - if (strncmp(currentCommand->arguments, parameters->connectedPlayers[index].playerName, 16) == 0) + // Allocate an outputMessage for the queue: + statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE); + } + free(statMessage); + free(formattedString); + + break; + } + + // Spec command: Assign spec points to stats: + case 5982259: + { + userMessage * specMessage = calloc(1, sizeof(userMessage)); + specMessage->senderName[0] = '\0'; + char * formattedString = calloc(121, sizeof(char)); + if (currentCommand->caller->stats->specPoints > 0) + { + int selectedAmount = 0; + strtok(currentCommand->arguments, " "); + selectedAmount = atoi(¤tCommand->arguments[strlen(currentCommand->arguments) + 1]); + coreStat selectedStat = getCoreStatFromString(currentCommand->arguments, 16); + if (selectedAmount > 0 && (currentCommand->caller->stats->specPoints - selectedAmount) >= 0) { - validName = false; + switch (selectedStat) + { + case WITS: + { + currentCommand->caller->stats->wits += selectedAmount; + strncat(specMessage->messageContent, "Increased wits.", 16); + currentCommand->caller->stats->specPoints -= selectedAmount; + break; + } + case INTELLECT: + { + currentCommand->caller->stats->intellect += selectedAmount; + strncat(specMessage->messageContent, "Increased intellect.", 21); + currentCommand->caller->stats->specPoints -= selectedAmount; + break; + } + case STRENGTH: + { + currentCommand->caller->stats->strength += selectedAmount; + strncat(specMessage->messageContent, "Increased strength.", 20); + currentCommand->caller->stats->specPoints -= selectedAmount; + break; + } + case ENDURANCE: + { + currentCommand->caller->stats->endurance += selectedAmount; + strncat(specMessage->messageContent, "Increased endurance.", 21); + currentCommand->caller->stats->specPoints -= selectedAmount; + break; + } + case DEXERITY: + { + currentCommand->caller->stats->dexerity += selectedAmount; + strncat(specMessage->messageContent, "Increased dexerity.", 21); + currentCommand->caller->stats->specPoints -= selectedAmount; + break; + } + case INVALID: + { + strncat(specMessage->messageContent, "Invalid stat.", 21); + } + } + } + else + { + strncat(specMessage->messageContent, "You have entered an invalid amount of spec points.", 51); } } - if (validName) + else { - strncpy(currentCommand->caller->playerName, currentCommand->arguments, 16); - currentCommand->caller->currentArea = getFromList(parameters->areaList, 1)->area; - // Call the look command after joining. It's fine to unlock, because the loop won't - // continue until the command is queued: - queue->lock = false; - queueCommand(queue, "look", "", 5, 0, currentCommand->caller); - queue->lock = true; + strncat(specMessage->messageContent, "You have no spec points available.", 35); } - } - } - // Talk command: Allows the player to begin a chat session with another player: - if (strncmp(currentCommand->command, "talk", 4) == 0) - { - userMessage * talkMessage = malloc(sizeof(userMessage)); - talkMessage->senderName[0] = '\0'; - - // Temporary message until we can implement objects, events, and challenges. - strcpy(talkMessage->messageContent, "The talk command is currently not implemented. Implement it if you want to use it.\n"); - // Allocate an outputMessage for the queue: - outputMessage * talkOutputMessage = createTargetedOutputMessage(talkMessage, ¤tCommand->caller, 1); + // Allocate an outputMessage for the queue: + outputMessage * specOutputMessage = createTargetedOutputMessage(specMessage, ¤tCommand->caller, 1); - // Queue the outputMessage: - pushQueue(parameters->outputQueue, talkOutputMessage, OUTPUT_MESSAGE); + // Queue the outputMessage: + pushQueue(parameters->outputQueue, specOutputMessage, OUTPUT_MESSAGE); - // Free the userMessage: - free(talkMessage); - } - // Stat command: Displays the current character's sheet. - if (strncmp(currentCommand->command, "stat", 4) == 0) - { - char * formattedString = calloc(121, sizeof(char)); - userMessage * statMessage = calloc(1, sizeof(userMessage)); - statMessage->senderName[0] = '\0'; - // Basic status: Name, level, location. - snprintf(formattedString, 120, "%s, Level %d | %s\n", currentCommand->caller->playerName, - currentCommand->caller->stats->level, currentCommand->caller->currentArea->areaName); - strncat(statMessage->messageContent, formattedString, 120); - - // Current stats: Health and WISED. - snprintf(formattedString, 120, - "Health: %d/%d\nStats:\n\tWits: %2d | Intellect: %2d | Strength: %2d | Endurance: %2d | Dexerity: %2d \n", - currentCommand->caller->stats->currentHealth, currentCommand->caller->stats->maxHealth, - currentCommand->caller->stats->wits, currentCommand->caller->stats->intellect, - currentCommand->caller->stats->strength, currentCommand->caller->stats->endurance, - currentCommand->caller->stats->dexerity); - strncat(statMessage->messageContent, formattedString, 120); - - // Levelling stats: Current XP, and spec points. - if (currentCommand->caller->stats->specPoints > 0 || currentCommand->caller->stats->skillPoints > 0) - { - snprintf(formattedString, 120, "Current Experience: %ld | Spec Points Available: %d | Skill Points Available: %d", - currentCommand->caller->stats->experience, currentCommand->caller->stats->specPoints, currentCommand->caller->stats->skillPoints); - } - else - { - snprintf(formattedString, 120, "Current Experience: %ld", currentCommand->caller->stats->experience); - } - 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); + // Show the new stat sheet: + queue->lock = false; + queueCommand(queue, "stat", "", 5, 0, currentCommand->caller); + queue->lock = true; - bzero(statMessage->messageContent, sizeof(char) * MAX); - if (currentCommand->caller->skills->head != NULL) - { - size_t skillIndex = 0; + // Free the finished message: + free(specMessage); + free(formattedString); + + break; + } + + // Try command: Attempt to use a stat or skill on an object: + case 163143: + { + // Allocate the userMessage to send: + userMessage * tryMessage = malloc(sizeof(userMessage)); + tryMessage->senderName[0] = '\0'; + + // Temporary message until we can implement objects, events, and challenges. + strcpy(tryMessage->messageContent, "The try command is currently not implemented. Implement it if you want to use it.\n"); + + // 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); + + break; + } + + // Move command: Moves the caller to a different area given a path name or number: + case 5677603: + { + char requestedPath[32]; + if (strlen(currentCommand->arguments) > 0 && currentCommand->caller->currentArea != getFromList(parameters->areaList, 0)->area) + { + memcpy(requestedPath, currentCommand->arguments, 32); + userNameSanatize(requestedPath, 32); + requestedPath[31] = '\0'; + if (movePlayerToArea(currentCommand->caller, requestedPath) == 0) + { + // Call the look command after moving. It's fine to unlock, because the loop won't + // continue until the command is queued: + queue->lock = false; + queueCommand(queue, "look", "", 5, 0, currentCommand->caller); + queue->lock = true; + } + } + + break; + } + + // Skill command: Allows you to put skill points into skills: + case 221096235: + { + userMessage * skillMessage = calloc(1, sizeof(userMessage)); + skillMessage->senderName[0] = '\0'; + if ((currentCommand->caller->stats->skillPoints - 1) >= 0) + { + int returnValue = takeSkill(parameters->globalSkillList, currentCommand->arguments, + strlen(currentCommand->arguments), currentCommand->caller); + switch(returnValue) + { + case -1: + { + strcpy(skillMessage->messageContent, "Not a valid skill."); + break; + } + case 0: + { + strcpy(skillMessage->messageContent, "Took "); + strcat(skillMessage->messageContent, currentCommand->arguments); + strcat(skillMessage->messageContent, "."); + currentCommand->caller->stats->skillPoints--; + break; + } + } + } + else + { + strcpy(skillMessage->messageContent, "You don't have enough skill points to take this skill.\n"); + } + + // Allocate an outputMessage for the queue: + outputMessage * skillOutputMessage = createTargetedOutputMessage(skillMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, skillOutputMessage, OUTPUT_MESSAGE); + + free(skillMessage); + break; + } + + // Listskills commands: List all available skills on the server: + case 2395990522: + { + userMessage * listMessage = calloc(1, sizeof(userMessage)); + char * formattedString = calloc(121, sizeof(char)); int charCount = 0; + size_t skillIndex = 0; bool addNewline = false; - playerSkill * skill; - while (skillIndex < currentCommand->caller->skills->itemCount) + playerSkill * currentSkill; + while (skillIndex < parameters->globalSkillList->itemCount) { - skill = getFromList(currentCommand->caller->skills, skillIndex)->skill; - skillIndex++; - snprintf(formattedString, 120, "| %2d | %31s ", skill->skillPoints, skill->skillName); + currentSkill = getFromList(parameters->globalSkillList, skillIndex)->skill; + snprintf(formattedString, 120, "| %-31s ", currentSkill->skillName); charCount += 43; - strncat(statMessage->messageContent, formattedString, 120); - if ((charCount + 43) >= MAX) + strncat(listMessage->messageContent, formattedString, 120); + if ((charCount + 46) >= MAX) { // Allocate an outputMessage for the queue: - statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1); - + outputMessage * listOutputMessage = createTargetedOutputMessage(listMessage, ¤tCommand->caller, 1); + // Queue the outputMessage: - pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE); - bzero(statMessage, sizeof(userMessage)); + pushQueue(parameters->outputQueue, listOutputMessage, OUTPUT_MESSAGE); + + bzero(listMessage, sizeof(userMessage)); charCount = 0; - break; + addNewline = false; } else if (addNewline) { - strncat(statMessage->messageContent, "|\n", 3); + strncat(listMessage->messageContent, "|\n", 3); charCount++; addNewline = false; } else { addNewline = true; - } + } + skillIndex++; } // Allocate an outputMessage for the queue: - statOutputMessage = createTargetedOutputMessage(statMessage, ¤tCommand->caller, 1); + outputMessage * listOutputMessage = createTargetedOutputMessage(listMessage, ¤tCommand->caller, 1); + + // Queue the outputMessage: + pushQueue(parameters->outputQueue, listOutputMessage, OUTPUT_MESSAGE); + free(listMessage); + free(formattedString); + break; + } + + // Talk command: Allows the player to begin a chat session with another player: + case 601264: + { + userMessage * talkMessage = malloc(sizeof(userMessage)); + talkMessage->senderName[0] = '\0'; + + // Temporary message until we can implement objects, events, and challenges. + strcpy(talkMessage->messageContent, "The talk command is currently not implemented. Implement it if you want to use it.\n"); + + // Allocate an outputMessage for the queue: + outputMessage * talkOutputMessage = createTargetedOutputMessage(talkMessage, ¤tCommand->caller, 1); // Queue the outputMessage: - pushQueue(parameters->outputQueue, statOutputMessage, OUTPUT_MESSAGE); - } - free(statMessage); - free(formattedString); - } - - // Spec command: Assign spec points to stats: - if (strncmp(currentCommand->command, "spec", 4) == 0) - { - userMessage * specMessage = calloc(1, sizeof(userMessage)); - specMessage->senderName[0] = '\0'; - char * formattedString = calloc(121, sizeof(char)); - if (currentCommand->caller->stats->specPoints > 0) - { - int selectedAmount = 0; - strtok(currentCommand->arguments, " "); - selectedAmount = atoi(¤tCommand->arguments[strlen(currentCommand->arguments) + 1]); - coreStat selectedStat = getCoreStatFromString(currentCommand->arguments, 16); - if (selectedAmount > 0 && (currentCommand->caller->stats->specPoints - selectedAmount) >= 0) - { - switch (selectedStat) - { - case WITS: - { - currentCommand->caller->stats->wits += selectedAmount; - strncat(specMessage->messageContent, "Increased wits.", 16); - currentCommand->caller->stats->specPoints -= selectedAmount; - break; - } - case INTELLECT: - { - currentCommand->caller->stats->intellect += selectedAmount; - strncat(specMessage->messageContent, "Increased intellect.", 21); - currentCommand->caller->stats->specPoints -= selectedAmount; - break; - } - case STRENGTH: - { - currentCommand->caller->stats->strength += selectedAmount; - strncat(specMessage->messageContent, "Increased strength.", 20); - currentCommand->caller->stats->specPoints -= selectedAmount; - break; - } - case ENDURANCE: - { - currentCommand->caller->stats->endurance += selectedAmount; - strncat(specMessage->messageContent, "Increased endurance.", 21); - currentCommand->caller->stats->specPoints -= selectedAmount; - break; - } - case DEXERITY: - { - currentCommand->caller->stats->dexerity += selectedAmount; - strncat(specMessage->messageContent, "Increased dexerity.", 21); - currentCommand->caller->stats->specPoints -= selectedAmount; - break; - } - case INVALID: - { - strncat(specMessage->messageContent, "Invalid stat.", 21); - } - } - } - else - { - strncat(specMessage->messageContent, "You have entered an invalid amount of spec points.", 51); - } - } - else - { - strncat(specMessage->messageContent, "You have no spec points available.", 35); + pushQueue(parameters->outputQueue, talkOutputMessage, OUTPUT_MESSAGE); + + // Free the userMessage: + free(talkMessage); + + break; } - // Allocate an outputMessage for the queue: - outputMessage * specOutputMessage = createTargetedOutputMessage(specMessage, ¤tCommand->caller, 1); - - // Queue the outputMessage: - pushQueue(parameters->outputQueue, specOutputMessage, OUTPUT_MESSAGE); - - // Show the new stat sheet: - queue->lock = false; - queueCommand(queue, "stat", "", 5, 0, currentCommand->caller); - queue->lock = true; - - // Free the finished message: - free(specMessage); - free(formattedString); - } - if (strncmp(currentCommand->command, "skill", 5) == 0) - { - userMessage * skillMessage = calloc(1, sizeof(userMessage)); - skillMessage->senderName[0] = '\0'; - if ((currentCommand->caller->stats->skillPoints - 1) >= 0) + // Exit command: Sends an "empty" exit message to disconnect a client: + case 5284234: { - int returnValue = takeSkill(parameters->globalSkillList, currentCommand->arguments, - strlen(currentCommand->arguments), currentCommand->caller); - switch(returnValue) + // Allocate a userMessage containing null characters as the first char in both fields: + userMessage * exitMessage = malloc(sizeof(userMessage)); + exitMessage->senderName[0] = '\0'; + exitMessage->messageContent[0] = '\0'; + + // 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); + + break; + } + + // Join command: Allows the player to join the game given a name: + // TODO: Implement login/character creation. Will be a while: + case 5525172: + { + if (currentCommand->caller->currentArea == getFromList(parameters->areaList, 0)->area) { - case -1: + bool validName = true; + for(int index = 0; index < *parameters->playerCount; index++) { - strcpy(skillMessage->messageContent, "Not a valid skill."); - break; + if (currentCommand->arguments[0] == '\0') + { + validName = false; + } + if (strncmp(currentCommand->arguments, parameters->connectedPlayers[index].playerName, 16) == 0) + { + validName = false; + } } - case 0: + if (validName) { - strcpy(skillMessage->messageContent, "Took "); - strcat(skillMessage->messageContent, currentCommand->arguments); - strcat(skillMessage->messageContent, "."); - currentCommand->caller->stats->skillPoints--; - break; + strncpy(currentCommand->caller->playerName, currentCommand->arguments, 16); + currentCommand->caller->currentArea = getFromList(parameters->areaList, 1)->area; + // Call the look command after joining. It's fine to unlock, because the loop won't + // continue until the command is queued: + queue->lock = false; + queueCommand(queue, "look", "", 5, 0, currentCommand->caller); + queue->lock = true; } } + break; } - else - { - strcpy(skillMessage->messageContent, "You don't have enough skill points to take this skill.\n"); - } + } - // Allocate an outputMessage for the queue: - outputMessage * skillOutputMessage = createTargetedOutputMessage(skillMessage, ¤tCommand->caller, 1); - - // Queue the outputMessage: - pushQueue(parameters->outputQueue, skillOutputMessage, OUTPUT_MESSAGE); - - free(skillMessage); - } - if (strncmp(currentCommand->command, "listskills", 10) == 0) - { - userMessage * listMessage = calloc(1, sizeof(userMessage)); - char * formattedString = calloc(121, sizeof(char)); - int charCount = 0; - size_t skillIndex = 0; - bool addNewline = false; - playerSkill * currentSkill; - while (skillIndex < parameters->globalSkillList->itemCount) - { - currentSkill = getFromList(parameters->globalSkillList, skillIndex)->skill; - snprintf(formattedString, 120, "| %-31s ", currentSkill->skillName); - charCount += 43; - strncat(listMessage->messageContent, formattedString, 120); - if ((charCount + 46) >= MAX) - { - // 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)); - charCount = 0; - addNewline = false; - } - else if (addNewline) - { - strncat(listMessage->messageContent, "|\n", 3); - charCount++; - addNewline = false; - } - else - { - addNewline = true; - } - skillIndex++; - } - // 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(formattedString); - } // Remove the current command and unlock the queue: currentCommand = NULL; queue->lock = false; @@ -719,7 +751,7 @@ int movePlayerToArea(playerInfo * player, char * requestedPath) if (selected != 0 && !(selected > player->currentArea->pathList->itemCount)) { if (getFromList(player->currentArea->pathList, selected - 1)->path != NULL && - getFromList(player->currentArea->pathList, selected - 1)->path->areaToJoin != NULL) + getFromList(player->currentArea->pathList, selected - 1)->path->areaToJoin != NULL) { player->currentArea = getFromList(player->currentArea->pathList, selected - 1)->path->areaToJoin; return 0; @@ -734,12 +766,25 @@ int movePlayerToArea(playerInfo * player, char * requestedPath) for (size_t index = 0; index < player->currentArea->pathList->itemCount; index++) { if (strncmp(getFromList(player->currentArea->pathList, index)->path->pathName, - requestedPath, 32) == 0) + requestedPath, 32) == 0) { - printf("%s: %s\n", player->playerName, getFromList(player->currentArea->pathList, index)->path->pathName); player->currentArea = getFromList(player->currentArea->pathList, index)->path->areaToJoin; return 0; } } return 1; } + +// A hash function for distinguishing commands for the game logic handler: +unsigned int hashCommand(char * command, unsigned int commandLength) +{ + unsigned int hash = 0; + char * currentCharacter = command; + + for (unsigned int index = 0; index < commandLength && *currentCharacter != '\0'; currentCharacter++) + { + hash = 37 * hash + *currentCharacter; + } + + return hash; +} diff --git a/src/gamelogic.h b/src/gamelogic.h index 1e717c5..2fd9b8d 100644 --- a/src/gamelogic.h +++ b/src/gamelogic.h @@ -55,6 +55,9 @@ int evaluateNextCommand(gameLogicParameters * parameters, queue * queue); void queueCommand(queue * queue, char * command, char * arguments, int commandLength, int argumentsLength, playerInfo * callingPlayer); +// A hash function for distinguishing commands for the game logic handler: +unsigned int hashCommand(char * command, unsigned int commandLength); + // ============================ // -=[ Gameplay Primitives ]=-: // ============================