Added area and path creation functions

- Added missing header guards.
- Increased the size of message contents to 2048.
- Added area and path initialization functions.
- movePlayerToArea no longer segfaults.
- /LOOK added to allow players to find exits.
- Amount of paths allowed out of an area has been decreased to 16.
- Debug builds are now available from the Makefile.
- Removed unused variables.
- Input sanatization has been moved to the server-side, phew.
- Server messages are now displayed differently to player messages.
- New area initialization has been added until I can integrate Guile.
- Server's sendBuffer has been renamed messageBuffer.
- Areas now have descriptions.
- Descriptions are sent to the player upon joining an area and /LOOK-ing.
This commit is contained in:
Barry 2021-11-04 23:14:47 +00:00
parent 85a31a2933
commit 241ac7a92b
6 changed files with 181 additions and 56 deletions

View File

@ -8,13 +8,22 @@ serverobj = $(serversrc:.c=.o)
CLIENTLDFLAGS= -lpthread -lncurses CLIENTLDFLAGS= -lpthread -lncurses
SERVERLDFLAGS= -lncurses SERVERLDFLAGS= -lncurses
SilverMUDClient: $(clientobj) SilverMUDClient: $(clientobj)
gcc -o $@ $^ $(CLIENTLDFLAGS) gcc -s -O3 -o $@ $^ $(CLIENTLDFLAGS)
SilverMUDServer: $(serverobj) SilverMUDServer: $(serverobj)
gcc -o $@ $^ $(SERVERLDFLAGS) gcc -s -O3 -o $@ $^ $(SERVERLDFLAGS)
SilverMUDClientDebug: $(clientobj)
gcc -ggdb -Wall $^ $(CLIENTLDFLAGS) -o $@
SilverMUDServerDebug: $(serverobj)
gcc -ggdb -Wall $^ $(SERVERLDFLAGS) -o $@
.PHONY: clean .PHONY: clean
clean: clean:
rm -f $(clientobj) $(serverobj) SilverMUDClient SilverMUDServer rm -f $(clientobj) $(serverobj) SilverMUDClient SilverMUDServer SilverMUDClientDebug SilverMUDServerDebug
all: SilverMUDClient SilverMUDServer all: SilverMUDClient SilverMUDServer
debug: CFLAGS += -Wall -ggdb
debug: SilverMUDClientDebug SilverMUDServerDebug

View File

@ -12,7 +12,7 @@
#include "misc/playerdata.h" #include "misc/playerdata.h"
#include "misc/texteffects.h" #include "misc/texteffects.h"
#include "misc/inputhandling.h" #include "misc/inputhandling.h"
#define MAX 1024 #define MAX 2048
#define PORT 5000 #define PORT 5000
#define SA struct sockaddr #define SA struct sockaddr
@ -36,7 +36,6 @@ void * messageSender(void * parameters)
// Takes user input in a window, sanatizes it, and sends it to the server: // Takes user input in a window, sanatizes it, and sends it to the server:
struct threadparameters *threadParameters = parameters; struct threadparameters *threadParameters = parameters;
char sendBuffer[MAX]; char sendBuffer[MAX];
int characterindex;
while (!shouldExit) while (!shouldExit)
{ {
@ -47,7 +46,6 @@ void * messageSender(void * parameters)
// Quit if there's any funny business with getting input: // Quit if there's any funny business with getting input:
pthread_exit(NULL); pthread_exit(NULL);
} }
userInputSanatize(sendBuffer, MAX);
if(sendBuffer[0] == '\n') if(sendBuffer[0] == '\n')
{ {
continue; continue;
@ -67,9 +65,20 @@ void * messageReceiver(void * parameters)
{ {
read(threadParameters->socketDescriptor, &receiveBuffer.senderName, sizeof(receiveBuffer.senderName)); read(threadParameters->socketDescriptor, &receiveBuffer.senderName, sizeof(receiveBuffer.senderName));
read(threadParameters->socketDescriptor, &receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent)); read(threadParameters->socketDescriptor, &receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
if(receiveBuffer.senderName[0] == '\0')
{
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
}
else
{
slowPrintNcurses(receiveBuffer.senderName, 8000, threadParameters->window); slowPrintNcurses(receiveBuffer.senderName, 8000, threadParameters->window);
slowPrintNcurses(": ", 8000, threadParameters->window); slowPrintNcurses(": ", 8000, threadParameters->window);
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window); slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
}
bzero(receiveBuffer.senderName, sizeof(receiveBuffer.senderName)); bzero(receiveBuffer.senderName, sizeof(receiveBuffer.senderName));
bzero(receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent)); bzero(receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
} }
@ -78,8 +87,8 @@ void * messageReceiver(void * parameters)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int sockfd, connfd; int sockfd;
struct sockaddr_in servaddr, cli; struct sockaddr_in servaddr;
pthread_t sendingThread; pthread_t sendingThread;
pthread_t receivingThread; pthread_t receivingThread;

View File

@ -14,8 +14,8 @@
#include <netinet/in.h> #include <netinet/in.h>
#include "misc/playerdata.h" #include "misc/playerdata.h"
#include "misc/texteffects.h" #include "misc/texteffects.h"
#include "misc/inputhandling.h"
const int PORT = 5000; const int PORT = 5000;
const int MAX = 1024;
typedef struct sockaddr sockaddr; typedef struct sockaddr sockaddr;
int main() int main()
@ -24,29 +24,25 @@ int main()
socketCheck, activityCheck, readLength; socketCheck, activityCheck, readLength;
int clientSockets[64]; int clientSockets[64];
int maxClients = 64; int maxClients = 64;
userMessage sendBuffer; userMessage messageBuffer;
playerArea areaA, areaB; char receiveBuffer[2048];
playerPath pathA, pathB;
char receiveBuffer[MAX];
fd_set connectedClients; fd_set connectedClients;
playerArea * areaA, * areaB, * areaC;
playerInfo connectedPlayers[64]; playerInfo connectedPlayers[64];
struct sockaddr_in serverAddress, clientAddress; struct sockaddr_in serverAddress, clientAddress;
// Initialize areas: // Initialize areas:
strncpy(areaA.areaName, "Spawn - North", 32); areaA = createArea("Spawn - North", "A large area, mostly empty, as if the designer hadn't bothered to put anything in it, just yet.");
strncpy(areaB.areaName, "Spawn - South", 32); areaB = createArea("Spawn - South", "A strange, white void. You feel rather uncomfortable.");
strncpy(pathA.pathName, "To South Spawn", 32); areaC = createArea("Temple of Emacs", "A beautifully ornate statue of GNU is above you on a pedestal. Inscribed into the pillar, over and over, is the phrase \"M-x exalt\", in delicate gold letters. You can't help but be awestruck.");
strncpy(pathB.pathName, "To North Spawn", 32); createPath(areaA, areaB, "To South Spawn", "To North Spawn");
pathA.areaToJoin = &areaB; createPath(areaC, areaB, "Back to South Spawn", "Path to Enlightenment.");
pathB.areaToJoin = &areaA;
areaA.areaExits[0] = &pathA;
areaB.areaExits[0] = &pathB;
// Initialize playerdata: // Initialize playerdata:
for (int index = 0; index < maxClients; index++) for (int index = 0; index < maxClients; index++)
{ {
strcpy(connectedPlayers[index].playerName, "UNNAMED"); strcpy(connectedPlayers[index].playerName, "UNNAMED");
connectedPlayers[index].currentArea = &areaA; connectedPlayers[index].currentArea = areaA;
} }
// Give an intro: Display the Silverkin Industries logo and splash text. // Give an intro: Display the Silverkin Industries logo and splash text.
@ -174,6 +170,7 @@ int main()
//Check if it was for closing, and also read the incoming message //Check if it was for closing, and also read the incoming message
explicit_bzero(receiveBuffer, sizeof(receiveBuffer)); explicit_bzero(receiveBuffer, sizeof(receiveBuffer));
readLength = read(socketCheck, receiveBuffer, sizeof(receiveBuffer)); readLength = read(socketCheck, receiveBuffer, sizeof(receiveBuffer));
userInputSanatize(receiveBuffer, 2048);
if (readLength == 0) if (readLength == 0)
{ {
// Somebody disconnected , get his details and print: // Somebody disconnected , get his details and print:
@ -207,12 +204,33 @@ int main()
break; break;
} }
} }
if(newName[0] != '\0')
{
strncpy(connectedPlayers[i].playerName, newName, 32); strncpy(connectedPlayers[i].playerName, newName, 32);
} }
}
else if(strncmp(receiveBuffer, "/LOOK", 5) == 0)
{
strcat(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaDescription);
strcat(messageBuffer.messageContent, "\nYou see:");
for(int index = 0; index < 16; index++)
{
if(connectedPlayers[i].currentArea->areaExits[index] != NULL)
{
strcat(messageBuffer.messageContent, "\n - ");
strcat(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaExits[index]->pathName);
}
}
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
}
else if(strncmp(receiveBuffer, "/MOVE", 5) == 0) else if(strncmp(receiveBuffer, "/MOVE", 5) == 0)
{ {
char requestedPath[32]; char requestedPath[32];
strncpy(requestedPath, &receiveBuffer[6], 32); strncpy(requestedPath, &receiveBuffer[6], 32);
userInputSanatize(requestedPath, 32);
// Remove newlines: // Remove newlines:
for (int index = 0; index < 32; index++) for (int index = 0; index < 32; index++)
{ {
@ -221,26 +239,46 @@ int main()
requestedPath[index] = '\0'; requestedPath[index] = '\0';
} }
} }
movePlayerToArea(&connectedPlayers[i], requestedPath); requestedPath[31] = '\0';
if(movePlayerToArea(&connectedPlayers[i], requestedPath) == 0)
{
strcpy(messageBuffer.senderName, "\0");
strcpy(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaDescription);
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
}
else
{
strcpy(messageBuffer.senderName, "");
strcpy(messageBuffer.messageContent, "You can't go somewhere that doesn't exist!");
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
}
} }
} }
// Echo back the message that came in: // Echo back the message that came in:
else if (receiveBuffer[0] == '\n')
{
continue;
}
else else
{ {
printf("%d/%s/%s: %s", clientSockets[i], connectedPlayers[i].currentArea->areaName, connectedPlayers[i].playerName, receiveBuffer); printf("%d/%s/%s: %s", clientSockets[i], connectedPlayers[i].currentArea->areaName, connectedPlayers[i].playerName, receiveBuffer);
fflush(stdout); fflush(stdout);
strcpy(sendBuffer.senderName, connectedPlayers[i].playerName); strcpy(messageBuffer.senderName, connectedPlayers[i].playerName);
strcpy(sendBuffer.messageContent, receiveBuffer); strcpy(messageBuffer.messageContent, receiveBuffer);
for (int sendIndex = 0; sendIndex < clientsAmount; sendIndex++) for (int sendIndex = 0; sendIndex < clientsAmount; sendIndex++)
{ {
if(clientSockets[sendIndex] != STDIN_FILENO && (connectedPlayers[i].currentArea == connectedPlayers[sendIndex].currentArea)) if(clientSockets[sendIndex] != STDIN_FILENO && (connectedPlayers[i].currentArea == connectedPlayers[sendIndex].currentArea))
{ {
write(clientSockets[sendIndex], sendBuffer.senderName, sizeof(sendBuffer.senderName)); write(clientSockets[sendIndex], messageBuffer.senderName, sizeof(messageBuffer.senderName));
write(clientSockets[sendIndex], sendBuffer.messageContent, sizeof(sendBuffer.messageContent)); write(clientSockets[sendIndex], messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
} }
} }
bzero(sendBuffer.senderName, sizeof(sendBuffer.senderName)); bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
bzero(sendBuffer.messageContent, sizeof(sendBuffer.messageContent)); bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
} }
} }
} }

View File

@ -13,4 +13,6 @@ void userInputSanatize(char * inputString, int length)
break; break;
} }
} }
inputString[length - 1] = '\0';
} }

View File

@ -1,19 +1,74 @@
// playerdata.c: Contains functions definitions for working with player data. // playerdata.c: Contains functions definitions for working with player data.
// Barry Kane, 2021 // Barry Kane, 2021
#include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "playerdata.h" #include "playerdata.h"
// Move a player to a different area given a path in the area. // Move a player to a different area given a path in the area:
int movePlayerToArea(playerInfo * player, char * requestedPath) int movePlayerToArea(playerInfo * player, char * requestedPath)
{ {
for (int index = 0; index < 32; index++) for (int index = 0; index < 16; index++)
{
if(player->currentArea->areaExits[index] != NULL)
{ {
if(strncmp(player->currentArea->areaExits[index]->pathName, requestedPath, 32) == 0) if(strncmp(player->currentArea->areaExits[index]->pathName, requestedPath, 32) == 0)
{ {
printf("%s: %s\n", player->playerName, player->currentArea->areaExits[index]->pathName);
player->currentArea = player->currentArea->areaExits[index]->areaToJoin; player->currentArea = player->currentArea->areaExits[index]->areaToJoin;
return 0; return 0;
} }
} }
}
return 1; return 1;
} }
// Create an area given a name and description:
playerArea * createArea(char * nameString, char * descriptionString)
{
playerArea * createdArea = calloc(1, sizeof(playerArea));
strncpy(createdArea->areaName, nameString, 32);
strncpy(createdArea->areaDescription, descriptionString, 256);
for(int index = 0; index < 16; index++)
{
createdArea->areaExits[index] = NULL;
}
return createdArea;
}
// Create a path between two areas given two areas and two strings:
int createPath(playerArea * fromArea, playerArea * toArea, char * fromDescription, char * toDescription)
{
int fromAreaSlot, toAreaSlot;
for(fromAreaSlot = 0; fromAreaSlot < 16; fromAreaSlot++)
{
if(fromArea->areaExits[fromAreaSlot] == NULL)
{
break;
}
if((fromArea->areaExits[fromAreaSlot] != NULL) && (fromAreaSlot == 15))
{
return 1;
}
}
for(toAreaSlot = 0; toAreaSlot < 32; toAreaSlot++)
{
if(toArea->areaExits[toAreaSlot] == 0)
{
break;
}
if((toArea->areaExits[toAreaSlot] != 0) && (toAreaSlot == 31))
{
return 2;
}
}
playerPath * fromPath = calloc(1, sizeof(playerPath));
playerPath * toPath = calloc(1, sizeof(playerPath));
fromArea->areaExits[fromAreaSlot] = fromPath;
toArea->areaExits[toAreaSlot] = toPath;
strncpy(fromArea->areaExits[fromAreaSlot]->pathName, fromDescription, 32);
strncpy(toArea->areaExits[toAreaSlot]->pathName, toDescription, 32);
fromArea->areaExits[fromAreaSlot]->areaToJoin = toArea;
toArea->areaExits[toAreaSlot]->areaToJoin = fromArea;
}

View File

@ -1,11 +1,14 @@
// playerdata.h: Header file containing data structures for player data and function // playerdata.h: Header file containing data structures for player data and function
// definitions for interacting with said data. // definitions for interacting with said data.
// Barry Kane, 2021. // Barry Kane, 2021.
#ifndef PLAYERDATA_H
#define PLAYERDATA_H
#include <stdlib.h>
typedef struct userMessage typedef struct userMessage
{ {
char senderName[32]; char senderName[32];
char messageContent[1024]; char messageContent[2048];
} userMessage; } userMessage;
@ -21,7 +24,8 @@ struct playerPath
struct playerArea struct playerArea
{ {
char areaName[32]; char areaName[32];
playerPath * areaExits[32]; char areaDescription[256];
playerPath * areaExits[16];
}; };
typedef struct playerInfo typedef struct playerInfo
@ -30,5 +34,13 @@ typedef struct playerInfo
playerArea * currentArea; playerArea * currentArea;
} playerInfo; } playerInfo;
// Move a player to a different area given a path in the area. // Move a player to a different area given a path in the area:
int movePlayerToArea(playerInfo * player, char * requestedPath); int movePlayerToArea(playerInfo * player, char * requestedPath);
// Create an area given a name and description:
playerArea * createArea(char * nameString, char * descriptionString);
// Create a path between two areas given two areas and a string:
int createPath(playerArea * fromArea, playerArea * toArea, char * pathFromString, char * pathToString);
#endif