Module scute.function

Expand source code Browse git
from uuid import uuid4

from scute import pack, _function_namespaces
from scute.internal.dict_to_NBT import dict_to_NBT
from scute.data_sources import DataSource, _NbtSource
from inspect import signature

from scute.internal.utils import format_text, create_function


class _MacroArguments:
    """
    The class instance passed to a function that has been declared with arguments (a macro). Accessing any property will return a `_MacroArg` instance which can be passed into any command
    """

    def __getattr__(self, item):
        return _MacroArg(item)


class _MacroArg:
    def __init__(self, item):
        """
        An internal class returned from `_MacroArguments` which can be passed into any command
        """
        self.arg: str = f"$({item})"

    def __str__(self):
        return self.arg


def func(function_namespace=None, function_name=None):
    """
    A decorator that creates a function in your datapack. You can provide an optional namespace and name,
    or it will default to your main namespace and a randomised name.
    Args:
        function_namespace: The namespace your function should go under
        function_name: The name of your function

    .. include:: ../pdoc/documentation/functions.md
    """

    def decorator(function):
        if function not in _function_namespaces:
            sig = signature(function)
            if len(sig.parameters) > 0:
                function(_MacroArguments())
            else:
                function()
            name = function_name or uuid4()
            space = function_namespace or pack.namespace

            _function_namespaces[function] = f"{space}:{name}"

            create_function(space, name, pack._command_stack)

            pack._command_stack = []

            print(format_text(f"Created function {space}:{name}", 32))

        # Code run if the function is called
        def wrapper(args: dict | _NbtSource = None, path=None):
            command = f"function {_function_namespaces[function]}"
            if isinstance(args, dict):
                command += " " + dict_to_NBT(args)
                if path is not None:
                    print(
                        "Warning: Macro argument path should not be specified when using hardcoded nbt."
                    )
            elif issubclass(type(args), DataSource):
                command += f" with {args.str} {path}"
            pack._command_stack.append(command + "\n")

        wrapper.unwrapped = function

        return wrapper

    return decorator

Functions

def func(function_namespace=None, function_name=None)

A decorator that creates a function in your datapack. You can provide an optional namespace and name, or it will default to your main namespace and a randomised name.

Args

function_namespace
The namespace your function should go under
function_name
The name of your function

Usage

Define a function, and wrap it with @func().

from scute.function import func
from scute.commands import give
from scute.items import Item

@func()
def myFunction():
    give("@s", Item.egg)

This function will be created with a uuid as its name, under the namespace specified in scute.pack.setMainNamespace

Alternatively, specify a namespace and function name.

@func("my_datapack", "function1")
def myFunction():
    give("@s", Item.egg)

To reference this function from other functions in your project, call it like you would any other function.

@func()
def myOtherFunction():
    myFunction()

Macros

To define a macro function (1.20.2+), give your function an argument. This represents the nbt compound that is passed in.

@func()
def myFunction(args):
    give("@s", args.item)

To call this function, just pass in some arguments.

from scute.items import nbt, Item
from scute.data_sources import Storage

myStorage = Storage("my_namespace")


@func()
def myOtherFunction():
    myFunction(nbt(item="minecraft:egg"))
    # or
    myFunction({"item": "minecraft:egg"})
    # or
    myFunction(nbt(item=Item.egg))
    # or
    myFunction(myStorage)
    # or
    myFunction(myStorage, "path.to.the.compound.i.want.to.use")
Expand source code Browse git
def func(function_namespace=None, function_name=None):
    """
    A decorator that creates a function in your datapack. You can provide an optional namespace and name,
    or it will default to your main namespace and a randomised name.
    Args:
        function_namespace: The namespace your function should go under
        function_name: The name of your function

    .. include:: ../pdoc/documentation/functions.md
    """

    def decorator(function):
        if function not in _function_namespaces:
            sig = signature(function)
            if len(sig.parameters) > 0:
                function(_MacroArguments())
            else:
                function()
            name = function_name or uuid4()
            space = function_namespace or pack.namespace

            _function_namespaces[function] = f"{space}:{name}"

            create_function(space, name, pack._command_stack)

            pack._command_stack = []

            print(format_text(f"Created function {space}:{name}", 32))

        # Code run if the function is called
        def wrapper(args: dict | _NbtSource = None, path=None):
            command = f"function {_function_namespaces[function]}"
            if isinstance(args, dict):
                command += " " + dict_to_NBT(args)
                if path is not None:
                    print(
                        "Warning: Macro argument path should not be specified when using hardcoded nbt."
                    )
            elif issubclass(type(args), DataSource):
                command += f" with {args.str} {path}"
            pack._command_stack.append(command + "\n")

        wrapper.unwrapped = function

        return wrapper

    return decorator