[Plugin] Life Command Engine [LIFE:CMD]
#21

Commands with params won't work. Below is example of command (rather - script), which not work:
pawn Код:
#include <a_samp>
#include <LIFE-CMD>

new gVehicleNames[212][] =
{
    "Landstalker", "Bravura", "Buffalo", "Linerunner", "Pereniel", "Sentinel", "Dumper", "Firetruck", "Trashmaster", "Stretch", "Manana",
    "Infernus", "Voodoo", "Pony", "Mule", "Cheetah", "Ambulance", "Leviathan", "Moonbeam", "Esperanto", "Taxi", "Washington", "Bobcat",
    "Mr Whoopee", "BF Injection", "Hunter", "Premier", "Enforcer", "Securicar", "Banshee", "Predator", "Bus", "Rhino", "Barracks",
    "Hotknife", "Trailer", "Previon", "Coach", "Cabbie", "Stallion", "Rumpo", "RC Bandit", "Romero", "Packer", "Monster", "Admiral",
    "Squalo", "Seasparrow", "Pizzaboy", "Tram", "Trailer", "Turismo", "Speeder", "Reefer", "Tropic", "Flatbed", "Yankee", "Caddy",
    "Solair", "Berkley's RC Van", "Skimmer", "PCJ-600", "Faggio", "Harley", "RC Baron", "RC Raider", "Glendale", "Oceanic",
    "Sanchez", "Sparrow", "Patriot", "Quad", "Coastguard", "Dinghy", "Hermes", "Sabre", "Rustler", "ZR3 50", "Walton", "Regina",
    "Comet", "BMX", "Burrito", "Camper", "Marquis", "Baggage", "Dozer", "Maverick", "News Chopper", "Rancher", "FBI Rancher",
    "Virgo", "Greenwood", "Jetmax", "Hotring", "Sandking", "Blista Compact", "Police Maverick", "Boxville", "Benson", "Mesa",
    "RC Goblin", "Hotring Racer", "Hotring Racer", "Bloodring Banger", "Rancher", "Super GT", "Elegant", "Journey", "Bike",
    "Mountain Bike", "Beagle", "Cropdust", "Stunt", "Tanker", "RoadTrain", "Nebula", "Majestic", "Buccaneer", "Shamal", "Hydra",
    "FCR-900", "NRG-500", "HPV1000", "Cement Truck", "Tow Truck", "Fortune", "Cadrona", "FBI Truck", "Willard", "Forklift", "Traktor",
    "Combine", "Feltzer", "Remington", "Slamvan", "Blade", "Freight", "Streak", "Vortex", "Vincent", "Bullet", "Clover", "Sadler",
    "Firetruck", "Hustler", "Intruder", "Primo", "Cargobob", "Tampa", "Sunrise", "Merit", "Utility", "Nevada", "Yosemite", "Windsor",
    "Monster", "Monster", "Uranus", "Jester", "Sultan", "Stratum", "Elegy", "Raindance", "RC Tiger", "Flash", "Tahoma", "Savanna",
    "Bandito", "Freight", "Trailer", "Kart", "Mower", "Duneride", "Sweeper", "Broadway", "Tornado", "AT-400", "DFT-30", "Huntley",
    "Stafford", "BF-400", "Newsvan", "Tug", "Trailer", "Emperor", "Wayfarer", "Euros", "Hotdog", "Club", "Trailer", "Trailer",
    "Andromeda", "Dodo", "RC Cam", "Launch", "Radiowoz", "Radiowoz", "Radiowoz", "Radiowoz", "Picador", "S.W.A.T. Van",
    "Alpha", "Phoenix", "Glendale", "Sadler", "Luggage Trailer", "Luggage Trailer", "Stair Trailer", "Boxville", "Farm Plow", "Utility Trailer"
};

playaName(playerid)
{
    static Name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, Name, sizeof(Name));
    return Name;
}

CreatePlayerVehicle(playerid, modelid)
{
    new vehicle, Float: X, Float: Y, Float: Z, Float: angle;
    if (GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
    {
        vehicle = GetPlayerVehicleID(playerid);
        GetVehiclePos(vehicle, X, Y, Z);
        GetVehicleZAngle(vehicle, angle);
        DestroyVehicle(vehicle);
    }
    else
    {
        GetPlayerPos(playerid, X, Y, Z);
        GetPlayerFacingAngle(playerid, angle);
    }
    vehicle = AddStaticVehicle(modelid, X, Y, Z + 1, angle, -1, -1);
    LinkVehicleToInterior(vehicle, GetPlayerInterior(playerid));
    SetVehicleVirtualWorld(vehicle, GetPlayerVirtualWorld(playerid));
    SetVehicleNumberPlate(vehicle, playaName(playerid));
    PutPlayerInVehicle(playerid, vehicle, 0);
    return 1;
}

str_del_free_space (string[], _char = ' ')
{
    new len = strlen (string);
    if (len)
    {
        new begin = -1, end = len;
        while (string[++begin] == _char) {}
        if (string[begin] == EOS)
        {
             string [0] = 0;
             return 1;
        }
        while (string[--end] == _char) {}
        strmid (string, string, begin, end+1, len+1);
    }
    return 1;
}

GetVehicleModelIdByName(vehiclename[])
{
    for(new i = 0; i < 211; i++)
        if (strfind(gVehicleNames[i], vehiclename, true) != -1) return i + 400;
    return -1;
}

CMD:v(playerid, params[])
{
    str_del_free_space(params);
    if(isnull(params)) return SendClientMessage(playerid, -1, "Write /v CarName");
    CreatePlayerVehicle(playerid, GetVehicleModelIdByName(params));
    return 1;
}
Reply
#22

Quote:

Commands with params won't work.

I confirm.

/vehicle -> Output: "Please use /vehicle [vehicle name]"
/vehicle Infernus -> Output: "Command not found. View /commands".
Reply
#23

Quote:
Originally Posted by ******
Посмотреть сообщение
Why is this "multi-threaded"? That doesn't make code faster! You specifically state that you are new to C++ but decide to use what is widely regarded as one of the hardest things in programming to get right (threads) with no understanding at all of WHY it should be used. xeeZ already touched on this and I agree entirely. This is what you do:
  • Get a command in your "CMD" function.
  • Pass it to an UNSAFE queue (i.e. one that can't be used in multi-threaded code without the risk of crashing).
  • Return 1 - you don't yet know if the command actually exists, but return 1 anyway...
  • Wait for the second thread to get scheduled (an indeterminate amount of time).
  • Do some TRIVIAL string processing that doesn't need to be in a second thread, and probably takes less time to run than the two queue operations required to move the data between the two threads (never mind the overhead involved in OS threads).
  • Pass the data in to ANOTHER unsafe queue, doubling your chances of a crash.
  • Wait for the first thread to get scheduled again.
  • Read and process a SINGLE command, regardless of the size of the waiting queue.
  • Finally actually do the command.
Oh, and by the way, your performance measurements are entirely wrong - you only time the first two points above, i.e. the time your command processor takes to put the command on to the first queue. You don't test how long it takes to actually RUN the commands, which all the other command processors' timings do. In fact, because of the way your system works that's BY DEFINITION slower than all the other methods because yours will still be poping commands off your second stack LONG after the timings are completed for everything else.

So, to sumarise:
  • Very insecure code liable to crashing.
  • New to C++ be decide to do multi-threading.
  • No need to do multi-threading (and actually HURTING your performance by doing so).
  • Total lack of understanding of what threads are good at (and what they are BAD at).
  • Incorrect performance MASSIVELY misrepresenting your code.
To summarise the summary:

"Threads" are not a magic "go faster" switch - they are hard.

I'll come to the more minor points after you fix these.

Edit: Actually, no, let's go:
  • Your timings have a lot of "format" calls in them - have you evaluated how much of the execution time is spent doing those compared to how much is actually spent running the commands? That's seems like an important fact to know.
  • You test 10 commands - that's not a lot by even the smallest modes' standards.
  • You disable warnings in the C code - ALWAYS a bad sign.
  • Why is your main structure called "Player" - what does it have to do with players? Surely "command_s" would be better (more closely following more traditional C++ naming conventions, though that's not required, just good practice).
  • Following on from that - just HORRIBLE naming conventions all over the place.
  • Also "Lenght" instead of "Length".
  • SO MANY OBJECT COPIES! Do you understand what pointers are or how memory in C works at all?
  • "new char[]" followed by "delete" instead of "delete []".
  • Why "list<AMX *>"? There can never be more than 17 (16 filterscripts and a gamemode).
  • Wait, sorry, having looked more closely at your code - your use of queues IS thread safe, because you block on mutexes everywhere! The fact that the queues are safe is a good thing, but your liberal use of locking is not - especially when you lock the ENTIRE second thread for the whole of its execution! Stay in locks for as short-a time as possible!
  • "WaitForSingleObject" is a Windows kernel call (and I suspect you have a similar call in the Linux code), that means it is SLOW - probably more slow than all the rest of your code put together!
  • "i++": use "++i" with iterators.
  • I take back what I just said about your code actually being thread safe because then I re-read "ProcessTick" and saw that despite your liberal use of mutexes everywhere else, there are none there.
  • Why use different callback names to every other command processor that exists?
  • WHY IS THIS THREADED!? I can't overstate this question!
I will, however, congratulate you on ONE thing: you didn't use "using std;" but actually specified which parts you wanted to "use"!
This is the reason why i was reading the whole damn thread , post by post. This is all i wanted to hear. This is nowhere faster then y_cmd or zcmd in real.
Reply
#24

Quote:
Originally Posted by Ballu Miaa
Посмотреть сообщение
This is the reason why i was reading the whole damn thread , post by post. This is all i wanted to hear. This is nowhere faster then y_cmd or zcmd in real.
zcmd can be optimized, i did my cmd processor and is faster than zcmd.
Reply
#25

Quote:
Originally Posted by ******
Посмотреть сообщение
That doesn't mean it is RIGHT...
Why did you say that?
Reply
#26

Quote:
Originally Posted by ******
Посмотреть сообщение
Because I've seen numerous attempts to "optimised" zcmd - usually by removing support for various corner cases or protection against crashers. Or getting rid of the extra callbacks. However, none of these have ever been faster once the bugs were pointed out and code to correct them added back in.
Hum... When i create my cmd processor I had some bugs but now don't have bugs and don't crash.
When i used slice benchmark and gave me 236.99 times/ms i knew that was very good to me.
Reply
#27

Indeed, ****** is right...

There's nothing bad about writing your own version or integrating zcmd into your gamemode so it fully fits your needs (leave out the callbacks, do it all in OnPlayerCommandText, remove unnecessary features, whatever floats your server's boat), but in such case, you cannot directly compare it to the original zcmd.
Reply
#28

Very nice well!
Reply
#29

Quote:
Originally Posted by ******
Посмотреть сообщение
Because I've seen numerous attempts to "optimised" zcmd - usually by removing support for various corner cases or protection against crashers. Or getting rid of the extra callbacks. However, none of these have ever been faster once the bugs were pointed out and code to correct them added back in.
Quote:
Originally Posted by BlueX
Посмотреть сообщение
Hum... When i create my cmd processor I had some bugs but now don't have bugs and don't crash.
When i used slice benchmark and gave me 236.99 times/ms i knew that was very good to me.
Quote:
Originally Posted by AndreT
Посмотреть сообщение
Indeed, ****** is right...

There's nothing bad about writing your own version or integrating zcmd into your gamemode so it fully fits your needs (leave out the callbacks, do it all in OnPlayerCommandText, remove unnecessary features, whatever floats your server's boat), but in such case, you cannot directly compare it to the original zcmd.
Exactly. I cant even think of something faster and efficient then zcmd.

Author is an lucky ass. Instead of decreasing his reputation by 2, i actually increased it +4 by mistake. Gosh fucked up.
Reply
#30

test against DC_CMD
Reply
#31

Dont worry about "speed", speed is how much time take the code to find the command and call the function, but the "heavy" process is the command execution, not the command finding. I think strcmp is enought for most servers, but zcmd offers better syntax and easier command declaration (for me)
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)