10 May, 2008, Impacatus wrote in the 1st comment:
Votes: 0
I've been making some progress tinkering with the socketmud database, but I've run into another problem. I'd like to create a datastructure of players that contains the socket that player is connected with. Thus:
// ****************************************************************************
// SocketMud II Copyright 2004 Brian Graversen
// ****************************************************************************
// Revision History
// —————-
// 19/01/04) Initial SocketMud II code released
// ****************************************************************************
// This product can be used freely as long as this copyright header remains
// intact. This header may not be removed or changed, and any work released
// based on this code must contain this header information in all files.
// ****************************************************************************

#include "server.h"
#include <string>

// The storage site of all information pertaining to individual users
struct players {
std::string name;
Socket connection;
} players [100];

int main(int argc, char** argv) {
Server *mServer = new Server();
int port;

switch(argc) {
case 2:
port = atoi(argv[1]);
if (port < 1024 || port > 9999) {
printf("[port] must be between 1024 and 9999\n");
return 1;
}
break;

default:
printf("Syntax: %s [port]\n", argv[0]);
return 1;
}

mServer->Connect(port);

while(1) {
// poll all sockets for incoming data
mServer->PollSockets();

std::list<Socket*> socketList = mServer->GetSocketList();
std::list<Socket*>::iterator iSocket;
Socket *pSocket;

// echo everything that each socket has sent to us
for (iSocket = socketList.begin(); iSocket != socketList.end(); ) {
pSocket = *iSocket++;

pSocket->Write(pSocket->GetInBuffer());
pSocket->ClrInBuffer();
}

// flush all outgoing data
mServer->FlushSockets();

// sleep the rest of the pulse
mServer->Sleep(5);
}

return 1;
}
This gets compilation errors, because it doesn't seem to recognize Socket as a datatype, even though it's used without problem in the main function. Through some experimentation, I've realized that the compiler doesn't mind if the structure is after the main function, so I'm assuming there's something in there that makes it valid.

The problem is if I declare the structure after the main function, I can't use it in the main function, or call any functions that use the Socket datatype. How can I make a usable structure of player information that contains their socket? Thanks in advance for your help.
10 May, 2008, David Haley wrote in the 2nd comment:
Votes: 0
Do you ever actually declare the Socket type? Note that your main function uses it as a pointer whereas the structure uses it as an actual structure. If you only have Socket declared using a forward declaration, then it's ok to use it as a pointer.

It might help to show the exact compiler errors you're getting, though, and what happens when you move the structure to below the main function.
10 May, 2008, Impacatus wrote in the 3rd comment:
Votes: 0
Thanks for your response. I noticed that I can use the type in the struct if I use it as a pointer. However, I'd also like to be able to pass it to functions. I was mistaken about there being any difference if I place it at the bottom.

How would I go about declaring the Socket type? I do see this code in the server.h header file:
std::list<Socket*>   socketList;
int control;
fd_set fSet;
fd_set rSet;
sockaddr_in my_addr;
struct timeval lastSleep;


I'm wondering if I shouldn't use a list to store the socket value. I tried to record the error I got, but it's difficult since I can't copy paste from my terminal window. (Edit: Apparently I can. Right now I don't really have time to reproduce the error, but maybe I will when I can.) I tried to transcribe it, but then it got lost so I gave up for now. There are several other things I want to try when I get the chance.
11 May, 2008, Davion wrote in the 4th comment:
Votes: 0
The problem definitely isn't because you don't have Socket declared. It is, in socket.h and included with server.h. As for why you can't use this:

class Player
{ public:
string name;
Socket connection;
};


Is because the Socket class no longer has a default constructor. It also doesn't have a copy constructor so probably a good idea not to use references!
11 May, 2008, David Haley wrote in the 5th comment:
Votes: 0
Well, if there's no default constructor, you can still use it as a non-pointer, you just have to make sure that the enclosing object calls an appropriate constructor.

Impactus said:
I noticed that I can use the type in the struct if I use it as a pointer. However, I'd also like to be able to pass it to functions.

I'm not sure I see the problem here. You can pass references and pointers to functions, so why would a pointer prevent you from passing it to functions?

It would probably be most helpful to wait until we can see what exactly you are getting as error messages, so let's wait until you get a chance to copy/paste those.

Davion said:
It also doesn't have a copy constructor so probably a good idea not to use references!

Why is that? A reference isn't a copy, so it should be fine to use it.
12 May, 2008, Davion wrote in the 6th comment:
Votes: 0
DavidHaley said:
Davion said:
It also doesn't have a copy constructor so probably a good idea not to use references!

Why is that? A reference isn't a copy, so it should be fine to use it.


Err uhm. Ya, that's right! Passing not by reference than… I always mess that up! So like void some_fun( Player pl ) would be (possibly) bad if you didn't have a proper copy constructor.
12 May, 2008, David Haley wrote in the 7th comment:
Votes: 0
If you don't have a copy constructor, the compiler will generate one for you that (IIRC) does a member-by-member copy. If any members forbid copying (by e.g. making the copy constructor private) then you won't be able to copy the whole structure. If you make the structure's copy constructor private, then you won't be able to copy it.
15 May, 2008, Impacatus wrote in the 8th comment:
Votes: 0
Sorry I took so long to get back to this, I've been pretty busy, but I really appreciate your help. Here's the program I try
// ****************************************************************************
// SocketMud II Copyright 2004 Brian Graversen
// ****************************************************************************
// Revision History
// —————-
// 19/01/04) Initial SocketMud II code released
// ****************************************************************************
// This product can be used freely as long as this copyright header remains
// intact. This header may not be removed or changed, and any work released
// based on this code must contain this header information in all files.
// ****************************************************************************

#include "server.h"
#include <string>

struct players {
std::string name;
Socket *connection;
} player [100];

int compare (socket *psocket, number) {
if (psocket = player[number].connection) {
return 1;}
return 0;
}

int main(int argc, char** argv) {
Server *mServer = new Server();
int port;


switch(argc) {
case 2:
port = atoi(argv[1]);
if (port < 1024 || port > 9999) {
printf("[port] must be between 1024 and 9999\n");
return 1;
}
break;

default:
printf("Syntax: %s [port]\n", argv[0]);
return 1;
}

mServer->Connect(port);

while(1) {
// poll all sockets for incoming data
mServer->PollSockets();

std::list<Socket*> socketList = mServer->GetSocketList();
std::list<Socket*>::iterator iSocket;
Socket *pSocket;

// echo everything that each socket has sent to us
for (iSocket = socketList.begin(); iSocket != socketList.end(); ) {
pSocket = *iSocket++;
compare (pSocket, 1);
pSocket->Write(pSocket->GetInBuffer());
pSocket->ClrInBuffer();
}

// flush all outgoing data
mServer->FlushSockets();

// sleep the rest of the pulse
mServer->Sleep(5);
}

return 1;
}


And here's the errors I get:
Quote
# g++ socketmud.cpp server.cpp socket.cpp server.h socket.h -o smud
socketmud.cpp:21: error: 'psocket' was not declared in this scope
socketmud.cpp:21: error: 'number' was not declared in this scope
socketmud.cpp:21: error: initializer expression list treated as compound expression
socketmud.cpp:21: error: expected ',' or ';' before '{' token
socketmud.cpp: In function 'int main(int, char**)':
socketmud.cpp:59: error: 'compare' cannot be used as a function
15 May, 2008, David Haley wrote in the 9th comment:
Votes: 0
OK, first thing is that this code is confusingly formatted and should be changed:
int compare (socket *psocket, number) {
if (psocket = player[number].connection) {
return 1;}
return 0;
}

This is much clearer:
int compare (socket *psocket, number) {
if (psocket = player[number].connection) {
return 1;
}
return 0;
}


Note that you have a single equals in there, which is probably not what you meant to do.

You refer to the structure "player", but above you called it "players", not "player". So that won't work…

Finally, sometimes you capitalize the Socket type, and other times you leave the first character as lowercase. You need to figure out what the actual capitalization is and stick to that.
15 May, 2008, Impacatus wrote in the 10th comment:
Votes: 0
Ah that was it, it was the capitalization. I also needed to put an "int" before number, and add another "=" like you said.

For the record, I'm not sure, but I think even though the structure is called players, the individual members are called "player[x]". At any rate, it compiled ok without the "s", I need to go really soon, otherwise I'd try running the program. Thank you very, very, much for all your patience and help everyone.
15 May, 2008, David Haley wrote in the 11th comment:
Votes: 0
Ah, I hadn't noticed that it was missing the "int", too. Good catch on that on.

As for "players" vs. "player[x]": If the structure is called "players", then the only way to access it is using "players" – if you use "player" and that works, then you're not talking to what you think you are. C/C++ are extremely literal this way: you will get exactly what you type; it does not do any clever things for you. :smile:
16 May, 2008, Impacatus wrote in the 12th comment:
Votes: 0
Ok, I'm confused.
struct players {
std::string name;
Socket *connection;
} player [100];

I was under the impression that you access an individual member the structure using the bottom line. In this case I was attempting to compare a single object of the "players" type, not the "players" structure itself. I read here:
Quote
struct product {
int weight;
float price;
} apple, banana, melon;



It is important to clearly differentiate between what is the structure type name, and what is an object (variable) that has this structure type. We can instantiate many objects (i.e. variables, like apple, banana and melon) from a single structure type (product).
So in my case, wouldn't "players" be the structure type, and "player[x]" be an object of the type "players"?

I could be mistaken of course, but I'm pretty sure I've gotten this to work fine in other projects. Perhaps I should have made the names less similar to prevent confusion, but from what I can tell I'm using it correctly. Could you please explain to me where my mistake is?
16 May, 2008, David Haley wrote in the 13th comment:
Votes: 0
Ungh, I'm sorry. Your first response and my quick reading made me think that the instance of the structure was called players; also, I'm following a convention where class names tend to be capitalized. (Having a good naming convention avoids a lot of potential confusion.) So you're right: if the variable is called player, then you access it with just player.
16 May, 2008, Impacatus wrote in the 14th comment:
Votes: 0
Alright. I picked up most of my programming knowledge outside a classroom setting, and outside of situations like these I'm generally the only one who sees my code, so I never really learned the conventions. I'll try to pay more attention to them next time I have someone look over some code. In the meantime, thanks again for all your help, that should hopefully be enough for me to work with for now.
0.0/14