• This is a read only backup of the old Emudevs forum. If you want to have anything removed, please message me on Discord: KittyKaev

[SOLVED] unordered_map

Status
Not open for further replies.

Xele

Enthusiast
hi

i cannot insert rows in unordered_map don't know why this don't work please correct me.

i have included typedef std::unordered_map<uint64, bool> PlayerList; in player.h

this is my code:
Code:
static bool AddInList(ChatHandler* handler, char const* args)
{
    char* Name = strtok((char*)args, " ");
    char* Mode = strtok(NULL, " ");

    if (!Name || !Mode)
        return true;

    Player* player = sObjectAccessor->FindPlayerByName(Name);
    std::string Handle = (char*)Mode;
    PlayerList _PlayerList;

    if (player && Handle == "on")
    {
        _PlayerList.insert(PlayerList::value_type(player->GetGUID(), true));
        ChatHandler(handler->GetSession()).PSendSysMessage("INSERT");
    }
    else
    {
        _PlayerList.erase(player->GetGUID());
        ChatHandler(handler->GetSession()).PSendSysMessage("ERASE");
    }

    return true;
}
static bool ShowList(ChatHandler* handler, char const* args)
{
    PlayerList _PlayerList;

    for (PlayerList::iterator itr = _PlayerList.begin(); itr != _PlayerList.end(); ++itr)
    {
        std::string Str = itr->first + " - " + itr->second;
        ChatHandler(handler->GetSession()).PSendSysMessage("%s", Str);
    }

    return true;
}
 

Rochet2

Moderator / Eluna Dev
Your code will always destory the lists at the end of the scope, so nothing is ever actually saved or printed.
What this means is that you always create a new unordered map, insert stuff to it or print, then delete the map, so when printing, the map is always empty.
The insert should work properly.
define PlayerList _PlayerList outside the functions so it will save the values and the map wont destroy all the time.
Btw. do note that insert only works once. You cant do insert true, then insert false. It will stay true and false is ignored. but atm there is no issue as you erase.
 

Xele

Enthusiast
so, where's the best place for _PlayerList being accessible in PlayerScript and CommandScript ?
i have removed the second param from unordered_map now just an uint64 so the insert will works correctly?

now i should remove that ->first from for loop ? just an itr

Code:
for (PlayerList::iterator itr = _PlayerList.begin(); itr != _PlayerList.end(); ++itr)
    {
        std::string Str = itr;
        ChatHandler(handler->GetSession()).PSendSysMessage("%s", Str);
    }
 

Rochet2

Moderator / Eluna Dev
so, where's the best place for _PlayerList being accessible in PlayerScript and CommandScript ?
Isnt the whole script a commandscript? So inside that class.
If you need the map in a playerscript as well, you need to define it outside both classes,
howerever, depending on what hooks you use, this can be unsafe and you should post the full script or give more details.

i have removed the second param from unordered_map now just an uint64 so the insert will works correctly?
map and unordered map require a key and a value. Not sure what you mean by remobing second parameter from the map .. hmm ..
The insert worked correctly to beginwith, so I assume you now screwed it up :) Need to see what you actually did.
Unless you now decided to use some other container than map.

now i should remove that ->first from for loop ? just an itr

Code:
for (PlayerList::iterator itr = _PlayerList.begin(); itr != _PlayerList.end(); ++itr)
    {
        std::string Str = itr;
        ChatHandler(handler->GetSession()).PSendSysMessage("%s", Str);
    }
Depends on what container you use. If you are using a vector or a list, it is correct to use uint64 guid = *itr
Your code above looks wrong though. The iterator is PlayerList::iterator, not a string.
Also, you cant use an std::string as a parameter for formatted string. When using functions that format the text (IE: %u, %i, %s), the %s means a char array. so you need to convert your string to a c string with Str.c_str()
 

Xele

Enthusiast
so, let me explain what i want to do exactly.
i need a container that can holds player's guid
so i can adds player's guid in that container with commands ( dont worry about command script )
then when i need those guid will call them like this one

Code:
for (Container::iterator itr = Container.begin(); itr != Container.end(); ++itr)
    if (player->GetGUID() == itr)
        ChatHandler(handler->GetSession()).PSendSysMessage("%u", itr);

i have heard that unordered_map is faster than map, and dont know about vector and list
so i decided use unordered_map.

which one is better for my job ?

thankyou
 

Rochet2

Moderator / Eluna Dev
so, let me explain what i want to do exactly.
i need a container that can holds player's guid
so i can adds player's guid in that container with commands ( dont worry about command script )
then when i need those guid will call them like this one

Code:
for (Container::iterator itr = Container.begin(); itr != Container.end(); ++itr)
    if (player->GetGUID() == itr)
        ChatHandler(handler->GetSession()).PSendSysMessage("%u", itr);

i have heard that unordered_map is faster than map, and dont know about vector and list
so i decided use unordered_map.

which one is better for my job ?

thankyou

unordered map is faster when used with randomized keys. (not 0,1,2,3,..) and for accessing random elements.
You should first decide what you want to do with the data.
Currently your examples dont show how you exactly use the data.

You should also consider: set, vector, list

For efficiency they are all different for different tasks and with different data types.
You should benchmark them yourself for what you need, or try googling to get some sort of idea.

Anyways, this would work as an example:
Code:
        static std::unordered_set<uint64> _PlayerList;
        static bool AddInList(ChatHandler* handler, char const* args)
        {
            char* Name = strtok((char*)args, " ");
            char* Mode = strtok(NULL, " ");

            if (!Name || !Mode)
                return true;

            Player* player = sObjectAccessor->FindPlayerByName(Name);
            std::string Handle = (char*)Mode;

            if (player && Handle == "on")
            {
                _PlayerList.insert(player->GetGUID());
                ChatHandler(handler->GetSession()).PSendSysMessage("INSERT");
            }
            else
            {
                _PlayerList.erase(player->GetGUID());
                ChatHandler(handler->GetSession()).PSendSysMessage("ERASE");
            }

            return true;
        }
        static bool ShowList(ChatHandler* handler, char const* args)
        {
            for (std::set<uint64>::const_iterator itr = _PlayerList.begin(); itr != _PlayerList.end(); ++itr)
            {
                uint64 guid = *itr;
                ChatHandler(handler->GetSession()).PSendSysMessage("%u", GUID_LOPART(guid));
            }

            return true;
        }
 
Last edited:

Xele

Enthusiast
Rochet2 thank you, one of my big problem has been solved, but there is a problem that container is not accessible in PlayerScript class, see below

Code:
// Command Script
class CommandsScript : public CommandScript
{
    public:
        CommandsScript() : CommandScript("CommandsScript") { }

        ChatCommand* GetCommands() const
        {
            static ChatCommand Commands[] =
            {
                { "forbidden", rbac::RBAC_PERM_COMMAND_DEFAULT_COMMANDS, true,  &Forbidden, "", NULL },
                { NULL,       0,                                         false, NULL,       "", NULL }
            };

            return Commands;
        }

        static bool Forbidden(ChatHandler* handler, char const* args)
        {
            char* Name = strtok((char*)args, " ");
            char* Mode = strtok(NULL, " ");

            if (!Name || !Handle)
                return true;

            Player* player = sObjectAccessor->FindPlayerByName(Name);
            std::string Handle1 = (char*)Handle;

            if (player && Handle1 == "on")
            {
                _PlayerList.insert(player->GetGUID());
                ChatHandler(handler->GetSession()).PSendSysMessage("Insert");
            }
            else
            {
                _PlayerList.erase(player->GetGUID());
                ChatHandler(handler->GetSession()).PSendSysMessage("Erase");
            }

            return true;
        }
}
Code:
// Player Script
class ForbiddenPlayers : public PlayerScript
{
    public:
        ForbiddenPlayers() : PlayerScript("ForbiddenPlayers") { }

        void OnPVPKill(Player* Killer, Player* Killed) override
        {
            for (std::set<uint64>::const_iterator itr = _PlayerList.begin(); itr != _PlayerList.end(); ++itr)
                if (Killer->GetGUID() == *itr)
                    return;

           Killer->Additem(49908, 1);
        }
}

looking for a place put that container to being accessible in both classes
 
Last edited:

Rochet2

Moderator / Eluna Dev
Rochet2 thank you, one of my big problem has been solved, but there is a problem that container is not accessible in PlayerScript class, see below
looking for a place put that container to being accessible in both classes

Already answered to this in second post when you revealed you had another script class needing it as well

If you need the map in a playerscript as well, you need to define it outside both classes,
howerever, depending on what hooks you use, this can be unsafe and you should post the full script or give more details.
 

Xele

Enthusiast
those scripts was in separates files so, that way you told didn't work, so i put them all in one single file then problem solved :cool (2):
 

Rochet2

Moderator / Eluna Dev
those scripts was in separates files so, that way you told didn't work, so i put them all in one single file then problem solved :cool (2):

This is exactly why it is suggested, or rather required, that you post all information you can provide and possibly even the script to beginwith.
Nobody can read your mind. And as far as I know, I dont have your computer under surveillance.. yet.
:3
 
Status
Not open for further replies.
Top