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

Username
  

Password
  





Search Forums



(Advanced Search)

Forum Statistics
» Members: 6,511
» Latest member: snaptrap
» Forum threads: 2,233
» Forum posts: 12,034

Full Statistics

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

Latest Threads
I humor myself
Forum: Programming
Last Post: nami16504
9 hours ago
» Replies: 5
» Views: 8,042
Command does not work in-...
Forum: Pawn Scripting
Last Post: PANZEHIR_
2024-11-23, 06:36 PM
» Replies: 0
» Views: 42
White Screen
Forum: Support
Last Post: Phat202146_real
2024-11-21, 02:50 PM
» Replies: 0
» Views: 41
I get error 021 using y_h...
Forum: Pawn Scripting
Last Post: daniscript18
2024-11-18, 11:34 PM
» Replies: 0
» Views: 61
Il reste des français sur...
Forum: French/Fran?ais
Last Post: tysanio
2024-11-18, 05:39 AM
» Replies: 2
» Views: 469
Object creation issues
Forum: Programming
Last Post: K1271
2024-11-15, 11:51 PM
» Replies: 0
» Views: 56
Is the SAMP Hosting the s...
Forum: General Discussions
Last Post: OperaGX
2024-11-14, 09:33 PM
» Replies: 0
» Views: 75
Run time error 19: "File ...
Forum: Pawn Scripting
Last Post: Rexey
2024-11-14, 03:50 AM
» Replies: 0
» Views: 65
How to Compile Your Gamem...
Forum: Tutorials
Last Post: thelante
2024-11-13, 08:50 AM
» Replies: 3
» Views: 475
Modeller wanted
Forum: Development Updates
Last Post: acc.gangbeni
2024-11-11, 05:10 PM
» Replies: 9
» Views: 16,506

 
  open.mp Server RC1
Posted by: Y_Less - 2023-01-05, 10:37 PM - Forum: Development Updates - Replies (36)

Happy New Year @everyone

It's here!

It's finally here!

After four years, two rewrites, arguments and drama, and countless other hurdles; it is finally here!

Release Candidate 1 (RC1) of the open.mp server.

This, hopefully, represents the final version of the code for our 1.0 release, and if everything goes smoothly with this version we will be able to finally openthe so-called open.mp in just a few days from now.

Before I get in to the meat of the release I want to first sincerely thank every member of the open.mp team for helping the mod get this far. It has not been easy, mostly because of how invested everyone truly was - we all wanted what was best for the mod, for the community, for SA:MP, for our servers, and for our players; we wouldn't have embarked on this journey if that wasn't the case. Unfortunately strong differing opinions on what is bestsometimes causes friction. But we're here now. So to all, a huge thank you:

  • Amir
  • Cheaterman
  • Freaksken
  • Graber
  • Hual
  • Josh
  • JustMichael
  • kseny
  • Nexius
  • pkfln
  • Potassium
  • Southclaws
  • TommyB
  • Y_Less
  • Zeex
  • And probably more...

Anyway, now the bit you actually care about...

Now we're out of beta, we're (if all goes well this week) releasing on time. So along with the server itself, which you've seen a dozen times before, we have some new goodies for you:

Pawn

The download has the official includes, no more patching the old SA:MP includes with omp.inc, now we're doing it properly! It also has a new compiler. Ever wonder when 3.10.11 was coming? Well wait no longer (if you built it yourself, you could think of this one as 3.10.12)! With this combination you'll probably get loads of new warnings, but worry not - we have a tool for that as well, to automatically upgrade a load of code, adding well-defined symbol names, const, and more in all the right places. Maybe you already noticed this, you've been using it for months, but the virtual machine (the bit inside the server) has been updated as well! Oh, and all those string natives you know and love, like SendClientMessage and AddMenuItem? They all format now. All of them*.

Documentation on the updated includes:

https://github.com/openmultiplayer/omp-stdlib

Documentation on the new compiler:

https://github.com/openmultiplayer/compiler/
https://github.com/pawn-lang/compiler/

Documentation on qawno:

https://github.com/openmultiplayer/qawno/

Documentation on the upgrader tool:

https://github.com/openmultiplayer/upgrade

A full list of what's available:
  • Symbol length limit increased to 64, no more OnPlyrDoTheTing to try and fit your names in. Leading to...
  • Multiple natives decompressed - is Col short for Colour or Collision? Now you know!
  • Tags. Tags everywhere. See the included documentation.
  • The official includes are finally const-correct. No more complaining that some people might not have them.
  • Compiler version updated: __nameof, __addressof, fixes, and too many more things to go in to here.
  • switch is way faster.
  • More warnings for previously undetected issues. The more problems the compiler can find, the fewer you need to.
  • An upgradertool to add tags and const to user-code and fix several new warnings.
  • More consistent naming. Every native has been closely examined and compared to ensure the maximum level of similarity and intuitiveness in naming.
  • Added {Float, _}:... everywhere. What does this mean? It means no more format()**- think y_va but natively.
  • -O2, the highest pawn optimisation level, works when using the new compiler and VM. Some includes may need to be updated, but some already have. To help with that...
  • The __optimisation macro was added so code can configure itself when compiled with -O2.

*Almost all of them.
**Almost no more format().

SDK

Pawn is the long-standing, and still official, way to write modes for your server. It isn't going away, but for those of you who want more control we are finally releasing the full SDK (the Software Development Kit). This is a C++ interface to the server, the same one used by all the components that make up the core open.mp code. Anything they can do you can do too (compared to plugins, which were only designed to provide functions to pawn, not write modes).

We have some documentation under way, it takes time unfortunately. But in the meantime have several example components for those of you who want to get straight stuck in. These are all templates you can build upon, and go from basically nothing to a fully working component with most common features:

https://github.com/openmultiplayer/empty-template
https://github.com/openmultiplayer/basic-template
https://github.com/openmultiplayer/pawn-template
https://github.com/openmultiplayer/full-template

Also a few terms to get you started, so you can start to understand what it is that you're reading:
  • Component - A logical individual piece of the server, like objects or pickups. Ones you don't need don't need to be loaded.
  • Extension - Code that extends another bit of code. You can write component extensions, but the most common ones are player extensions, which define some structure of data to be associated with a player in addition to all their normal data like health and weapons.
  • UID - Unique IDentifier, a number that represents your component, and your component alone. This ia always required and can be got here: http://open.mp/uid
  • Entity - A thing, usually a thing a player can interact with, and which you might have a lot of. Objects are entities, but other players are also entities, even commands in a processor could be called entities.
  • Pool - Something that holds entities. When you have a lot you need to be able to access them by name or ID in some way, this is what a pool does.
  • Interface - Components use an abstract base class as an interface. This declares which methods a component has, but doesn't contain the code for the methods. Interfaces are passed around so that components can communicate with each other, but implementations are kept private.
  • SDK - The collection of all the interfaces defined by the core server.
  • ABI - An Application Binary Interface is the way compiled code talks to other compiled code. The interfaces exported by the SDK are ABI stable, which means that using two components compiled at different times will still work together.
  • pawn-natives - The library on which all native declarations are built. Useing a wrapper called SCRIPT_API around this library: https://github.com/openmultiplayer/pawn-natives
  • Event - Something that happens externally. Things like players connecting and typing commands are events. Any component can define events and tell other components when those events happen.
  • Handler - A component that wants to know when an event happens.

Features

Beside all the new features announced for pawn, there are several new (and newly announced) features in the server:
  • Per-player gang zones, as were in YSF.
  • Per-player pickups, also as in YSF.
  • AttachPlayerObjectToPlayer.
  • Better PawnPlus support.
  • :memory:, and other special names support in SQLite.
  • SQLite open flags.
  • exclude config option to not load certain components.
  • Show config parse errors, don't just silently fail.
  • SDK major version check, just in case we ever make major server changes (hopefully we won't).

Fixes

There were a few new bugs introduced in beta 11, and a few minor ones left over from before. The ones fixed include:
  • funcidx already registered warning.
  • GDK plugins (streamer etc) missing natives.
  • Random crash on GMX.
  • GDK callbacks sometimes not called.
  • No logging when requested in SQLite component.
  • Some settings not reset on GMX.
  • NPCs were connecting when there were a lot done at once.
  • .so was still needed in Linux legacy plugin names.

Links

Firstly, of course, is the new server version:

https://github.com/openmultiplayer/server-beta/releases

Secondly, the forums are back up. Head there for all your questions:

https://forum.open.mp/

Or if you prefer:

https://vk.com/open_mp

Finally, despite it being offered a few times, we have explicitly resisted any money up to this point; because we didn't feel it was right until we had proven ourselves with a release. With this post, that time is now, so if anyone wants to help support us (all donations will go towards infrastructure and future client dev work), it would be most appreciated:

https://www.patreon.com/open_mp
https://opencollective.com/openmultiplayer

And of course everything is still in active development, so please do check all the links above regularly to see what's new that we have.


  Dunzod Entered The Building
Posted by: Dunzod - 2022-12-31, 03:27 PM - Forum: Chat - No Replies

Dunzod Entered The Building!

Hello everyone, please ditch the Discord Forums. I vote BurgerShot <3

Over and out.

Happy New Year!


  Can't run the gamemode on hosting tab!
Posted by: nerfmydrugs - 2022-10-03, 04:30 PM - Forum: Pawn Scripting - Replies (2)

Hello i can't run my gamemode on the hosting tab that i bought, i can run it on my computer at all.

Quote:[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_sendto_remote_client'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_close_remote_client'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_query'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_connect'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_create'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'is_socket_valid'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_set_max_connections'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_listen'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'socket_destroy'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_insert_id'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_store_result'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_num_rows'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_retrieve_row'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_fetch_field_row'

[10/09/2022 21:23:31]? ? Error: Function not registered: 'mysql_free_result'

[10/09/2022 21:23:31] [debug] Run time error 19: "File or function is not found"

[10/09/2022 21:23:31] [debug]? socket_sendto_remote_client

[10/09/2022 21:23:31] [debug]? socket_close_remote_client

[10/09/2022 21:23:31] [debug]? socket_create

[10/09/2022 21:23:31] [debug]? is_socket_valid

[10/09/2022 21:23:31] [debug]? socket_set_max_connections

[10/09/2022 21:23:31] [debug]? socket_listen

[10/09/2022 21:23:31] [debug]? socket_destroy

[10/09/2022 21:23:31] [debug]? mysql_insert_id

[10/09/2022 21:23:31] [debug]? mysql_store_result

[10/09/2022 21:23:31] [debug]? mysql_num_rows

[10/09/2022 21:23:31] [debug]? mysql_retrieve_row

[10/09/2022 21:23:31] [debug]? mysql_fetch_field_row

[10/09/2022 21:23:31] [debug]? mysql_free_result

[10/09/2022 21:23:31] [debug] Run time error 19: "File or function is not found"

[10/09/2022 21:23:31] [debug]? socket_sendto_remote_client

[10/09/2022 21:23:31] [debug]? socket_close_remote_client

[10/09/2022 21:23:31] [debug]? socket_create

[10/09/2022 21:23:31] [debug]? is_socket_valid

[10/09/2022 21:23:31] [debug]? socket_set_max_connections

[10/09/2022 21:23:31] [debug]? socket_listen

[10/09/2022 21:23:31] [debug]? socket_destroy

[10/09/2022 21:23:31] [debug]? mysql_insert_id

[10/09/2022 21:23:31] [debug]? mysql_store_result

[10/09/2022 21:23:31] [debug]? mysql_num_rows

[10/09/2022 21:23:31] [debug]? mysql_retrieve_row

[10/09/2022 21:23:31] [debug]? mysql_fetch_field_row

[10/09/2022 21:23:31] [debug]? mysql_free_result



and showing gamemode unknown.


  Assembly tricks
Posted by: Y_Less - 2022-09-18, 11:58 PM - Forum: Tutorials - No Replies

Over the years of writing a lot of assembly in pawn I?ve developed a few tricks for things.? These are just some of them.



Calling a function by variable.



Normally to call a function you use CALL, but that only takes a constant, not a variable.? If you want to load the target address from a variable you instead need to use SCTRL to set the target.? But CALL does some other bits as well like setting the return address, which must be done manually with SCTRL using LCTRL.? LCTRL gets the current instruction pointer, but the return address should be the instruction after the SCTRL.? With this snippet it turns out that that return address is exactly nine cells later, so the code to call a function stored in a local variable called func is:



Pawn Wrote:#emit LCTRL? ? ? 6

#emit ADD.C? ? ? 36

#emit LCTRL? ? ? 8

#emit PUSH.pri

#emit LOAD.S.pri func

#emit SCTRL? ? ? 6



Control register 8



If you?re using the JIT plugin the return address needs to be modified to a new address space.? This is what LCTRL 8 does.? It takes the AMX address in pri and converts it to a JIT address.? However if you?re not using the JIT plugin there is no register eight and pri remains the same.? So always using it is perfectly safe - either the address will be correctly updated or it won?t change at all.



Named registers.



That code is already a bit unreadable.? I said the return address is nine cells later, yet 9 doesn?t appear anywhere in the code.? Also what are 6 and 8 doing?? Fortunately const values work in #emit, so we can name some of these constants and make them more readable.? The previous snippet thus becomes:



Pawn Wrote:#emit LCTRL? ? ? __cip

#emit ADD.C? ? ? __9_cells

#emit LCTRL? ? ? __jmp

#emit PUSH.pri

#emit LOAD.S.pri ptr

#emit SCTRL? ? ? __cip



[See this file]() for the full list of constant offsets defined in YSI, there are too many to list here.? But a few highlighted ones are:


  • __frame_offset - The offset of the previous frame?s pointer in the current frame.? Actually just 0, but still named to be clear.

  • __return_offset - The offset of the return address in the current frame (the value pushed in the code above).

  • __args_offset - The offset of the number of arguments passed to the current function (in bytes) in the current frame.

  • __param0_offset - The offset of the first parameter passed to the function, for example playerid in GetPlayerName(playerid, name, size);.

  • __minus1 - Just the number -1, since - is broken in #emit.

  • __cip - The control register for the current instruction pointer (cip).

  • __2_cells - The size in bytes of two cells.? Useful when adjusting other values to make it clear that it is just two cells generally, not an offset such as __args_offset.




So for example to load the number of parameters passed to the current function use:



Pawn Wrote:#emit LOAD.S.pri __args_offset // In bytes.

#emit SHR.C.pri 2 // In cells.



Or using another YSI define:



Pawn Wrote:#emit LOAD.S.pri __args_offset // In bytes.

#emit SHR.C.pri __COMPILER_CELL_SHIFT // In cells.



Current stack address.



This code will get the current address of the stack pointer (stk):



Pawn Wrote:#emit LCTRL __stk



But it will get the value in to the pri register while sometimes you want it in the alt register instead.? You could load it and move it:



Pawn Wrote:#emit LCTRL __stk

#emit MOVE.alt



But that takes two instructions and clobbers pri.? You could swap the registers about to preserve pri:



Pawn Wrote:#emit MOVE.alt

#emit LCTRL __stk

#emit XCHG



But that takes even more instructions.? Or you could just load the value straight in to alt:



Pawn Wrote:#emit STACK 0



This adjusts the stack size by naught cells.? It doesn?t get any bigger or smaller.? At first that seems pointless, but pawn-impl.pdf says this about STACK:



Quote:ALT = STK, STK = STK value



So the instruction first saves the current value of stk in alt, then adjusts the size.? We only want the first part so we NOP the second part by making the size adjustment naught, yet still get the register being saved.



Masking with shifts.



There is no AND.C so to do:



Pawn Wrote:a = b & 0xFFFF0000;



In assembly is:



Pawn Wrote:#emit LOAD.S.pri b

#emit CONST.alt? 0xFFFF0000

#emit AND

#emit STOR.S.pri a



That?s usually fine, but what if there is some data we want to keep in alt?? It could be saved to the stack:



Pawn Wrote:#emit LOAD.S.pri b

#emit PUSH.alt

#emit CONST.alt? 0xFFFF0000

#emit AND

#emit POP.alt

#emit STOR.S.pri a



But that takes many extra instructions.? But this code is the same as:



Pawn Wrote:a = (b >>> 16) << 16;



>>> and << lose data, and there are SHR.C and SHL.C instructions:



Pawn Wrote:#emit LOAD.S.pri b

#emit SHR.C.pri? 16

#emit SHR.L.pri? 16

#emit STOR.S.pri a



This is one cell longer than the first method, but two instructions shorter than the second and doesn?t clobber alt.? However, it doesn?t work for masks like 0x00FF0000 without yet another shift, at which point it probably isn?t worth the effort compared to AND, nor at all for any mask with naughts in like 0xF0F0F0F0:



Pawn Wrote:#emit LOAD.S.pri b

#emit SHR.L.pri? 8

#emit SHR.C.pri? 24

#emit SHR.L.pri? 16

#emit STOR.S.pri a



Escaping DAT



The data segment is called dat, and is distinct from the code segment cod.? The former is where all data is stored, including the stack and heap, the latter is where all the code is stored.? But to write self-modifying code of the sort found in @emit we must write to cod instead of dat, so how is that done?? The instruction STOR.pri writes the value of the register pri to the given variable, but the VM checks that these variables are valid, i.e. that they are in some active part of global memory the stack.? But there is an oversight in the indirection instructions - SREF.pri, LREF.S.alt, etc.? These take a variable and check that this variable is within the memory segment, then use the value in that variable as a pointer to the location to write to.? However, crucially this second access is NOT checked for validity, so we can write anywhere.? The code section comes immediately before the data section so we can write there using negative addresses.? The offset of dat is found in LCTRL 1, the offset of cod is in LCTRL 0, so the two together give the relative offset of cod from dat.? For example to read the parameter of HALT at address 0 in cod:



Pawn Wrote:new ptr;



// ptr = cod - dat 4

#emit LCTRL __dat

#emit MOVE.alt

#emit LCTRL __cod

#emit SUB

#emit ADD.C __1_cell

#emit STOR.S.pri ptr



// ptr = *ptr;

#emit LREF.S.pri ptr

#emit STOR.S.pri ptr



printf("Default HALT parameter: %d", ptr);



This trick is basically the core of amx_assembly, indirection, YSI, and more.? Without it there would be no code re-writing at all of the sort needed for advanced techniques like hook and inline.



You can invert strings.



For some reason this code compiles:



Pawn Wrote:Func(const str[])

{

}



main()

{

? ? new str[] = "Hello";

? ? Func(~str);

}



This is likely an oversight in the compiler because the inversion of a string is gibberish, the code will probably just crash.? But inverting an inversion gives the original value back so this is fine:



Pawn Wrote:Func(const str[])

{

}



main()

{

? ? new str[] = "Hello";

? ? Func(~~str);

}



It might seem pointless but in assembly you end up with:



asm Wrote:ADDR.pri str

INVERT

INVERT

PUSH.pri



Still pointless, except for the fact that it is a very interesting sequence of instructions that can be scanned for.? This INVERT/INVERT pair is the core of how y_inline actually locates inline functions and their names in memory (searching through the dat segment with LREF as detailed above).



Labels reset the stack.



Pawn Wrote:Func()

{

? ? new a = 4;

label:

? ? return a;

}



Compiles as:



asm Wrote:PROC

PUSH.C 4

LCRTL 5

ADD.C -4

SCTRL 4

LOAD.S.pri -4

STACK 4

RETN



So we push something to the stack, then reset the stack.? This is exploited in the decl keyword which declares a large variable without initialising it:



Pawn Wrote:decl a[128];



Becomes:



Pawn Wrote:goto after_a;

new a[128];

after_a:



Which compiles as:



asm Wrote:JUMP after_a

STACK -512

ZERO.pri

FILL 512

after_a:

LCTRL 5

ADD.C -512

SCTRL 5



Most importantly the FILL opcode is skipped, but because labels don?t modify scope a still exists.



There is at least one bit of assembly in YSI where the LCTRL/SCTRL pair generated by a label are important to functionality (Inline_NumArgs to cancel out a PUSH.pri elsewhere in the function), but they?re extremely rare for one reason - you can only jump backwards in assembly, future labels can?t be used.



Starting a function just to end it.



Consider the following function:



Pawn Wrote:sprintf(const fmat[], {Float, _}:...)

{

? ? static target[144];

? ? format(target, sizeof (target), fmat, ???);

? ? return target;

}



There are four main ways to implement this function and forward all the parameters - 1) a macro, 2) y_va, 3) copy all the parameters as in the very common bit of assembly everyone copies, 4) the clever way.? We already have most of the parameters for format on the stack, we just need to add two more.? To call a function the number of parameters in bytes is pushed, then the function is called with CALL, which adds the return address to the stack and jumps to the address specified.? The first thing in a function is then PROC, which saves the current frame pointer to the stack and sets up a new frame.? So at the moment that format is called in this function the stack looks like:


  • ???

  • ???

  • ???

  • fmat

  • arg_count

  • return_address

  • frame_pointer




target is declared static in this example to make the stack much simpler.? So really to call format we need:


  • ???

  • ???

  • ???

  • fmat

  • sizeof (target)

  • target

  • arg_count 8




Most of that data is already there if we can just modify the rest:



Pawn Wrote:// Remove the frame pointer from the stack and use it.

#emit POP.pri

#emit SCTRL 5



// Remove the return address from the stack.

#emit POP.alt



// Remove the arg count from the stack.

#emit POP.pri



// Push the two extra parameters.

const size = sizeof (target) * cellbytes;

#emit PUSH.C size

#emit PUSH.C target



// Update and push the parameter count.

#emit ADD.C __2_cells

#emit PUSH.pri



We have now modified the stack to look how we want, put the return address in alt, and set the frame pointer back to what it used to be.? So call format:



Pawn Wrote:#emit SYSREQ.C format



After format returns we need to restore the stack to how is was without clobbering alt, which still holds the return address we need, since SYSREQ.C doesn?t touch that register:



Pawn Wrote:// Remove and reset the count again.

#emit POP.pri

#emit ADD.C __m2_cells // -8



// Remove the next cell without altering any registers (tricky).

#emit SWAP.alt

#emit POP.alt



// Put the count back on the stack.

#emit SWAP.pri



// Put the return address back.

#emit PUSH.alt



Now the part this entire section has been building to - we need to get the frame pointer back out and back on to the stack.? We used SCTRL to save it (we could have saved it to a global variable, but why waste one when the control register is right there, plus a global variable might not work if the native calls a callback), so the obvious code is:



Pawn Wrote:#emit LCTRL 5

#emit PUSH.pri

#emit LCTRL 4

#emit SCTRL 5



But there?s an instruction that does all of this in one go:



Pawn Wrote:#emit PROC



So you may sometimes see PROC randomly in the middle of a function, and this is what it is doing.? In fact it isn?t unusual to see:



Pawn Wrote:#emit PROC

#emit RETN



Which is the name of the section - we call PROC just to set up the stack correctly for calling RETN.



The stack doesn?t even need restoring.



Normally after calling a native you need to remove all the parameters pushed for it, but you don?t after calling a normal function - RETN does that for you.? In the above example we needed to restore the stack to how it was before format was called, but sometimes you don?t need to because the native is the last thing done in the function.? In that case we can just exploit RETN to remove all the extra parameters we added too:



Pawn Wrote:// As before.

#emit POP.pri

#emit SCTRL 5

#emit POP.alt

#emit POP.pri

const size = sizeof (target) * cellbytes;

#emit PUSH.C size

#emit PUSH.C target

#emit ADD.C __2_cells

#emit PUSH.pri

#emit SYSREQ.C format



// Leave the two extra parameters on the stack and just pretend they were passed to us.

// Push the return address again.

#emit PUSH.alt



// Put the frame pointer back and end the function.

#emit PROC

#emit RETN


  #emit, __emit, @emit
Posted by: Y_Less - 2022-09-18, 01:12 PM - Forum: Tutorials - No Replies

Between the latest versions of the compiler and the amx_assembly library, there are now three versions of emit - #emit, __emit, and @emit.? They all have subtly different uses and quirks, and these differences are explained here.



#emit



This is the original version, and is used to insert assembly (p-code) in to a script directly, exactly at the point it is used.? For example:



pawn Wrote:Function()

{

? ? #emit ZERO.pri

? ? #emit RETN

? ? return 1;

}



This function will be compiled with two return instructions - one from RETN and one from return, and the second one will never be hit.? The generated assembly will look something like:



asm Wrote:PROC

ZERO.pri

RETN

CONST.pri 1

RETN



This is the most inflexible version - it just puts exactly what you typed exactly where you typed it.



It is also in a very strange part of the compiler, likely because it was only originally intended for basic debugging of the pawn VM (hence why it was removed in later official releases).? It uses barely any of the standard compiler features:



pawn Wrote:#emit CONST.pri 5 // This works.

#emit CONST.pri -5 // This is a syntax error.



Thus you will often see negative numbers written in their full hex representation (for some reason hex does work despite the fact that negative numbers don?t):



pawn Wrote:#emit CONST.pri 0xFFFFFFFB // -5



Defines don?t work to abstract that, but const does:



pawn Wrote:#define MINUS_5 0xFFFFFFFB

#emit CONST.pri MINUS_5 // Undefined symbol `MINUS_5`



pawn Wrote:const MINUS_5 = -5;

#emit CONST.pri MINUS_5 // Fine.



And #if is completely ignored:



pawn Wrote:#if TEST

? ? #emit CONST.pri 5

#else

? ? #emit CONST.pri 6

#endif



Very unhelpfully generates:



asm Wrote:CONST.pri 5

CONST.pri 6



Both branches are used, so you will often see functions with assembly at the end of a file, ommitted with #endinput:



pawn Wrote:#if !TEST

? ? #endinput

#endif



Func()

{

? ? #emit CONST.pri 5

}



Or in a separate file altogether.



In short #emit is very weird, but everything else has been built from it so there?s a lot to thank it for.



__emit



This is #emit, but super-powered.? It is a full expression-level version of #emit correctly integrated in to the compiler.? That means you can use full compile-time expressions:



pawn Wrote:__emit(CONST.pri (5 * MAX_PLAYERS));



You can use it in defines:



pawn Wrote:#define GetCurrentAddress() __emit(LCTRL 6)



And you can use it in expressions:



pawn Wrote:new var = __emit(CONST.pri 6);



Where the register pri is always the result of __emit returned like a normal expression.? Compared to the old version:



pawn Wrote:new var = 0;

#emit CONST.pri 6

#emit STOR.S.pri var



It also adds .U, which tries to work out which instruction to use based on the parameter.? For example with #emit incrementing a global variable is:



pawn Wrote:#emit INC var



While incrementing a local variable is:



pawn Wrote:#emit INC.S var



With __emit these become:



pawn Wrote:__emit(INC.U var);



And the compiler works out which instruction to use based on the scope of var.



There is more that __emit can do, like including multiple instructions in one expression:



pawn Wrote:new var = __emit(LOAD.S.pri param, ADD.C 5); // new var = param 5;



But it is still fundamentally the same as #emit in one important way - it is done at compile-time by the compiler.? Everything is inserted in to the AMX at a fixed location (bearing in mind that macros can change this location).



@emit



This is a macro, and purely a run-time operation.? The simplest way to see what it does is to remove the macro itself and look at the underlying function calls.? A context is created, which includes an address in the AMX, and instructions are written to that address one-by-one while the server is running.? This is a very easy way to write self-modifying code:



pawn Wrote:ReturnFive()

{

? ? // Wrong value!

? ? return 3;

}



public OnCodeInit()

{

? ? // Create the context.

? ? new context[AsmContext];



? ? // Initialise the context to point to a function.

? ? AsmInitPtr(context, _:addressof (ReturnFive<>), 4 * cellbytes);



This code creates a context, points it to the given function to rewrite it, and makes the buffer big enough to hold four cells.? Note that this code is in OnCodeInit, which is a special callback called before the mode starts, and before the JIT plugin compiles the mode.? All code rewriting must be done before JIT initialisation.? Note also that because OnCodeInit is called so early you can?t use most useful YSI features like hook and foreach - it too is generating its own code at this point.? We then rewrite the function at that address in assembly:



pawn Wrote:? ? // A function starts with `PROC`.

? ? AsmEmitProc(context);



? ? // Then load the correct return value in to `pri`.

? ? AsmEmitConstPri(context, 5);



? ? // And end the function.

? ? AsmEmitRetn(context);



? ? return 1;

}



@emit is just a clever macro that wraps all of these confusing function calls.? While they are fundamentally how code is rewritten at run-time, there?s a lot of boilerplate there that obscures what code is being generated.? So if we call the context ctx (this is important as it is hard-coded in to the macros).? The @emit macro is something like:



pawn Wrote:#define @emit%0%1 AsmEmit%0(ctx, %1);



It isn?t exactly that, because that?s not a valid macro, but it shows what is happening.? Thus the code becomes:



pawn Wrote:ReturnFive()

{

? ? // Wrong value!

? ? return 3;

}



public OnCodeInit()

{

? ? // Create the context.

? ? new ctx[AsmContext];



? ? // Initialise the context to point to a function.

? ? AsmInitPtr(ctx, _:addressof (ReturnFive<>), 4 * cellbytes);



? ? // A function starts with `PROC`.

? ? @emit PROC



? ? // Then load the correct return value in to `pri`.

? ? @emit CONST.pri 5



? ? // And end the function.

? ? @emit RETN



? ? return 1;

}



So if you see @emit look around for ctx and that?s where the instructions are being written to in memory.? You can also use labels, but if you want to use variables in the generated code, and not to generate the code, you need to explicitly get their address:



pawn Wrote:// return var ? 0 : 1;

@emit LOAD.S.pri ref(var)

@emit JZER.label failure

@emit CONST.pri 0

@emit RETN

@emit failure:

@emit CONST.pri 1

@emit RETN


  possible to create a folder inside scriptfiles?
Posted by: mems - 2022-09-12, 01:12 PM - Forum: Pawn Scripting - Replies (3)

hello,



title possibly explains exactly what i want. i'm looking to make a function that checks if there is a specific named folder on the scriptfiles folder. if there isn't, then it simply creates that folder. tried searching for a library that could help me but apart from filemanager which probably also doesn't do what i'm asking for i couldn't find anything else. grateful if anyone helps!


  SA-MP 0.3DL compatibility plus other added features and bug fixes - SERVER BETA RELEA
Posted by: Potassium - 2022-09-08, 09:26 AM - Forum: Development Updates - No Replies

Posted in our Discord server announcements channel by kseny (discord.gg/samp)



Hello everyone



We have just released open.mp server beta 9, fixing several reported issues and adding several new features. The most notable change being - SA:MP 0.3DL support. You can now run 0.3.7 and 0.3.DL compatible servers from the same binary!



Other Changes


  • Dynamic tick rate. Specify a target tickrate, rather than a fixed sleep time.

    - Use the tickrate console command to set the rate

    - sleep can now be a float to accomodate precise tick rates.
  • More plugin compatibility - fsutil, Discord connector (only with non static build)

  • SetSpawnInfo return fixed.

  • Fix weather and time not resetting after GMX.

  • Fix various GMX bugs.

  • Fix various console commands.

  • Fix GetPlayerClass.

  • Fix GetVehicleLastDriver.

  • Add GetVehicles native.

  • Add GetPlayers native.

  • Add GetActors native.

  • All lagcomp modes are now available through config.

  • Fix trailer sync.

  • Fix GetVehicleLastDriver.

  • Fix GetPlayerRotationQuat.

  • Fix crash in vehicle component.






SA:MP DL





This is the big news obviously, and comes with a whole host of new settings:


  • Implemented all DL natives and callbacks (AddSimpleModel, AddSimpleModelTimed, GetPlayerCustomSkin, OnPlayerFinishedDownloading, OnPlayerRequestDownload):

    - RedirectDownload native and OnPlayerRequestDownload callback are now deprecated in favour of CDN config options.

  • Add artwork.enable (legacy: useartwork) config option.

  • Add artwork.models_path (legacy: artpath) config option.

    - Server can load custom models from artconfig.txt file like SA:MP does.

  • 0.3.7 compatibility is preserved and can be configured by network.allow_037_clients config option (true by default).

  • open.mp server comes now with a built in webserver used to serve custom models

    - Webserver is using open.mp server bind address and port. Please allow TCP connections on your port in firewall if you plan to use it.- If your public IP address is different than bind address (ex: you're behind a router) you'll need to set it in network.public_addr config option.


Notes


  • Due to few changes old config.json files may not work properly. Please use ./omp-server --default-config to generate a new one

  • server.cfg users are not affected.

  • While allowing 0.3.7 connections only 1000 objects can be created

  • open.mp server now provides two types of Linux builds, standard and static. You are encouraged to use the standard build if possible, it will minimize incompatibilities with various plugins; however, it will require openssl 1.1 installed on your system. If you can't install modern openssl on your system (typically if it's very old), you can use the static build, but some plugins or components might fail to load and crash the server.


Official Includes



Preparing a full release is not just having a working server, but all the other peripherals as well - libraries, tools, documentation, and more. On the pawn side open.mp is a significant upgrade, with many QoL improvements already seen through fixes and new functions, and more to come. A big part of this push is more compiler diagnostics to find code problems ahead of time, mostly through more tags and const-correctness. While the offical versions aren't out yet you can still help in the meantime by testing your code with the following includes and tools:



https://github.com/pawn-lang/samp-stdlib...y-overhaul?

https://github.com/pawn-lang/pawn-stdlib...ed-natives?

https://github.com/openmultiplayer/upgrade?

https://github.com/pawn-lang/compiler



These were originally developed to improve the default SA:MP includes, but never fully released (i.e. never merged to master, despite the PR being accepted). The open.mp includes build on the foundation established here so think of these as a stepping-stone to full open.mp tag and const safety; and important feedback on their direction. See the links above for far more information and documentation on upgrading.



As ever, if you don't want to upgrade old code and includes will still work (at least for the first release).


  optimize the code?
Posted by: nbx2000 - 2022-08-07, 07:44 PM - Forum: Pawn Scripting - No Replies

You can improve this script or leave it like this
#include <a_samp>

#define? TIME? ? ? ? ? ? 1? //When the contest will start (Minutes)
#define? PRIZE? ? 3000 //Reward ($$$) when win in Math Contest
#define? PRIZESCORE? ? ? 5? //Reward (Score) when win in Math Contest

new answer;
new endm = 0;
new no1, no2, no3;
new typem = -1;
new timermath;
new timermath2;
new str[128];

forward Math();
forward MathEnd();

#define COLOR_YELLOW? ? 0xFFFF00FF

#define white? ? ? ? ? ? "{FFFFFF}"
#define red? ? ? ? ? ? ? "{FF002B}"
#define orange? ? ? ? ? "{F2C80C}"

#define FILTERSCRIPT
#if defined FILTERSCRIPT

public OnFilterScriptInit()
{
print("\n");
print("* Math System by BuzZ *");
print("* Loaded *");
print("\n");
typem = -1;
endm = 0;
timermath = SetTimer("Math", 1000*60*TIME, true);
return 1;
}

public OnFilterScriptExit()
{
print("\n");
print("* Math System by BuzZ *");
print("* Unloaded *");
print("\n");
typem = -1;
endm = 0;
KillTimer(timermath);
return 1;
}

#endif

public Math()
{
typem = random(2);
no1 = random(600);
no2 = random(50);
no3 = random(100);

endm = 1;
switch(typem)
{
case 0:
{
? ? answer = no1 no2 no3;
format(str, sizeof(str), "MATH: "white"The first one who answers (solve) this "red"%d%d%d "orange"wins $3,000 5 score", no1, no2, no3);
SendClientMessageToAll(COLOR_YELLOW, str);
}
case 1:
{
answer = no1 - no2 - no3;
format(str, sizeof(str), "MATH: "white"The first one who answers (solve) this "red"%d-%d-%d "orange"wins $3,000 5 score", no1, no2, no3);
SendClientMessageToAll(COLOR_YELLOW, str);
}
case 2:
{
answer = no1 * no2 * no3;
format(str, sizeof(str), "MATH: "white"The first one who answers (solve) this "red"%dx%dx%d "orange"wins $3,000 5 score", no1, no2, no3);
SendClientMessageToAll(COLOR_YELLOW, str);
}
}
SendClientMessageToAll(-1, "Math will end on 30 seconds!");
timermath2 = SetTimer("MathEnd", 1000*30, false);
return 1;
}

public MathEnd()
{
switch(typem)
{
case 0:
{
format(str, sizeof(str), "MATH: "white"No one won the Math Contest the answer is '%d'", answer);
SendClientMessageToAll(COLOR_YELLOW, str);
}
case 1:
{
format(str, sizeof(str), "MATH: "white"No one won the Math Contest the answer is '%d'", answer);
SendClientMessageToAll(COLOR_YELLOW, str);
}
case 2:
{
format(str, sizeof(str), "MATH: "white"No one won the Math Contest the answer is '%d'", answer);
SendClientMessageToAll(COLOR_YELLOW, str);
}
}
endm = 0;
KillTimer(timermath2);
return 1;
}

public OnPlayerText(playerid, text[])
{
if(strval(text) == answer && endm == 1)
{
? ? format(str, sizeof(str), "MATH: %s(%d) won the Math Contest, He/She won the $%d %i score [ Answer: %d ]", GetName(playerid), playerid, PRIZE, PRIZESCORE, answer);
? ? SendClientMessageToAll(COLOR_YELLOW, str);
? ? GivePlayerMoney(playerid, PRIZE);
? ? SetPlayerScore(playerid, GetPlayerScore(playerid) PRIZESCORE);
? ? KillTimer(timermath2);
? ? endm = 0;
? ? return 0;
}
return 1;
}

You can improve this script or leave it like this? ??


  goto label
Posted by: claudespeed - 2022-07-29, 11:36 PM - Forum: Pawn Scripting - No Replies

//SOLVED


Lightbulb Fusez's Map Editor (Version 3) [Dynamic Categories] [Improved] [Best of Version 1&2 C
Posted by: fusez - 2022-07-19, 07:30 PM - Forum: Filterscripts - Replies (2)

[Image: GXbn2ba.png]

Version 3?GitHub?Page