Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums



(Advanced Search)

Forum Statistics
» Members: 6,505
» Latest member: lucasmillerfeb2022
» Forum threads: 2,241
» Forum posts: 12,047

Full Statistics

Online Users
There are currently 517 online users.
» 0 Member(s) | 514 Guest(s)
Bing, Google, Yandex

Latest Threads
What is mebendazole used ...
Forum: Questions and Suggestions
Last Post: lucasmillerfeb2022
6 hours ago
» Replies: 0
» Views: 12
Rosalife Gamemode [openMP...
Forum: Gamemodes
Last Post: vactidylee
Yesterday, 04:17 AM
» Replies: 5
» Views: 4,549
White Screen
Forum: Support
Last Post: Phat202146_real
2024-11-21, 02:50 PM
» Replies: 0
» Views: 25
Offensive-Core: TDM
Forum: Gamemodes
Last Post: threezhang.cn
2024-11-21, 09:54 AM
» Replies: 5
» Views: 940
Outstanding Customer Serv...
Forum: Chat
Last Post: va6220902
2024-11-21, 07:52 AM
» Replies: 0
» Views: 130
New place
Forum: Life
Last Post: sjaardamilly
2024-11-21, 06:58 AM
» Replies: 0
» Views: 24
How Zhewitra Oral Jelly W...
Forum: General Discussions
Last Post: erctilenovus
2024-11-20, 08:39 AM
» Replies: 0
» Views: 31
Cenforce 100 Mg Medicine ...
Forum: Chat
Last Post: ezraallen45ea
2024-11-19, 10:00 AM
» Replies: 0
» Views: 38
I get error 021 using y_h...
Forum: Pawn Scripting
Last Post: daniscript18
2024-11-18, 11:34 PM
» Replies: 0
» Views: 46
What is the use of Wakler...
Forum: Other
Last Post: allencooper
2024-11-18, 10:37 AM
» Replies: 0
» Views: 30

 
Lightbulb ?Creen que Open MP tendr? voice dentro del juego?
Posted by: Soichiro - 2019-04-17, 01:46 PM - Forum: Discusi?n GTA SA Multijugador - Replies (29)

Sera que es posible que implemente chat de voz dentro de OMP?


  The internals of switch and chained else ifs and which one should you use
Posted by: kristo - 2019-04-17, 12:25 PM - Forum: Tutorials - No Replies

The internals of switch and chained else ifs and which one should you use



This tutorial takes a look into how if and switch statements work on the assembly level and helps determine, where to use a switch and where to prefer chained else ifs. I decided to write this tutorial, because one of the topics I am about to address is a semi-common issue and currently there is no good place to refer to when it comes to it. In addition to that, the research I did for this tutorial helped me understand the AMX structure quite a bit more than I used to before.



The internals



I used the -a flag to generate the assembly of two simple snippets of code that perform the same task, one using switch and the other using chained else ifs. I also took the time to rewrite them in a more human-readable form (using variable names instead of raw addresses, named labels instead of numbered ones prefixed with l., etc.) and to document them. It is worth noting that while the rewritten assembly is valid, it does not currently compile due to a compiler bug related to forward jumps.



Chained else ifs



PHP Code:
new val;



if (
val == 1) {

? ?
// do something here

} else if (<= val <= 4) {

? ?
// do something here

} else {

? ?
// do something here





For the sake of simplicity I used the form 2 <= val <= 4 instead of val >= 2 && val <= 4 for the range check. If written the other way, the code would use 7 jump instructions instead of 4 and keeping track of the instructions would be more difficult. It would also be a tiny bit slower since it would have to load the value of val to the primary register one more time.



When using chained else ifs, the assembly contains the AMX instructions for each individual check. If the check fails, it jumps to the next check, otherwise it jumps to the end of the chain. Here is the assembly equivalent to this code:



PHP Code:
new val;





// if (val == 1)

#emit LOAD.S.pri ? ?val ? ? ? ? // load the value of val to the primary register

#emit EQ.C.pri ? ? ?1 ? ? ? ? ? // compare the value in the primary register to constant 1: they must be equal; store the result in the primary register

#emit JZER ? ? ? ? ?range ? ? ? // if the result of the comparison is false, jump to "range" to perform the next check

// do something here

#emit JUMP ? ? ? ? ?done ? ? ? ?// everything is done, jump to "done"





// else if (2 <= val <= 4)

range:

#emit CONST.pri ? ? 2 ? ? ? ? ? // store the constant value 2 in the primary register

#emit LOAD.S.alt ? ?val ? ? ? ? // load the value of val to the alternate register

#emit SLEQ ? ? ? ? ? ? ? ? ? ? ?// compare the values in the registers to eachother: 2 (primary) must be less than or equal to val (alternate); store the result in the primary register

#emit PUSH.pri ? ? ? ? ? ? ? ? ?// load the value to the primary register (the result of the comparison) in the stack

#emit CONST.pri ? ? 4 ? ? ? ? ? // store the constant value 4 in the primary register

#emit SGEQ ? ? ? ? ? ? ? ? ? ? ?// compare the values in the registers to eachother: 4 (primary) must be greater than or equal to val (alternate); store the result in the primary register

#emit POP.alt ? ? ? ? ? ? ? ? ? // load the value of the first comparison from the stack to the alternate register

#emit AND ? ? ? ? ? ? ? ? ? ? ? // check if both of the comparisons were true by checking if both registers contain a non-zero value

#emit JZER ? ? ? ? ?otherwise ? // if the result of the comparison is false, jump to "otherwise"

// do something here

#emit JUMP ? ? ? ? ?done ? ? ? ?// everything is done, jump to "done"



// else

otherwise:

// do something here

// no jump needed since "done" is just after this code





done



If the value of val is 1, the code uses four instructions:



PHP Code:
LOAD.S.prival

EQ
.C.pri? ? 1

JZER
? ? ? ? range the jump does not happenbut the instruction is still used

JUMP
? ? ? ? done 



If the value of val is 2, 3 or 4, the code uses 13 instructions:



PHP Code:
LOAD.S.prival

EQ
.C.pri? ? 1

JZER
? ? ? ? range

CONST.pri? ?2

LOAD
.S.altval

SLEQ

PUSH
.pri

CONST.pri? ?4

SGEQ

POP
.alt

AND

JZER? ? ? ? otherwise the jump does not happenbut the instruction is still used

JUMP
? ? ? ? done 



If the value is not matched by any of the previous checks, the code uses 12 instructions:



PHP Code:
LOAD.S.prival

EQ
.C.pri? ? 1

JZER
? ? ? ? range

CONST.pri? ?2

LOAD
.S.altval

SLEQ

PUSH
.pri

CONST.pri? ?4

SGEQ

POP
.alt

AND

JZER? ? ? ? otherwise 



The longer your chain is and the more failed checks there are, the more instructions the code uses. Each failed single value check adds 3 instructions and each failed range check adds 9 instructions.



switch



PHP Code:
new val;



switch (
val) {

? ?case 
1: {

? ? ? ?
// do something here

? ?}



? ?case 
.. 4: {

? ? ? ?
// do something here

? ?}



? ?default: {

? ? ? ?
// do something here

? ?}





When using switch, the compiler generates a case table that contains the value and jump address for every single case, including the default case. Here is the assembly equivalent to this code:



PHP Code:
new val;





#emit LOAD.S.pri ? ?val ? ? ? ? // load the value of val to the primary register

#emit SWITCH ? ? ? ?casetable ? // jump to the case table



// case 1:

single:

// do something here

#emit JUMP ? ? ? ? ?done ? ? ? ?// everything is done, jump to "done"





range:

// do something here

#emit JUMP ? ? ? ? ?done ? ? ? ?// everything is done, jump to "done"





otherwise:

// do something here

#emit JUMP ? ? ? ? ?done ? ? ? ?// everything is done, jump to "done"





casetable:

#emit CASETBL

// default:

#emit CASE ? ? ? ? ?4 otherwise // the amount of case table items; the jump address of "default"

// case 1:

#emit CASE ? ? ? ? ?1 single ? ?// the value and jump address of the case

// case 2 .. 4:

#emit CASE ? ? ? ? ?2 range

#emit CASE ? ? ? ? ?3 range

#emit CASE ? ? ? ? ?4 range





done



Whatever the value of val is 1, the code always uses just three instructions:



PHP Code:
LOAD.S.prival

SWITCH? ? ? casetable

JUMP
? ? ? ? done 



The SWITCH instruction jumps to the case table, performs a linear search on the cases and jumps to the correct one. If the search does not find a matching case, it jumps to the default case instead. It is similar to the behaviour of chained else ifs, but since it is done in native code instead of using AMX instructions, the performance is a lot better.



When NOT to use switch?



Large ranges



As seen before, case tables can only use single values as cases, which means that if you use a range of 10000 elements in your switch, the compiler will have to write 10000 entries to the case table and the runtime will have to search through 10000 entries. Using the following benchmarking script I determined that the runtime performance of a case table becomes worse than the one of a single a <= x <= b check at around 30 entries.



PHP Code:
#define MAX 30

#define ITERATIONS 1000000



new tick GetTickCount();



for (new 
iITERATIONSi) {

? ?switch ((
MAX)  1) {

? ? ? ?case 
.. MAX: {}

? ?}

}



printf("switch: %i"GetTickCount() - tick);





tick GetTickCount();



for (new 
iITERATIONSi) {

? ?if (
<= (MAX)  <= MAX) {}

}



printf("if: %i"GetTickCount() - tick); 



However, runtime performance is not the biggest issue. As seen from this forum topic, the amount of time it takes for the compiler to generate large case tables can be so long that it seems for the user that the compiler has ran into an infinite loop. Even ranges small enough to only have a small impact on the compilation time (for example, 1000 elements) can eventually make the compilation process painful if the delays stack up.



Floating point values



When using switch with floating point values, the case table must also contain every single value within the range. The step between two cases grows as the values grow, but it starts at the smallest possible floating point value in the IEEE754 specification, which is 1.4E-45. This means that each entry differs from the previous and next one by just 0.0000000000000000000000000000000000000000000014.



Some examples of ranges with the respective amounts of case table elements:



Code:
|? ? ? ? ? ? ? ? ? ? ? ?Range? ? ? ? ? ? ? ? ? ? ? ?| Amount of entries |

|---------------------------------------------------|-------------------|

| 0.0 .. 0.0000000000000000000000000000000000000001 |? ? ? ?71363? ? ? ?|

|? ? ? ? ? ? ? ? ? ? 1.0 .. 1.01? ? ? ? ? ? ? ? ? ? |? ? ? ?83887? ? ? ?|

|? ? ? ? ? ? ? ? ? ?10.0 .. 10.1? ? ? ? ? ? ? ? ? ? |? ? ? ?104859? ? ? |

|? ? ? ? ? ? ? ? ? 100.0 .. 101.0? ? ? ? ? ? ? ? ? ?|? ? ? ?131073? ? ? |

|? ? ? ? ? ? ? ? ?1000.0 .. 1010.0? ? ? ? ? ? ? ? ? |? ? ? ?163841? ? ? |

|? ? ? ? ? ? ? ? 10000.0 .. 10100.0? ? ? ? ? ? ? ? ?|? ? ? ?102401? ? ? |

|? ? ? ? ? ? ? ?100000.0 .. 101000.0? ? ? ? ? ? ? ? |? ? ? ?128001? ? ? |



This test should be enough to show that using switch with floating point values relevant in the context of SA-MP (coordinates, health, etc.) is completely unreasonable.



When to use switch?



I would say that everywhere where there are chains of comparisons against constant values. I have seen people saying that switch is faster no matter what and using a switch with two cases is much faster than an if-else. However, their runtime performance is about the same and where an if and an else make more sense, they should be used instead.



Tips and tricks



Using switch with floatcmp to compare floating point values



Comparison operators for variables with the Float tag are overloaded to use the floatcmp native instead of comparing them with AMX instructions. When comparing floating point values to eachother and having different outcomes depending of if one of the values is larger than the other or they are equal, you can save a floatcmp call by comparing them using switch instead. floatcmp returns 0 if the values are equal, 1 if the first value is larger and -1 if the second value is larger, so the following snippets of code are equivalent, but the second one performs better:



PHP Code:
if (b) { // floatcmp called implicitly

? ?// a is larger than b

} else if (b) { // floatcmp called implicitly

? ?// a is smaller than b

} else {

? ?
// a and b are equal





PHP Code:
switch (floatcmp(ab)) {

? ?case 
1: {

? ? ? ?
// a is larger than b

? ?}



? ?case -
1: {

? ? ? ?
// a is smaller than b

? ?}



? ?case 
0: {

? ? ? ?
// a and b are equal

? ?}





Using switch to compare strings



Comparing strings with strcmp has been notorious being both slow and tedious for a long time. Although most of that bad reputation came when ZCMD became the goto command processor and strcmp is still very useful elsewhere, there is a grain of truth in every joke. When comparing a string to a long chain of other strings, comparing their hashes would be more efficient and also convenient due to the ability to use switch, because the hashes are in the form of integers. The PAWN language does not support such thing natively, but y_stringhash from YSI does just the job. According to Y_Less? tests, comparing strings using hashes becomes more efficient than using strcmp at around 10 comparisons. More information about y_stringhash and its usage can be found from this topic.



PHP Code:
if (!strcmp(number"one")) {



} else if (!
strcmp(number"two") || !strcmp(number"three")) {



} else {







PHP Code:
switch (YHash(number)) {

? ?case 
_H<one>: {



? ?}



? ?case 
_H<two>, _H<three>: {



? ?}



? ?default: {



? ?}





Credits


  • Yashas for the excellent AMX Assembly documentation.

  • Y_Less for reviewing the tutorial prior to me publishing it.

  • Users of the SA-MP Discord for productive conversations on this topic.


  [MAP] Desert Airport
Posted by: iChiwi_. - 2019-04-17, 11:28 AM - Forum: Filterscripts - No Replies

Abandoned Airport, which?had been destroyed due to the wars that happened recently between the?countries.



Every country trying to capture this place to have the most powerful vehicles.



Download:-

https://pastebin.com/W0VAbtc9?( will retexture it soon, so check the topic regularly )





Credits:-

iChiwi_.


  [MAP] Area 51
Posted by: iChiwi_. - 2019-04-17, 11:22 AM - Forum: Filterscripts - No Replies

A modern Military base which is good for Call of Duty servers & TDM servers.



Download:-

https://pastebin.com/472P3wvB?( I might retexture it soon, so check the topic regularly?)



Credits:-

iChiwi_.

ZigGamerx


  Discord SACNR Monitor Bot
Posted by: Bork - 2019-04-17, 10:22 AM - Forum: Tech - Replies (14)

I wrote a discord bot that will query information from the SACNR Monitor based on a IP and port you provide. It currently does not support URL's with an A record for an IP but I will eventually bring that out.



The invite link can be found here:?https://discordapp.com/api/oauth2/authorize?client_id=565207337883795487&permissions=8&scope=bot

To use the bot, all you need to type is:



Code:
!sacnr ip port(default 7777)



You'll get information like this thrown out:

[Image: EQGraNx.png]



For those who are wondering where it's being hosted and what it was written in, dakyskye?is hosting the bot and it was written in C#.

Have fun!


  [Include] pawn-array-view: non-owning spans for multi-dimensional pawn arrays
Posted by: Yashas - 2019-04-17, 05:00 AM - Forum: Plugins - No Replies

pawn-array-view

pawn-array-view is an efficient C library that abstracts the complex memory layout of multi-dimensional pawn arrays and provides an intuitive C/ array-like interface for dealing with them. The name suggests that the library only allows read-only access to the arrays but that's not true; you can access and modify the arrays. Any decent C compiler will be able to optimize off all access and modifications to the arrays into simple pointer arithmetic.

Defects (Help Wanted)
LICM optimizations aren't pushing loop invariant subexpressions out of the loop because of aliased pointers. I haven't figured out how to correctly place restrict qualifiers which aren't ignored.

Code:
int main() {
    pawn::array_view<int, 3> array((cell*)0x10000);
    for(int i = 0; i < 100; i) {
        for(int j = 0; j < 100; j) {
            for(int k = 0; k < 128; k) {
                array[i][j][k] = 10;
            }
        }
    }
    return 0;
}

The compiler does not move the array[i][j] calculations outside the loop. There is a valid reason to not move them since modifying an element could modify something which would require recalculating the indexes. This is useful only when indirection tables are being modified. The common case is data being modified but not the indirection table. In this situation, moving the calculations out of the loop improves performance.

There are more consequences. The compiler can also vectorize the loop if it manages to pull the subexpression out of the loop. The failure to move the subexpression outside the loop prevents a ton of optimizations.

Note that the optimizations happen when the array is only being read. The problem is for modifications only.

Plans
If the size of the arrays are known at compile-time, a better interface can be provided. I have plans on providing full-fledged container like support for arrays where the dimensions are available at compile time.

There is a project going on in the develop branch which has working but inefficient code for dealing with known dimensions at run-time.

I plan on renaming array_view to span. This include was initially providing a view but then the ability to mutate was added but the name wasn't changed. It's a very misleading name now.

Links


  old trailer
Posted by: Atom - 2019-04-17, 03:21 AM - Forum: Videos and Screenshots - No Replies

Hi all.

This is the trailer I made for one of my old projects, I had posted it in the sa-mp forum but I was erased and banned because of the youtube rule.

And I wanted to put it here because in the past it did not last long until they deleted the post xD



[Video: https://www.youtube.com/watch?v=VKkTnhBWTf4]



[Video: https://youtu.be/eyxwyUoZPOA]



The server was about a world where there was a world crisis where only the most money was kept, the media were extorted to show a false reality where everything was beautiful.

That's the message I wanted to convey in the second anchored video.


  pawn-plus-mysql: PawnPlus extensions and helpers for the MySQL plugin
Posted by: Graber - 2019-04-17, 01:38 AM - Forum: Libraries - Replies (8)

pawn-plus-mysql



[Image: sampctl-pawn--async--mysql-2f2f2f.svg?st...-the-badge]



PawnPlus extensions and helpers for the MySQL plugin



Installation



Simply install to your project:



Code:
sampctl package install AGraber/pawn-plus-mysql



Include in your code and begin using the library:



Code:
#include <pp-mysql>



It is recommended that you set a PawnPlus version explicitely on your pawn.json (preferibly the latest) to avoid always downloading the latest one.



If you don?t use sampctl, just download the pp-mysql.inc include and drop it to your includes/ folder, and then download the PawnPlus plugin and include from here.



While you?re on it and if you don?t use PawnPlus yet, you should check it out!



Usage



All existing mysql_[t/p]query now have a variant that accepts PawnPlus strings, ending with _s (for example, mysql_tquery_s).



In addition, a new member arrives into the family of these natives: mysql_aquery[_s], which returns a task that will be set as completed when the query completes successfully, or fault when there?s an error during its execution.



Note that mysql_aquery[_s] will piggyback on mysql_tquery by default. You can override this and use mysql_tquery by setting the parallel parameter at the end to true, or explicitly change this default value by defining MYSQL_ASYNC_DEFAULT_PARALLEL to you desired value.



Examples



Using PawnPlus strings on natives



PHP Code:
public OnPlayerTookAllCandies(playerid)

{

? ?
mysql_tquery_s(DatabaseHandle, @("UPDATE player SET took_candies = UNIX_TIMESTAMP() WHERE id = ") % GetPlayerDBID(playerid));





Task-based asynchronous queries:



PHP Code:
LoadPlayerData(playerid)

{

? ?
await mysql_aquery_s(DatabaseHandle, @("SELECT * FROM player WHERE id = ") % GetPlayerDBID(playerid), .parallel false);

? ?
// Cache functions will be available after this

? ?cache_get_value_name_float(0"health"PlayerHealth[playerid]);

? ?
// ...



  SAMPLauncherNET - A launcher for San Andreas Multiplayer
Posted by: Rafael_Rosse - 2019-04-16, 11:45 PM - Forum: Releases - Replies (12)

Author

[Image: -XQtOWURRuU.jpg]

SAMPLauncherNET

Download

Download SAMPLauncherNET at https://github.com/BigETI/SAMPLauncherNET/releases

Project and source code

The project and source code are located at GitHub: https://github.com/BigETI/SAMPLauncherNET

Features



Backwards compatibility

Most features that are present in the native SA:MP launcher are present in this application.



Modernized look

With the use of the Material Design layout the launcher looks modern.



Multi-language support

If you prefer a different language than the english language, you can easily change the language of the launcher.



ASI plugin loader and manager

Load or manage any GTA San Andreas compatible ASI plugin within this launcher.

Supported and listed ASI plugins by default:

SA:MP Discord Rich Presence plugin



Multi-threaded query mechanism

Fast server listing, where hundreds of SA:MP servers can be queried at the same time.



Show extended server information

List any relevant information of a server for example modes or server location with a couple of clicks.



Improved server filter

Search for your beloved server fast and easily



Search engines integration

Search anything related to a SA:MP server easily on popular search engines.



Debug mode and singleplayer

You can launch SA:MP debug mode or Grand Theft Auto San Andreas with a click on a button.



Media

The media tab allows to manage screenshots, look up the last chatlog and saved positions.



Sessions data

A very important feature for users who want to record session based data.

This can be enabled at the launcher options.



Version changer

Change your SA:MP version to your needs by applying a patch or installing manually.



SA:MP settings

Change your SA:MP settings through an user interface.



Server list APIs

Manage your server list endpoints, and access lists that were inaccessible through a launcher before.



Developer tools

Make your server development workflow easier by configuring, starting and joining your test server using the sampctl integration.



Screenshots

[Image: LFAbqcGrpq4.jpg]

[Image: 1ZOjfnW5ZKU.jpg]

[Image: OJnI7pSF_YM.jpg]

[Image: AiIHkN2Mtfs.jpg]

[Image: G5xwWzDFvDk.jpg]

[Image: IJYwzGDfA6A.jpg]

[Image: HW2bEprOf84.jpg]

[Image: Eey59-lqN2Q.jpg]

[Image: qO56Y988M5s.jpg]


  Update System [MySQL]
Posted by: solstice - 2019-04-16, 11:34 PM - Forum: Filterscripts - No Replies

Hey there, I decided to make my second release here and this time a filterscript (again, this is reuploaded from the SA:MP forums).

This is a filterscript I made for server owners / developers to simply add updates in-game, without having to make edits on the script multiple times.

To use it, you must clone the repository:
Commands:
-?/addupdate
-?/removeupdate
-?/updates

Credits:
Y_Less - sscanf
BlueG / maddinat0r - MySQL
Emmet_ -?easyDialog
Zeex - zcmd

Here's a list of screenshots if you want to see how it looks:

https://imgur.com/a/fdIbGIs