[Plugin] MultiThread
#21

well we can't do much about the choice of the sa-mp devs, they've chosen pawn as the scripting lang and you can't do much about it so I think we have to improve it on our own, and multi architecture is a big improvement if we get it to work because nowadays gamemodes ARE NOT 'light'! many code is processed each second , and in most scenarios the code can be processed safely in threads (like updating player textdraw information, instead of looping throu all players and then go on with our gamemode!).

But can anyone give me some examples? and does this really improve the speed ? :P my question still remains: how the heck can you run a callback in a separate thread ? :O
Reply
#22

Quote:
Originally Posted by ******
Посмотреть сообщение
Edit: Actually, I just looked at the code to see what LockThread does and the simple answer is nothing! In fact worse than nothing - pointless loops I can't find the use of wasting time... If the code did what you think it does (which it doesn't) then it would create a mutex, but not actually turn it on, which makes the whole process pointless.
Why do you think? LockThread uses mutex created by the stream.

Код:
		boost::mutex::scoped_lock 
			* lock = new boost::mutex::scoped_lock( (* i).second->mutex )
		;
Reply
#23

Quote:
Originally Posted by gamer_Z
Посмотреть сообщение
well we can't do much about the choice of the sa-mp devs, they've chosen pawn as the scripting lang and you can't do much about it so I think we have to improve it on our own, and multi architecture is a big improvement if we get it to work because nowadays gamemodes ARE NOT 'light'! many code is processed each second , and in most scenarios the code can be processed safely in threads (like updating player textdraw information, instead of looping throu all players and then go on with our gamemode!).

But can anyone give me some examples? and does this really improve the speed ? :P my question still remains: how the heck can you run a callback in a separate thread ? :O
If you use multiple threads, you can execute code in parallel.
Example: You want to sort an array by using mergesort. You can sort the two halfs by two threads and merge it afterwards. In the best case, you will use only half of the time compared to the time it takes when using only one thread.

But do you actually know what it takes to make a save multithreaded program? Have you got any clue of parallel programming?
You can't use multiple threads in PAWN since PAWN has absolutely no support for multithreading.
You may need real locks to lock a variable or you may need volatile variables to prevent race conditions. However, locking a variable can introduce deadlocks and your whole server would freeze until someone shuts it down.
There are many other things you have to know about to make a thread-save program/script.
Noone here is able to make a multithreaded script using this plugin since noone has the necessary utils.
Example: Look at the object streamer. It may look save, but what happens when an object has to be destroyed and in the same moment its being streamed for a player. The object may be created after it has been destroyed and suddenly there's an object which can't be destroyed because the streamer actually doesn't know that it's there.
When this happens 400 times, the whole streamer may fuck up for a player.
Reply
#24

Useless plugin.
But great work!

PS: who deletes my posts? wtf?!!!
Reply
#25

sure knew about the dangers of var locks etc but for example to stream data to a website whle the server is running? would be great to not lag the server with data sending/recieving to/from the website. But okay so this plugin doesn't work or what?
Reply
#26

Quote:
Originally Posted by gamer_Z
Посмотреть сообщение
sure knew about the dangers of var locks etc but for example to stream data to a website whle the server is running? would be great to not lag the server with data sending/recieving to/from the website. But okay so this plugin doesn't work or what?
All work fine!
Reply
#27

Quote:
Originally Posted by Fro1sha
Посмотреть сообщение
All work fine!
okay the only thing i need to make is a 'callback' and put my threat code in there?
also how to specify how many times per second it should run?
Reply
#28

Quote:
Originally Posted by gamer_Z
Посмотреть сообщение
sure knew about the dangers of var locks etc but for example to stream data to a website whle the server is running? would be great to not lag the server with data sending/recieving to/from the website. But okay so this plugin doesn't work or what?
You do realize we have multiple mysql plugins that offer (safe) threading features? I strongly advise you look into them instead.
Reply
#29

Quote:
Originally Posted by Kyosaur
Посмотреть сообщение
You do realize we have multiple mysql plugins that offer (safe) threading features? I strongly advise you look into them instead.
Erm It was just an example, I want to do the textdraw info update in a separate threat (so ONLY GET variables, what will the problem be if it is GET and WRITE at the same time?) and some other stuff that just slows down the gamemode like SetWorldTime every second etc..
Reply
#30

Quote:
Originally Posted by ******
Посмотреть сообщение
The issue is if you are trying to GET and SET at the same time - and I mean EXACTLY the same time. You can end up reading data in a corrupt state because it isn't all correctly written yet.
So is that possible (and safe) to make a thread do get and set (for example GUI cursor update) that the threads have no communications?
Reply
#31

Quote:
Originally Posted by ******
Посмотреть сообщение
If the threads never communicate ever then that should be OK. But don't forget that the PAWN natives aren't thread safe either. If you are using a text draw for your cursor for example, and your main thread is creating TDs too, you could end up creating two at the same time and, due to the way empty slots are found and assigned, you could get two with the same ID, and then I'm not sure what would happen (which is the main problem with threading).
for the td problem it could be sloved with looping throught all variables and check if two td variables have the same ID, if yes destroy them and recreate in a safe way.


okay so the only thing i need to do is to create the player textdraw in ongamemodeinit, (so 500 td's),
then only get player stats and settextdrawstring in the threat should be safe? if you set corrupt data i hope it won't crash so the next cycle can set the good data.

okay . again? just make a callback and put the code in there, and that's a thread? <wow>
sorry I ask it soo many times but I don't want to corrupt my GM.

and if I want a thread to run 50 times a second i need to do sleep(1000/50) ? and do I need to lock/unlock the thread or can I just do it without?
Reply
#32

No, it isn't that simple. If you aren't familiar with how extremely difficult concurrency is in multithreaded programming, I'd suggest deeply researching the topic before you attempt to write anything at all.

As I said earlier, the AMX functions aren't thread-safe—meaning, of course, that they are only designed to be called from a single thread. Unless you want to rewrite the PAWN language, there is simply no way to extend this kind of functionality to scripts without creating serious problems.
Reply
#33

well okay usefull plugin but it just doesn't fit sa-mp, maybe the only things threads should have should only be plugins themselves...
Reply
#34

Quote:
Originally Posted by ******
Посмотреть сообщение
No, it's not that simple - I'm not even sure if the raknet library compiled in SA:MP is thread-safe (it CAN be, but you can compile it without thread safety for speed). This means that even if you do use entirely separate textdraws in separate threads, if raknet tries to send the data for the two textdraws (or indeed tries to send any data for anything at the same time as any data for anything else) it will entirely screw up (of course, the SA:MP server MAY be compiled with that one part multi-threaded - only Kye could answer that).

The bottom line is multi-threaded programming is HARD, not just a little tricky as you seem to be thinking, but VERY VERY HARD. Add to this the fact that, despite me telling the author several times, the lock thread function does nothing and you have serious issues.

It is possible to write PAWN-based critical section locks using, for example:

http://en.wikipedia.org/wiki/Dekker%27s_algorithm

or:

http://en.wikipedia.org/wiki/Peterson%27s_algorithm

However these only work for two threads, not many, and as most PAWN natives are not thread safe you may need to put critical sections around almost everything, making threads actually WORSE than no threads.
So even it could be possible to do multithread in PAWN, but we'll need to lock the threads to prevent using the functions at the same time. However this will cause waiting issues, which do no (or very few) performance increase.
Reply
#35

Times like this that I miss Java.

Synchronized Keyword
Reply
#36

I think switch statements dont work in your threat plugin?
proof:
pawn Код:
#if defined USE_MULTI_THREAD
enum gTpos
{
    Float:X,
    Float:Y,
    Float:Z,
    Float:Angle1,
    Float:Angle2,
    Points,
    Timer
}

new GlobalPos[MAX_PLAYERS][gTpos];// USED ONLY IN THE THREAD except Timer and Points!

forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
    for(new playerid; playerid < MAX_PLAYERS; playerid++)
    {
        if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
        {
            new PlayerVehicleID = GetPlayerVehicleID(playerid);
            new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
            new Float:floatdata[11];

            //switch(PlayerVehicleModelID)
            //{
            //    case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
            //    {
                    new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
                    GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
                    floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);

                    GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);

                    GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
                    floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
                    GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
                    if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
                    if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
                    if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
                        floatdata[0] = asin(floatdata[7]/floatdata[1]);
                        floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
                    }
                    if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
                        floatdata[0] = asin(floatdata[7]/floatdata[1]);
                        floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
                    }
                    if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
                        floatdata[0] = acos(floatdata[8]/floatdata[1]);
                        floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
                    }
                    if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
                        floatdata[0] = asin(floatdata[7]/floatdata[1]);
                        floatdata[9] = floatadd(floatdata[0], 180);
                    }
                    if(floatdata[9] == 0.0)
                    {
                        GlobalPos[playerid][Angle2] =  floatdata[3];
                    } else {
                        GlobalPos[playerid][Angle2] =  floatdata[9];
                    }

                    new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
                    if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
                    {
                        if(GlobalPos[playerid][Timer] != -1)KillTimer(GlobalPos[playerid][Timer]);
                        GlobalPos[playerid][Timer] = -1;
                        GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
                        GlobalPos[playerid][Timer] = SetTimerEx("DriftCancel", 2000, 0, "d", playerid);
                    }
                //}
            //}
           
            GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
        }
    }
    SleepThread(100);
}

forward DriftCancel(playerid);
public DriftCancel(playerid)
{
    //do something with the points
    GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 1500, 1, GlobalPos[playerid][Points]);
    //
    GlobalPos[playerid][Timer] = (-1);
    GlobalPos[playerid][Points] = 0;
    return 1;
}
#endif
I have commented it out to test if the script itself works,...

I try to look if something is wrong with my code and update my post.

BTW works nice! NO LAGS AT ALL!

and this randomly crashesh the server when you drift:
pawn Код:
#if defined USE_MULTI_THREAD
enum gTpos
{
    Float:X,
    Float:Y,
    Float:Z,
    Float:Angle1,
    Float:Angle2,
    Points,
    Timer
}

new Text:PlayerTextDraw[MAX_PLAYERS];

forward DU_OnGameModeInit();
public DU_OnGameModeInit()
{
    for(new x=0;x<MAX_PLAYERS;x++)
    {
        PlayerTextDraw[x] = Text:TextDrawCreate(7.0, 300.0, " ");
        TextDrawColor(PlayerTextDraw[x], 0x3355FFFF);
        TextDrawFont(PlayerTextDraw[x], 1);
        TextDrawSetShadow(PlayerTextDraw[x], 0);
        TextDrawSetOutline(PlayerTextDraw[x], 1);
        TextDrawAlignment(PlayerTextDraw[x], 0);
        TextDrawLetterSize(PlayerTextDraw[x], 0.4, 0.8);
    }
    return 1;
}

new GlobalPos[MAX_PLAYERS][gTpos];// USED ONLY IN THE THREAD , no exceptions!

forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
    for(new playerid; playerid < MAX_PLAYERS; playerid++)
    {
        if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
        {
            new PlayerVehicleID = GetPlayerVehicleID(playerid);
            //new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
            new Float:floatdata[11];

            //switch(PlayerVehicleModelID)
            //{
            //    case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
            //    {
            new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
            GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
            floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);

            GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);

            GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
            floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
            GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
            if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
            if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
                floatdata[0] = acos(floatdata[8]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
            }
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatadd(floatdata[0], 180);
            }
            if(floatdata[9] == 0.0)
            {
                GlobalPos[playerid][Angle2] =  floatdata[3];
            } else {
                GlobalPos[playerid][Angle2] =  floatdata[9];
            }

            new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
            if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
            {
                if(GlobalPos[playerid][Timer] != -1)
                {
                    new s[256];
                    format(s, 256, "~n~~n~~n~~w~_________________Drift!~n~___________________~p~Points: %d", GlobalPos[playerid][Points]);
                    TextDrawSetString(PlayerTextDraw[playerid], s);
                }
                else
                {
                    TextDrawShowForPlayer(playerid,PlayerTextDraw[playerid]);
                    GameTextForPlayer(playerid, "Drift started!", 500, 1);
                }

                GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
                GlobalPos[playerid][Timer] = 20;
            }
            else
            {
                if(GlobalPos[playerid][Timer] != -1)
                {
                    GlobalPos[playerid][Timer]--;
                    if(GlobalPos[playerid][Timer] == -1)
                    {
                        TextDrawHideForPlayer(playerid,PlayerTextDraw[playerid]);
                        GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);

                        GlobalPos[playerid][Points] = 0;
                    }
                }
            }
                //}
            //}

            GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
        }
    }
    SleepThread(100);
}
#endif
But when drifting the counter is incredible fast responsing!
I would like to have something crash free.
I wanted to make a drift counter In a plugin but I do not know how :P

PS: can somebody help me make this work without crash and WITH using TD? :P

also this seems to be non-crashing:
pawn Код:
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
    for(new playerid; playerid < MAX_PLAYERS; playerid++)
    {
        if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
        {
            new PlayerVehicleID = GetPlayerVehicleID(playerid);
            //new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
            new Float:floatdata[11];

            //switch(PlayerVehicleModelID)
            //{
            //    case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
            //    {
            new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
            GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
            floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);

            GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);

            GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
            floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
            GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
            if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
            if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
                floatdata[0] = acos(floatdata[8]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
            }
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatadd(floatdata[0], 180);
            }
            if(floatdata[9] == 0.0)
            {
                GlobalPos[playerid][Angle2] =  floatdata[3];
            } else {
                GlobalPos[playerid][Angle2] =  floatdata[9];
            }

            new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
            if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
            {
                if(GlobalPos[playerid][Timer] != -1)KillTimer(GlobalPos[playerid][Timer]);
                else CallLocalFunction("OnDriftStart","i",playerid);
                GlobalPos[playerid][Timer] = -1;

                GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
                GlobalPos[playerid][Timer] = SetTimerEx("OnDriftEnd", 2000, 0, "d", playerid);
            }
                //}
            //}
           
            GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
        }
    }
    SleepThread(100);
}

forward OnDriftStart(playerid);
public OnDriftStart(playerid)
{
    GameTextForPlayer(playerid, "Drift started!", 750, 1);
    return 1;
}

forward OnDriftEnd(playerid);
public OnDriftEnd(playerid)
{
    //do something with the points
    GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
    //
    GlobalPos[playerid][Timer] = (-1);
    GlobalPos[playerid][Points] = 0;
    return 1;
}
But the game text's aren't really nice bleh.


EDIT:
this seems to be crash proof, fast and lag free:
pawn Код:
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
    for(new playerid; playerid < MAX_PLAYERS; playerid++)
    {
        if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
        {
            new PlayerVehicleID = GetPlayerVehicleID(playerid);
            //new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
            new Float:floatdata[11];

            //switch(PlayerVehicleModelID)
            //{
            //    case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
            //    {
            new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
            GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
            floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);

            GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);

            GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
            floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
            GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
            if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
            if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
            }
            if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
                floatdata[0] = acos(floatdata[8]/floatdata[1]);
                floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
            }
            if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
                floatdata[0] = asin(floatdata[7]/floatdata[1]);
                floatdata[9] = floatadd(floatdata[0], 180);
            }
            if(floatdata[9] == 0.0)
            {
                GlobalPos[playerid][Angle2] =  floatdata[3];
            } else {
                GlobalPos[playerid][Angle2] =  floatdata[9];
            }

            new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
            if(90.0 > angle > 17.5 && floatdata[10] > 23.5)
            {
                GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 83);
                if(GlobalPos[playerid][Timer] != -1)
                {
                    GlobalPos[playerid][Combo] += 1;
                    new s[256];
                    format(s, 256, "~n~~n~~n~~w~_________________Drift!~n~___________________~r~Points:~w~_%d~n~___________________~r~Combo:~w~_x%d!",GlobalPos[playerid][Points],floatround(GlobalPos[playerid][Combo]/30,floatround_floor)+1);
                    TextDrawSetString(PlayerTextDraw[playerid], s);
                }
                else
                {
                    TextDrawShowForPlayer(playerid,PlayerTextDraw[playerid]);
                    //GameTextForPlayer(playerid, "Drift started!", 500, 1);
                }
                GlobalPos[playerid][Timer] = 20;
            }
            else
            {
                if(GlobalPos[playerid][Timer] != -1)
                {
                    GlobalPos[playerid][Timer]--;
                    if(GlobalPos[playerid][Timer] == -1)
                    {
                        TextDrawHideForPlayer(playerid,PlayerTextDraw[playerid]);
                        //GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
                        GlobalPos[playerid][Combo] = 0;
                        GlobalPos[playerid][Points] = 0;
                    }
                }
            }
                //}
            //}

            GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
        }
    }
    SleepThread(100);
}
have fun drifting my dear (thread) racers!

EDIT2:
ah nevermind, it crashes -.-...
Cmon people help us out ! don't let such great plugin let fall apart! - performance is what we want today, people, yes? SO get your ass up and think with me how to make multi threading safer!
Reply
#37

Код:
SleepThread(100);
Set to 200 or 300 or 400 or 500 ms.
Reply
#38

Quote:
Originally Posted by Fro1sha
Посмотреть сообщение
Код:
SleepThread(100);
Set to 200 or 300 or 400 or 500 ms.
Will try and let ya know, or test it yourself ^^ (I gave the code )

EDIT:
making the time bigger reduces the crashes (which is obvious) but doesn't remove them ;x

Hmm Frosha , I'm Polish, I don't speak or read Russian but maybe if I get you vodka we won't have any communication issues, can sit down and talk a bit ^^
Reply
#39

Quote:
Originally Posted by gamer_Z
Посмотреть сообщение
Hmm Frosha , I'm Polish, I don't speak or read Russian but maybe if I get you vodka we won't have any communication issues, can sit down and talk a bit ^^
xDDD ok. Come in Siberia
Reply
#40

Fro1sha, when I use DestroyThread, it shuts down my server - is there any way to stop the thread from continuing without shutting it down?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)