This is a Python 3 interface with the Blockland engine. Many of the C++ functions available with TSFuncs are available to Python in addition to anything inside the wide array of default Python libraries.

Queuenard 560fc2d437 Added FullFeatureTest.zip example, fixed README 2 years ago
examples 560fc2d437 Added FullFeatureTest.zip example, fixed README 2 years ago
generated 3b6f8696df 0.0.2: improved bootstrap due to fixing direct file execution in loader; fixed Windows DLL issues; added BLpython to basic test 2 years ago
include 318840e5a5 ZIP importer rewritten. tsfuncs now included in project with minhook excluded. Now using BLstructs and now directly accesses SimSet objects in C++. Include folder cleaned up. 2 years ago
release f9f03d87ae Added crash protection around TS-returning Python functions that don't return properly 2 years ago
src f9f03d87ae Added crash protection around TS-returning Python functions that don't return properly 2 years ago
srcPython 3b6f8696df 0.0.2: improved bootstrap due to fixing direct file execution in loader; fixed Windows DLL issues; added BLpython to basic test 2 years ago
CMakeLists.txt f9f03d87ae Added crash protection around TS-returning Python functions that don't return properly 2 years ago
README.md 560fc2d437 Added FullFeatureTest.zip example, fixed README 2 years ago
cmake-variants.yaml d926726158 Initial commit 2 years ago

README.md

BLpython3

This is a Python 3 interface with the Blockland engine. Many of the C++ functions available with TSFuncs are available to Python in addition to anything inside the wide array of default Python libraries.

This acts as a sort of opposite to BlLua: you are given the full power of Python without restriction. Python is in control here, rather than TorqueScript.

There are two goals: speed and power.

  1. Carefully-written Python code can be faster than TorqueScript.
  2. You can use any library provided in the embedded Python distribution: threads, image processing, date and time, SQLite3, JSON, HTTP(S) client, network sockets, compression, and so on...

This is a beta project so expect some Python errors to be unhandled. Any uncaught exceptions will kill the entire Python engine.

Installing

Install RedBlocklandLoader (Eagle517) here: https://gitlab.com/Eagle517/redblocklandloader

Create a "modules" folder in your Blockland folder if you don't have one yet.

Copy "BLpython3.dll" and the "python" folder (located in the release folder of this project) to the "modules" folder.

Re-installing

Delete modules\BLpytohn\bootstrap.py because an improved loader was written.

Security notice

Python scripts are given full permissions - treat any modules as if you were installing another program or DLL.

Installing modules

Drop the module ZIP file in the folder "modules/BLpython". This folder is not created until BLpython3 successfully runs for the first time.

No modules have been created at the time of writing except for the HelloWorld and FullFeatureTest packages.

Build dependencies (for developers)

TSfuncs - Now included without minhook code, which is not used by this project - https://gitlab.com/Eagle517/tsfuncs xxd - converts bootstrap.py and test.py into C arrays for using C++ includes to directly store Python code

Runtime dependencies (for developers)

Python stable 3 Windows embeddable package (32-bit) - https://www.python.org/downloads/release/python-3107/

Size 7615330 bytes

MD5 python-3.10.7-embed-win32.zip 7e4de22bfe1e6d333b2c691ec2c1fcee

SHA256 python-3.10.7-embed-win32.zip d5eb57d67c8c74c1362e671933720151a62eaae4437e71dad7b06ddbcdbad0ff

Writing modules (for developers)

Note the structure has changed and has been simplified.

A fully-working package is provided in examples/HelloWorld.zip

Example ZIP package structure called "packageName":

packageName.zip
	packageName/
		__init__.py (executes during DLL load)
			Import modules in the same folder with "from . import <module>"
			"from . import ImportThisClass"
		ImportThisClass.py
			Another module
	README.txt - optional README

Modules are executed during Sim::init. Eval does not work and there are no objects. Try to execute code at a later time.

The API (for developers)

Object functions work based on object IDs. An object ID of zero means an object does not exist.

BLpython module

TSgetvar("$Favorite::Brick1_0")
	Get a TorqueScript global variable. Dollar sign is optional.

TSgetvar_int("$Game::argc")
	Get a TorqueScript global variable as an integer. Dollar sign is optional.

TSfindObj("rootGroup")
	Find an object ID by its name. Does not raise TorqueObjectNotFoundError, but will return 0 if object wasn't found.

BlPrint("print this")
	Print through Blockland's streams. Accepts one string argument.

TSregisterFunc()
	Register a TorqueScript function. First argument to the called Python function is the TorqueScript function name.
	Usage: (string)package name, (string)class name, (string)torque function, (callable)python function,
	None|str|int|float|bool, min args, max args
	Can raise TorqueRegisterFunctionError.

TSeval("echo(\"hello from python\");")
	Eval a string

TScall((string)name, arg0... arg19)
	Call a function up to 20 arguments.

TScallSimObj((int)object id, (string)name, arg0... arg18)
	Call a function on an object. Note there can only be 19 arguments beyond the object ID. Can raise TorqueObjectNotFoundError.

TSgetDataField(TSfindObj('MainMenuGUI'), 'vertSizing', None)
	Get a field from an object. The field name is in two parts: slot and array. Can raise TorqueObjectNotFoundError.

TSgetDataField_int(TSfindObj('MainMenuGUI'), 'visible', None)
	Get a field from an object as an integer. The field name is in two parts: slot and array. Can raise TorqueObjectNotFoundError.

TSsetDataField(TSfindObj('MainMenuGUI'), 'visible', None, 0)
	Set a field on an object. The field name is in two parts: slot and array. Can raise TorqueObjectNotFoundError.

BLpython module exceptions

TorqueObjectNotFoundError
TorqueRegisterFunctionError

SimSetLooper module (contains object class of same name, child of BLpython module)

  • In the constructor, takes a single integer: the object ID of a SimSet or SimGroup (anything that implements getObject() and getCount() in TorqueScript)
  • Constructor can raise TorqueObjectNotFoundError
  • Implements iter and iternext (__iter__ and __next__) making this iterable
  • The logic now directly works off a SimSet's mElementCount and mArray variables, as if the engine itself were looping through the SimSet

Examples (for developers)

The example package FullFeatureTest.zip uses most if not all of the features of this program. After installing, it can be initiated with BLP_FFT_test_all(); in the console.

Create multiple functions accesible through TorqueScript and mess with the different return types:

import BLpython

#Keyword arguments "obj" and "args" are mandatory
#obj keyword is provided as a Torque object ID - only relevant in class calls

def PYreturn(obj=None, args=None):
	return

def PYreturnString(obj=None, args=None):
	return "string from python"

def PYreturnInt(obj=None, args=None):
	return 3

def PYreturnFloat(obj=None, args=None):
	return float(5.0)

def PYreturnBool(obj=None, args=None):
	return True

#Make functions callable from TorqueScript (no package and no class, so regular functions)

BLpython.TSregisterFunc(None, None, "PYreturn", PYreturn, None, "help text", 1, 1)
BLpython.TSregisterFunc(None, None, "PYreturnString", PYreturnString, str, "help text", 1, 1)
BLpython.TSregisterFunc(None, None, "PYreturnInt", PYreturnInt, int, "help text", 1, 1)
BLpython.TSregisterFunc(None, None, "PYreturnFloat", PYreturnFloat, float, "help text", 1, 1)
BLpython.TSregisterFunc(None, None, "PYreturnBool", PYreturnBool, bool, "help text", 1, 1)

Loop through rootGroup and print each object name:

import BLpython

try:
	iterator = BLpython.SimSetLooper(BLpython.TSfindObj("rootGroup"))
	BLpython.BlPrint("rootGroup children:")
	for obj in iterator:
		name=BLpython.TScallSimObj(obj, 'getName')
		name="("+ str(name) +")"
		BLpython.BlPrint("    "+ str(obj) +" = "+ name)
except:
	type, value, traceback = sys.exc_info()
	BLpython.BlPrint('Exception: '+ str(value))