Gamemode SDK for C/C++ (GDK)
#41

Is there any vector or any way to access all Player class objects?
I would like to extend Player class and access those objects using the object and not the playerid parameter.
Reply
#42

Thank you very much for this awesome project.
Reply
#43

Quote:
Originally Posted by Stewie`
Посмотреть сообщение
Is there any vector or any way to access all Player class objects?
I would like to extend Player class and access those objects using the object and not the playerid parameter.
No, there's no such thing built-in but you can store Player's in a container (probably std:et) once they connect and remove them on disconnect. I'd create a separate class for this purpose, roughly something like this:

pawn Код:
class Players {
 public:
  ....

  static MyPlayer *GetPlayer(int playerid) {
    // Retrieve the existing Player object from players or add a new one.
  }
  ...

 private:
  // A comparison function for std::set - compares two players using on their IDs.
  static int ComparePlayers(const MyPlayer *p, const MyPlayer *q) {
    return p->GetId() - q->GetId();
  }

  static std::set<MyPlayer*, ComparePlayers> players;
};
and then use it in SA-MP callbacks to convert player IDs to MyPlayer's:

pawn Код:
bool OnPlayerConnect(int playerid) {
  MyPlayer *player = Players::GetPlayer(playerid);
  // Do stuff with player
}
Reply
#44

As I realized Player class is nothing more than a nice interface, I did something like this:
pawn Код:
class MyPlayer :
    public Player
{
    explicit MyPlayer(int x) : Player(x) { }
};
Reply
#45

GDK 3.3 is released!
  • Fixed a bug that stopped certain callbacks defined in gamemodes and
    filterscripts from being executed
  • Fixed a crash happening when a native function that is called is not found
  • Changed return type of some of the core API functions (and corresponding Plugin
    methods) to int so they now return an error code when fail and a non-negative
    return value indicates success
  • Renamed some methods of the Player and Vehicles classes
  • Added the FindSampGdk3 module to be used with CMake's find_pacakge() command
Reply
#46

Added documentation on CMake and FindSampGdk3 (see "Using CMake" at the bottom of the first post).
Reply
#47

What does the 'Plugin does not conform to architecture.' error message mean? What did I leave out?
I am using Visual Studio 2012 on Windows 7 (64bit) and compiled the helloworld gamemode with no errors.
Edit: Btw if this helps, I am linking with #pragma comment(lib, "sampgdk3.lib")

Edit: This is utterly embarassing. To anyone wondering, my error was caused by not downloading the .def file. ._.
Reply
#48

It means your plugin doesn't export one of the functions that the SA-MP server expects be exported, such as Supports() or Load(). AFAIK, Unload() is not mandatory, AmxLoad() and AmxUnload() are needed if you return the SUPPORTS_AMX_NATIVES flag in Supports(), and ProcessTick() is required if you return SUPPORTS_PROCESS_TICK.

Quote:
Originally Posted by fml
Посмотреть сообщение
What does the 'Plugin does not conform to architecture.' error message mean? What did I leave out?
Edit: This is utterly embarassing. I thought I didn't even need to read the CMake stuff since I just wanted to create a quick test, but no. I've read that this error is caused by not having a .def file for your project, trying cmake now
You don't have to use CMake.
Reply
#49

Hi. I don't know it's an bug or maybe I'm doing something wrong. Further - I've this code:
pawn Code:
extern "C"
{
    bool __stdcall OnPlayerConnect(int playerid)
    {
        int giveplayerid;
        char join[144];
        SendClientMessage(playerid, COLOR_GREEN, "Hello.");
        sprintf(join, "%s joined to us. IP: %s", giveplayerid, ReturnIP(giveplayerid));
        SendPlayerMessageToAll(giveplayerid, join);
        return true;
    }
}
If I'm try to connect, I see this message, but the server immediately shuts down, but only, if I have "sprintf..." in code. I tried change SendPlayerMessageToAll to SendClientMessageToAll - the same problem, server immediately shutting down.

How to fix it?
Reply
#50

Quote:
Originally Posted by Dystans
View Post
Hi. I don't know it's an bug or maybe I'm doing something wrong. Further - I've this code:
pawn Code:
extern "C"
{
    bool __stdcall OnPlayerConnect(int playerid)
    {
        int giveplayerid;
        char join[144];
        SendClientMessage(playerid, COLOR_GREEN, "Hello.");
        sprintf(join, "%s joined to us. IP: %s", giveplayerid, ReturnIP(giveplayerid));
        SendPlayerMessageToAll(giveplayerid, join);
        return true;
    }
}
If I'm try to connect, I see this message, but the server immediately shuts down, but only, if I have "sprintf..." in code. I tried change SendPlayerMessageToAll to SendClientMessageToAll - the same problem, server immediately shutting down.

How to fix it?
pawn Code:
extern "C"
{
    bool __stdcall OnPlayerConnect(int playerid)
    {
        char join[144], name[24];
                GetPlayerName(playerid, name, 24);
        SendClientMessage(playerid, COLOR_GREEN, "Hello.");
        sprintf(join, "%s joined to us. IP: %s", name, ReturnIP(playerid));
        SendClientMessageToAll(COLOR_GREEN, join);
        return true;
    }
}
Reply
#51

My issue was another, but thanks.
But now I would like to use the strfind function, that in C++ and GDK don't exists. So... how I can modify this code to work properly?
pawn Code:
int GetVehicleModelIDFromName(char vname[])
{
    for(int i = 0; i < 211; i++)
    {
        if(strfind(aVehicleNames[i], vname) != -1) // I don't know what I could replace strfind. When I'm tried with string::vname.find - I've an bug - when I wrote "/car infernus", I received Landstalker...
        return i + 400;
    }
    return -1;
}
Reply
#52

pawn Code:
int GetVehicleModelIDFromName(std::string vname)
{
    for(int i = 0; i < 211; i++)
    {
        if( vname.find( aVehicleNames[i] ) != std::string::npos )
        {
            return i + 400;
        }
    }
    return -1;
}
Reply
#53

Quote:
Originally Posted by Dystans
View Post
My issue was another, but thanks.
But now I would like to use the strfind function, that in C++ and GDK don't exists. So... how I can modify this code to work properly?
pawn Code:
int GetVehicleModelIDFromName(char vname[])
{
    for(int i = 0; i < 211; i++)
    {
        if(strfind(aVehicleNames[i], vname) != -1) // I don't know what I could replace strfind. When I'm tried with string::vname.find - I've an bug - when I wrote "/car infernus", I received Landstalker...
        return i + 400;
    }
    return -1;
}
Quote:
Originally Posted by iggy1
View Post
pawn Code:
int GetVehicleModelIDFromName(std::string vname)
{
    for(int i = 0; i < 211; i++)
    {
        if( vname.find( aVehicleNames[i] ) != std::string::npos )
        {
            return i + 400;
        }
    }
    return -1;
}
if you always know the exact name I recommend you guys the C++ approach :P

pawn Code:
#include <algorithm>
    #include <string>
    #include <map>

    std::map<std::string,unsigned int> Vehicles;
    void InitVehicleNames()
    {
        //for consistency use only lowercase, or uppercase, but not both
        Vehicles["landstalker"] = 400;
        Vehicles["bravura"] = 401;
        //....
    }
    unsigned int GetVehicleIdFromName(std::string name)//returns 0 when not found
    {
        //uncomment if you want case-insensetive compare
        //std::string lowername(name);
        //std::transform(name.begin(), name.end(), name.begin(), ::tolower);
        if(Vehicles.find(name) != Vehicles.end())
            return Vehicles[name];//change 'name' to 'lowername' for case insensetive compare
        return 0;
    }
Reply
#54

Iggy1, your code don't work.
Gamer_Z, thanks, but what I have to do when I want to type "/car inf" and this command spawn the Infernus in the same way as "/car 411" and "/car Infernus"? More specifically, I want to check only part of whole name.

@edit: I don't know what I'm doing bad, but errm... your code didn't work too. I'm create map, as you told me, but when I try to execute this command in OnPlayerCommandText:
pawn Code:
else if(strcmp(cmd, "/car") == 0)
    {
        int carid;
        char
                string[148],
                *cmd;

        cmd = strtok(const_cast<char*>(cmdtext), " ");
        #define strtok_special(a,b) cmd = strtok(NULL, " "); if(cmd == 0 || !strlen(cmd)) return a; b = strval(cmd);
        strtok_special(SendClientMessage(playerid, COLOR_WHITE, "/car [id / name]"), carid);
        if(!strlen(cmd)) return SendClientMessage(playerid, COLOR_ADMIN, "Where is your car name?");

        carid = GetVehicleModelIDFromName(cmd);
        //if(carid < 400 || carid > 611) return SendClientMessage(playerid, COLOR_ADMIN, "That vehicle name was not found"); // I suggested this code, but it nothing happens even it is commented. I've only message below, but without car name and ID...
        sprintf(string, "Car: %s, ID: %d", aVehicleNames[carid - MIN_VEHI_ID], carid);
        SendClientMessage(playerid, COLOR_GREEN, string);
        CreatePlayerVehicle(playerid, carid);
        return true;
    }
nothing spawns.
Reply
#55

This works for me. (array copied from a forum post)

Console APP just for speed of testing.
pawn Code:
#include <string>
#include <iostream>

char aVehicleNames[212][32] =
{
    {"Landstalker"},
    {"Bravura"},
    {"Buffalo"},
    {"Linerunner"},
    {"Perrenial"},
    {"Sentinel"},
    {"Dumper"},
    {"Firetruck"},
    {"Trashmaster"},
    {"Stretch"},
    {"Manana"},
    {"Infernus"},
    {"Voodoo"},
    {"Pony"},
    {"Mule"},
    {"Cheetah"},
    {"Ambulance"},
    {"Leviathan"},
    {"Moonbeam"},
    {"Esperanto"},
    {"Taxi"},
    {"Washington"},
    {"Bobcat"},
    {"MrWhoopee"},
    {"BFInjection"},
    {"Hunter"},
    {"Premier"},
    {"Enforcer"},
    {"Securicar"},
    {"Banshee"},
    {"Predator"},
    {"Bus"},
    {"Rhino"},
    {"Barracks"},
    {"Hotknife"},
    {"Trailer1"},
    {"Previon"},
    {"Coach"},
    {"Cabbie"},
    {"Stallion"},
    {"Rumpo"},
    {"RCBandit"},
    {"Romero"},
    {"Packer"},
    {"Monster"},
    {"Admiral"},
    {"Squalo"},
    {"Seasparrow"},
    {"Pizzaboy"},
    {"Tram"},
    {"Trailer2"},
    {"Turismo"},
    {"Speeder"},
    {"Reefer"},
    {"Tropic"},
    {"Flatbed"},
    {"Yankee"},
    {"Caddy"},
    {"Solair"},
    {"BerkleyRCVan"},
    {"Skimmer"},
    {"PCJ-600"},
    {"Faggio"},
    {"Freeway"},
    {"RCBaron"},
    {"RCRaider"},
    {"Glendale"},
    {"Oceanic"},
    {"Sanchez"},
    {"Sparrow"},
    {"Patriot"},
    {"Quad"},
    {"Coastguard"},
    {"Dinghy"},
    {"Hermes"},
    {"Sabre"},
    {"Rustler"},
    {"ZR-350"},
    {"Walton"},
    {"Regina"},
    {"Comet"},
    {"BMX"},
    {"Burrito"},
    {"Camper"},
    {"Marquis"},
    {"Baggage"},
    {"Dozer"},
    {"Maverick"},
    {"NewsChopper"},
    {"Rancher"},
    {"FBIRancher"},
    {"Virgo"},
    {"Greenwood"},
    {"Jetmax"},
    {"Hotring"},
    {"Sandking"},
    {"Blista Compact"},
    {"Police Maverick"},
    {"Boxville"},
    {"Benson"},
    {"Mesa"},
    {"RCGoblin"},
    {"HotringRacer A"},
    {"HotringRacer B"},
    {"BloodringBanger"},
    {"Rancher"},
    {"SuperGT"},
    {"Elegant"},
    {"Journey"},
    {"Bike"},
    {"MountainBike"},
    {"Beagle"},
    {"Cropdust"},
    {"Stunt"},
    {"Tanker"},
    {"Roadtrain"},
    {"Nebula"},
    {"Majestic"},
    {"Buccaneer"},
    {"Shamal"},
    {"Hydra"},
    {"FCR-900"},
    {"NRG-500"},
    {"HPV1000"},
    {"CementTruck"},
    {"TowTruck"},
    {"Fortune"},
    {"Cadrona"},
    {"FBITruck"},
    {"Willard"},
    {"Forklift"},
    {"Tractor"},
    {"Combine"},
    {"Feltzer"},
    {"Remington"},
    {"Slamvan"},
    {"Blade"},
    {"Freight"},
    {"Streak"},
    {"Vortex"},
    {"Vincent"},
    {"Bullet"},
    {"Clover"},
    {"Sadler"},
    {"FiretruckLA"},
    {"Hustler"},
    {"Intruder"},
    {"Primo"},
    {"Cargobob"},
    {"Tampa"},
    {"Sunrise"},
    {"Merit"},
    {"Utility"},
    {"Nevada"},
    {"Yosemite"},
    {"Windsor"},
    {"MonsterA"},
    {"MonsterB"},
    {"Uranus"},
    {"Jester"},
    {"Sultan"},
    {"Stratum"},
    {"Elegy"},
    {"Raindance"},
    {"RC Tiger"},
    {"Flash"},
    {"Tahoma"},
    {"Savanna"},
    {"Bandito"},
    {"FreightFlat"},
    {"StreakCarriage"},
    {"Kart"},
    {"Mower"},
    {"Duneride"},
    {"Sweeper"},
    {"Broadway"},
    {"Tornado"},
    {"AT-400"},
    {"DFT-30"},
    {"Huntley"},
    {"Stafford"},
    {"BF-400"},
    {"Newsvan"},
    {"Tug"},
    {"Trailer 3"},
    {"Emperor"},
    {"Wayfarer"},
    {"Euros"},
    {"Hotdog"},
    {"Club"},
    {"FreightCarriage"},
    {"Trailer3"},
    {"Andromada"},
    {"Dodo"},
    {"RCCam"},
    {"Launch"},
    {"PoliceCar(LSPD)"},
    {"PoliceCar(SFPD)"},
    {"PoliceCar(LVPD)"},
    {"PoliceRanger"},
    {"Picador"},
    {"S.W.A.T.Van"},
    {"Alpha"},
    {"Phoenix"},
    {"Glendale"},
    {"Sadler"},
    {"LuggageTrailerA"},
    {"LuggageTrailerB"},
    {"StairTrailer"},
    {"Boxville"},
    {"FarmPlow"},
    {"UtilityTrailer"}
};

int GetVehicleModelIDFromName(std::string vname)
{
    for(int i = 0; i < 211; i++)
    {
        if( vname.find( aVehicleNames[i] ) != std::string::npos )
        {
            return i + 400;
        }
    }
    return -1;
}

int main()
{
    std::cout << "Infernus ID == " <<
        GetVehicleModelIDFromName("Infernus") << std::endl;
    return 0;
}
Obviously using a map is better, but just thought I'd show you the code DOES work.

find() looks for a substring and returns std:tring::npos if not found.

EDIT:
Was thinking it would be a pain in the ass inserting all those values into a map so i wrote this small loop that creates a file called "VehicleMap.txt". It defines an unordered_map that holds vehicle names and ids.

This needs to be used with the above code. It's not optimized because it only needs to be run once.

pawn Code:
#include <fstream>
#include <sstream>

int main()
{
    std::ofstream out("vehiclemap.txt");

    if( out.is_open() )
    {
        out << "std::unordered_map<std::string, int> gVehicleMap;\n\n";

        for(int i = 0; i < 211; i++)
        {
            std::stringstream buffer;
            buffer << "gVehicleMap.insert( std::make_pair<std::string, int>( (std::string)\""
                << aVehicleNames[i] << "\", " << GetVehicleModelIDFromName( aVehicleNames[i] )
                    << ") );" << std::endl;
            out << buffer.str();
        }
        out.close();
    }
    return 0;
}
Tested and it generates valid code.
OUTPUT
Reply
#56

Hm... your example works well for me, so... how can I write my code of command to run it normally, without bugs?
Reply
#57

А можно скомпилировать все в один плагин? Без использования libsampgdk.so.3.2

Объясните пожалуйста.
Reply
#58

Does anyone use this on a real server?
Reply
#59

It depends what you consider a "real server" to be.

Mine uses it and I'm about 20% done in rewriting my whole gamemode into C++ (many segments partially exist in both PAWN code and C++ to not lose functionality).

About players - I don't know if it could be called a real server since it has been 2 years since we last had ~200 players online, currently averaging at about 20.

... But I think this creation is just perfect. I do have some random crashes like once a day or so which crashdetect doesn't show an exact reason for, but streamer.so seems to be the highest up in the call log so I assume it has something to do with it.
Reply
#60

Any idea how to import the "command processor" into C++, example ZCMD?

I think its possible to do with "int asdasd(...)" but I don't know how to call it.
Reply


Forum Jump:


Users browsing this thread: 11 Guest(s)