[Plugin] Python
#1

Introduction

I started to work on this plugin a few weeks ago, as I thought it would be much easier and faster to write scripts in Python than in PAWN.
Now every SAMP native is added and can be used from within Python scripts, though most of them are untested and might not work properly, so this is not a final/stable release yet, but probably most of them will work anyway.
Of course anyone can test some functions or give me some suggestions on how to improve the plugin. Any untested SAMP functions are commented with a TODO in nativefunctions.cpp.


What is it?

With this plugin you can use Python scripts for writing a gamemode and use any functions and callbacks available in SAMP.
Most functions can be used exactly the same way as in PAWN, but some of them are somewhat different (see below).

A simple testing script in Python looks like this:
http://pastebin.com/HM5TAani


Requirements

Before using this plugin you will need Python installed, you can get it from the Python homepage. If you use a Linux server, you should already have it installed.
Both newest packages were built with Python 2.6; you will need that version, if you don't want to build it for yourself.

For compiling on Linux you also need the package python-dev, on Windows everything should have already been installed with the Python installer.
On Linux you can just type "make" in the source directory to compile the plugin, it will use the paths returned by python-config.
On Windows you have to manually add the include directory (usually "C:\Program Files (x86)\Python\include") and the library directory (usually "C:\Program Files (x86)\Python\libs").
When running a 64-bit Linux version, you will need the 32-bit version of Python.

Of course, you will also need some knowledge about Python.


How to use

First, you have to download the plugin appropriate to your operating system from below (or download the source and compile the plugin for yourself).
Then put it in the "plugins" directory of SAMP and copy the file python.amx to the gamemode directory. Now add the plugin to your server.cfg ("plugins pythonplugin.so" if you haven't changed the file name) and set the gamemode to "python" (this is required for loading a Python script, redirecting callbacks and calling SAMP natives).


Sometimes you might see a few errors like this one when you start the server:
Код:
PYTHON: Could not find native IsPlayerHoldingObject
If you are using another SAMP server version than 0.3d or 0.3c (for which there are pre-compiled python.amx are available), you have to manually edit the python.pwn and add/remove/edit the functions different in your version.
When calling a function from Python, that wasn't found, it will crash the server.
Of course it's also possible to use Python from a filterscript. For this you just have to change the OnGameModeInit/-Exit to OnFilterScriptInit/-Exit and recompile it. This can be useful if you want to have a gamemode in PAWN but extend functionality with Python scripts just like with normal filterscripts.

After that, create a file called gamemode.py and a file __init__.py in the gamemodes directory and you can start to write a script in Python.

You can also create a file python.cfg in the scriptfiles directory and add every Python module to be loaded by the plugin, for example:
Код:
gamemode
test
The modules specified here are relative to the gamemodes directory (on Windows with Python 2.6 also in the SAMP server root due to a bug in Python).
Every loaded script can contain SAMP callbacks, which are then being called. If one function returns 0 (1 for OnPlayerCommandText), that value is being returned, the default value otherwise.


Functions / Callbacks

As mentioned above, almost every SAMP function can be called exactly the same as in PAWN.
Differences are listed here:

Callbacks
OnPyInit(): This function will be called when the script is being loaded.
OnPyExit(): This function will be called when the script is being unloaded.

Functions
SetTimer(func, interval, repeating[, params ]): The parameter "func" needs to be a callable object and no string.
With the last parameter (optional) you can pass a tuple. Its contents are passed as parameters to the function specified with funcname.
InvokeFunction(func[, params ]): This function can be used from another thread to invoke a function into PAWN's thread (e.g. outputting a result from a background thread to a player). The second optional parameter contains a tuple like in SetTimer.

Functions with hexadecimal colors (SendClientMessage, TextDrawColor, ...): The colors can also be specified as a tuple (see example script above) with four elements (RGBA).
Functions with reference parameters: Any parameters that are references are removed. The function will then return a dictionary containing every reference parameter (if there is only one reference parameter and no return value (GetPlayerName, GetPlayerHealth, ...), it is returned directly; function return values will be returned as "return" in the dictionary).


Threads

Since the version from Jul. 18, 2011 it is possible to use multiple threads in the Python script. Threads can be started with Python's own modules 'thread' or 'threading'.
This can be useful if you for example want to make a HTTP request. When the background thread is done with the request, it can call InvokeFunction to get the result sent to a player.

Inside other threads you may not call any functions in the SAMP module except for SetTimer, KillTimer and InvokeFunction, otherwise it will crash your server.
If you want to restart the gamemode using the RCON commands changemode or gmx, you need to make sure, that any thread has exited before OnPyExit has returned.

In the Windows and the Linux package there is an example on using threads (python/httpserver.py), where a very simple HTTP server is used to make a simple web interface for showing online player information.

Command processing

Of course you can just split the cmdtext and use if/elif for processing commands, but that is not really fast and would require processing seperately in every Python module, where you want to have commands.
Another, much better and faster way is to use the Python module "cmdparser.py", which is available in the download section below. This module provides a function decorator with which you can decorate any function in any module which is then added as a command.
Before using it, you have to import it and add the following to ONE OnPlayerCommandText (adding it to more than one will cause any command to be executed multiple times):
Код:
from cmdparser import cmd, handle_command
def OnPlayerCommandText(playerid, cmdtext):
	handle_command(playerid, cmdtext)
The simplest way of using it is the following:
Код:
@cmd
def mycmd(playerid, prm1=None, prm2=None):
	print('player %d: %s %s' % (playerid, prm1, prm2))
This defines a new command with the name "mycmd" with two parameters prm1 and prm2. You should always define parameters with default values, because otherwise it will throw an exception if a player does not specify all needed parameters.
When just using the decorator like this, you don't have to specify a command name, it is taken from the function name. But if you want to use some more advanced features, you have to use it like that and then you have to specify the command name:
Код:
@cmd("mycmd", requires=samp.IsPlayerAdmin, convert=dict(prm1=int))
def cmd_mycmd(playerid, prm1=None):
	if prm1 == None:
		samp.SendClientMessage(playerid, 0xFFFFFF00, "Missing parameter")
		return
	print('prm1 is now an integer! %d' % prm1)
This again defines the command "mycmd", but this time there are some parameters passed to the decorator.
The first one is the name of the command (or a list of multiple aliases for the command), which is required.
The second one can be either one single callable object or a list/tuple (or any other iterable object which gives callable objects) with multiple callable objects, which expect exactly one argument, a playerid, and returns True or False. These functions are called when a player uses the command and if one of these returns False, a text message with the text unauthorized_text and the color unauthd_color (both parameters of cmd) is sent to the player and the command function is not executed.
The last parameter, convert, is a dictionary with function parameter's names as the key and a function as the value. This function has to expect one string and return any other type. The return value of that function is then passed to the command function as that parameter.

Also, you can tell the command processor to pass the raw cmdtext to the function with the parameter "raw" (raw=True in the decorator). This is for example useful if you need consecutive whitespace characters in a string.
Every parameter is also documented in the docstring of the cmd function.

Speed

Python is slightly slower when executing SAMP natives and is even slower with functions with string parameters.
However this is not because Python is slower, but because every parameter from SAMP native functions need to be parsed and the right PAWN function needs to be called.
Except for that Python scripts should not be any slower than PAWN scripts, as Python scripts are also compiled to byte code (.pyc), which is done automatically by the interpreter.

Download
****** Code project page: Here

Python modules:
Command parser (cmdparser.py): Pastebin

Old version (Dec. 02, 2011):
Source: Download (Visual Studio 2010 solution, makefile and project files)
Windows: Download (compiled with Visual Studio 2010 and Python 2.6)
Linux: Download (compiled on Debian 6 with Python 2.6)

Old version (Jul. 18, 2011):
Source: Download (Visual Studio 2010 solution, makefile and project files)
Windows: Download (compiled with Visual Studio 2010 and Python 2.6)
Linux: Download (compiled on Ubuntu 11.04; requires GLIBC >= 2.4 and Python 2.7)

Updates
Dec. 27, 2010: Added the last few functions, fixed a few bugs and added constants and OnPyExit callback.
Jan. 3, 2011: Fixed timers (they didn't work at all, but they should now) and added another simple example script. Also, the PAWN include file, example scripts and the python.pwn for SAMP 0.3c is now in the Windows and Linux archives..
Feb. 9, 2011: Added support for multiple scripts.
Jul. 18, 2011:
  • completely reimplemented timers
  • added possibility to use threads (and other things using threads in Python like Python's own timer class); see section "Threads" before using
  • added OnRconCommand
  • added InvokeFunction to invoke a function from another thread into PAWN's thread
  • changed SetTimer to accept a callable object instead of a string containing a function name
  • fixed sys.path being overwritten after start (mainly paths added by site.py)
  • fixed crash on Linux when using SAMP natives with string parameters
  • fixed wrong handling of True and False in callback return values
  • removed dictionary return value from GetPlayerIp and directly return the ip now
Nov. 24, 2011: added a command parser (see "Command processing"); no changes to the plugin itself
Dec. 02, 2011:
  • added new functions and callbacks from SAMP 0.3c R3/R4 and 0.3d
  • updated example gamemode.py to use the new cmdparser module
  • disabled warnings about missing natives for IsPlayerHoldingObject, SetPlayerHoldingObject and StopPlayerHoldingObject
  • instead of the SAMP directory now add the gamemodes directory to sys.path (this needs updating imports of modules in the SAMP directory)
  • fixed deadlock when exiting the gamemode if there is no OnPyExit function in a Python module
Jan. 21, 2012:
  • fixed (or worked around) undefined symbol issues with Python C modules
  • added to ****** Code and now published under the GPL
Reply


Messages In This Thread
Python - by Fabsch - 25.12.2010, 19:37
Re: Python - by [L3th4l] - 25.12.2010, 19:57
Re: Python - by HyperZ - 25.12.2010, 20:24
Re: Python - by Guest3598475934857938411 - 25.12.2010, 20:31
Respuesta: Python - by anonymousx - 25.12.2010, 21:56
Re: Python - by Retardedwolf - 25.12.2010, 22:02
Re: Python - by Mean - 25.12.2010, 22:09
Re: Python - by mkr - 26.12.2010, 08:47
Re: Python - by Wyu - 26.12.2010, 09:00
AW: Python - by Fabsch - 27.12.2010, 18:39
Re: Python - by yass0016 - 29.12.2010, 23:43
Re: Python - by _rAped - 30.12.2010, 00:11
Re: Python - by Lorenc_ - 30.12.2010, 00:28
Re: Python - by TheRob - 30.12.2010, 01:00
Re: Python - by Retardedwolf - 30.12.2010, 01:12
Re: Python - by mkr - 30.12.2010, 08:20
AW: Re: Python - by Fabsch - 30.12.2010, 14:08
Re: Python - by Retardedwolf - 30.12.2010, 19:22
Re: Python - by mkr - 05.01.2011, 22:18
AW: Python - by Fabsch - 06.01.2011, 13:35
Re: Python - by Leeroy. - 06.01.2011, 13:49
Re: Python - by GaGlets(R) - 06.01.2011, 14:47
AW: Python - by Fabsch - 06.01.2011, 15:55
Re: Python - by Wyu - 06.01.2011, 16:37
Re: Python - by ToPhrESH - 09.01.2011, 03:21
Re: Python - by TheYoungCapone - 09.01.2011, 03:50
AW: Re: Python - by Fabsch - 09.01.2011, 18:41
Re: Python - by mkr - 21.05.2011, 02:35
AW: Re: Python - by Fabsch - 21.05.2011, 16:11
Re: Python - by Sfinx_17 - 24.07.2011, 23:01
Re: Python - by GangsTa_ - 25.07.2011, 07:29
AW: Re: Python - by Fabsch - 25.07.2011, 10:38
Re: Python - by Sfinx_17 - 26.07.2011, 18:23
AW: Python - by Fabsch - 28.07.2011, 13:12
Re: Python - by Trenico - 19.01.2012, 22:12
AW: Python - by Fabsch - 20.01.2012, 11:17
Re: Python - by gephaest - 20.01.2012, 22:34
Re: Python - by Deskoft - 20.01.2012, 23:17
AW: Python - by NaS - 20.01.2012, 23:57
Re: Python - by gephaest - 21.01.2012, 08:30
AW: Python - by NaS - 22.01.2012, 00:02
AW: Python - by Fabsch - 22.01.2012, 11:31

Forum Jump:


Users browsing this thread: 1 Guest(s)