Tell me more ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

UPDATE After going over all my code, the updating code was pointing to the wrong variable which made it null. It works now, very good may I add, thanks for anyone who took the time.

I have a C++ server I am working on for a game. And I have a class with a mutex that will sometimes return the "player_map_id" as blank, but the rest of the packet that is generated is fine. Here is my function: NOTE every function in this call is started with a WaitForSingleObject, so I dont know if its a race condition or what ...

CLASS:

class _PLAYER_INFORMATION_OBJ {
public:
    void SET_OBJ ( string client_id, string client_id_len, string player_name, string player_name_len, string player_id, string player_class_id, string player_level, string player_experience,
                    string player_health, string player_mana, string player_str, string player_vit, string player_dex, string player_int, string player_agi, string player_defense, 
                    string player_velocity, string player_buff, string player_debuff, string player_status, string player_map_id, string player_x_pos, string player_y_pos );
    bool SAVE ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id );
    bool CLIENT_CONNECT_CHECK ( vector<_PLAYER_INFORMATION_OBJ> &s, string id );
    bool CHANGE_STATUS ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string player_status );
    bool UPDATE_MAP_ID_X_POS_Y_POS ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string player_map_is, string player_x_pos, string player_y_pos );
    string Return_New_Player_Info_String ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string send_to_client_id, string send_to_client_id_len,  string packet_type);
    string Return_New_Player_X_Y_String ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string send_to_client_id, string send_to_client_id_len,  string packet_type);
    string Return_Delete_Player_From_Object_String ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string send_to_client_id, string send_to_client_id_len,  string packet_type );

private:
    string              client_id;
    string              client_id_len;
    string              player_name;
    string              player_name_len;
    string              player_id;
    string              player_class_id;
    string              player_level;
    string              player_experience;
    string              player_health;
    string              player_mana;
    string              player_str;
    string              player_vit;
    string              player_dex;
    string              player_int;
    string              player_agi;
    string              player_defense;
    string              player_velocity;
    string              player_buff;
    string              player_debuff;
    string              player_status;
    string              player_map_id;
    string              player_x_pos;
    string              player_y_pos;
};


string _PLAYER_INFORMATION_OBJ:: Return_New_Player_Info_String ( vector<_PLAYER_INFORMATION_OBJ> &s, string client_id, string send_to_client_id, string send_to_client_id_len, string packet_type ) {
DWORD dwCount=0, dwWaitResult;

string player_information_string;

    while( dwCount < 2000 ) {
dwWaitResult = WaitForSingleObject( PLAYER_INFORMATION_CLASS, INFINITE );
        switch (dwWaitResult) {
            case WAIT_OBJECT_0:{
                vector<_PLAYER_INFORMATION_OBJ>::iterator it;
                it = s.begin();

                if(it == s.end()){
                    dwCount = 2000;
                    break;
                }

                while(it != s.end()) {
                    if(it->client_id == client_id) {
                        string player_name_ascii = it->player_name;
                        string player_name_hex;
                        player_name_hex = ascciStringToHexString(player_name_ascii);

                        string type = packet_type;

                        string WORD_PACKET_LEN_FINDER = "0000" + type + it->player_id + it->player_class_id + it->player_level + it->player_health + it->player_mana + 
                        it->player_buff + it->player_debuff + it->player_status + it->player_map_id + it->player_x_pos + it->player_y_pos + it->player_name_len + player_name_hex;

                        string WORD_PACKET_LEN = toHexadecimal(WORD_PACKET_LEN_FINDER.length()/2, 4);

                        string WORD_WHOLE_LEN_FINDER = "0000" + send_to_client_id_len + send_to_client_id + WORD_PACKET_LEN + "0000" + type + it->player_id + it->player_class_id + it->player_level + it->player_health + 
                        it->player_mana + it->player_buff + it->player_debuff + it->player_status + it->player_map_id + it->player_x_pos + it->player_y_pos + it->player_name_len + player_name_hex;

                        string WORD_WHOLE_LEN_PACKET = toHexadecimal(WORD_WHOLE_LEN_FINDER.length()/2, 4);

                        player_information_string = WORD_WHOLE_LEN_PACKET + send_to_client_id_len + send_to_client_id + WORD_PACKET_LEN + "0000" + type + it->player_id + it->player_class_id + it->player_level + it->player_health + 
                        it->player_mana + it->player_buff + it->player_debuff + it->player_status + it->player_map_id + it->player_x_pos + it->player_y_pos + it->player_name_len + player_name_hex;

                    }

                    break;
                }

                if(it != s.end())
                    it++;
                }
            dwCount = 2000;
            }
            break;

            case WAIT_ABANDONED:
                dwCount = 2000;
                break;

            case WAIT_FAILED:
                cout << "WAIT FAILED" << endl;
                dwCount++;
                break;
        }
}

    ReleaseMutex(PLAYER_INFORMATION_CLASS);
return player_information_string;
}

AND HOW ITS CALLED: (the code is bad, I never did antyhing this big before :p)

bool _PLAYER_MAP_AI:: PLAYER_AI_CHECK_AREA ( vector<_PLAYER_MAP_AI> &s, string client_id, string client_id_len, string player_map_id, string player_x_pos, string player_y_pos ) {
DWORD dwCount=0, dwWaitResult;
bool return_value = false;  // false means dont update the player_map_ai

while( dwCount < 2000 ) {
dwWaitResult = WaitForSingleObject( PLAYER_MAP_AI_CLASS, INFINITE );
    switch (dwWaitResult) {
        /// The thread got ownership of the mutex
        case WAIT_OBJECT_0:{
            vector<_PLAYER_MAP_AI>::iterator it;
            it = s.begin();
            _PLAYER_INFORMATION_OBJ C;
            _QUE_PACKET_SEND_OBJ S;

            if(it == s.end()){ // if this is empty... it cant happen lol
                cout << "Seems like player_ai_check_area is empty..." << endl;
                dwCount = 2000; // so we know itll end the loop
                break;
            }

            while(it != s.end()) {
                if(it->client_id == client_id ) {   //
                    if(it->player_map_id == player_map_id) {    // this says okay.. you didnt change areas yet
                        return_value = true;    // this means okay when we return well update the AI information with our new map,x,y information

                    // if this triggers it means you were already in the area but we still need a way to know if you need to update anyone
                    if(it->player_in_group == false) {
                        it->player_in_group = true;
                        // this says oh okay your not in a group yet...  so lets gather everyone in the area thats in the same player_map_id
                        vector<_PLAYER_MAP_AI>::iterator check;
                        check = s.begin();
                        while(check != s.end()){
                            // this will gather every-single-player in your map id
                            if(check->player_map_id == player_map_id && check->client_id != client_id) {    // makes it so we dont send ourself our own information ...
                                // now we just send everyone our info

                                string New_Player_Info_In_String = C.Return_New_Player_Info_String(PLAYER_INFORMATION_OBJ, client_id, check->client_id, check->client_id_len, "01" );

                                // so now we have sent everyone (but ourselves) our player information object class so they can add us to their client list
                                S.SET_OBJ(Socket,New_Player_Info_In_String,New_Player_Info_In_String.length());
                                string Update_Self_New_Player_Info_In_String = C.Return_New_Player_Info_String(PLAYER_INFORMATION_OBJ, check->client_id, client_id, client_id_len, "01" );

                                // Thread the sends information
                                S.SET_OBJ(Socket,Update_Self_New_Player_Info_In_String,Update_Self_New_Player_Info_In_String.length());
                                check->player_in_group = true;

                            }

                            if(check != s.end())
                                check++;
                        }
                    } else {

.... the above part is what is generated first (that gives the player_map_id as nothing sometimes. I have checked and the information of the player_map_id is actually loaded into the server... and sometimes if i have 5 players in the game, it'll send the player_map_id to some players, and other players get nothing, so the data they parse is off.

Sorry for the long post. Should I switch to boost...

share|improve this question
"Should I switch to boost" I don't think that would help. Your problem seems like a serious lack of understanding how threading works. In general, if you "dont know if its a race condition," then you shouldn't be writing threaded code. – Nicol Bolas May 10 '12 at 19:06
Good idea, maybe ill never try and write threaded code ever so I never learn. >.> – user1328762 May 10 '12 at 20:52
1  
Writing threaded code is not how you learn about threading. Learning about threading is how you learn about threading. There are books, articles, and such you should be reading before tangling with code. – Nicol Bolas May 10 '12 at 20:56
I don't see the relevance to my question. Even a scholar in college who reads a book about threads and understands the principles would most likely run into problems(the first time). My server doesn't crash or anything (even if I spam it hardcore), it just is missing a single string, that is in the middle of the code. So I am extremely confused... if the memory was changed halfway through, x_pos, and y_pos, etc wouldnt be missing, and in this case it isnt. Maybe if the question was re-worded to: "What can cause a string to return empty, even if its part of the same class" ? – user1328762 May 10 '12 at 21:07

closed as too localized by Joe Wreschnig, Tetrad May 11 '12 at 7:10

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, see the FAQ.