Source code for bedrock.utils

from __future__ import annotations

from collections.abc import Iterable, Mapping
from enum import Enum
import json
from typing import Literal, NewType

from attrs import define


[docs]def rawtext( text: str | Iterable[ Mapping[Literal["text", "selector", "translate"], str] | Mapping[Literal["score"], Mapping[Literal["name", "objective"], str]] ] ) -> str: """ Wraps text inside a rawtext JSON object which can be used for ``/tellraw``, ``/titleraw`` etc. .. seealso:: https://wiki.bedrock.dev/commands/tellraw.html Parameters ---------- text Either just a string or an iterable of mappings beeing valid rawtext parts. Examples -------- .. code-block:: python >>> from bedrock.utils import rawtext >>> rawtext('Hello World') '{"rawtext": [{"text": "Hello World"}]}' >>> rawtext([{'text': 'Hello '}, {'selector': '@p[r=10]'}]) '{"rawtext": [{"text": "Hello "}, {"selectors": "@p[r=10]}]}' """ if isinstance(text, str): return json.dumps({"rawtext": [{"text": text}]}) else: return json.dumps({"rawtext": text})
[docs]class TargetSelector(str, Enum): """ A collection of target selectors that can be used within commands. .. seealso:: https://minecraft.wiki/w/Target_selectors """ NEAREST_PLAYER = "@p" RANDOM_PLAYER = "@r" ALL_PLAYERS = "@a" ALL_ENTITIES = "@e" SELF = "@s" PLAYER_AGENT = "@c" ALL_AGENTS = "@v" INITIATOR = "@initiator"
[docs]@define class WorldCoordinate: """ A class representing a world coordinate. """ coord: float is_relative: bool = False def __str__(self) -> str: return f"{'~' if self.is_relative else ''}{self.coord}"
[docs] @classmethod def from_string(cls, value: str) -> WorldCoordinate: """Parses a world coordinate. Parameters ---------- value The coordinate to parse. Examples -------- .. code-block:: python from bedrock.utils import WorldCoordinate, WorldCoordinates x = WorldCoordinate.from_string("17") y = WorldCoordinate.from_string("~27") z = WorldCoordinate.from_string("~-27.4928") goto = WorldCoordinates((x, y, z)) """ n = value.removeprefix("~") return cls(numeric(n), is_relative=len(n) != len(value))
[docs]@define class LocalCoordinate: """ A class representing a local coordinate. """ coord: float def __str__(self) -> str: return f"^{self.coord}"
[docs] @classmethod def from_string(cls, value: str) -> LocalCoordinate: """Parses a local coordinate. Parameters ---------- value The coordinate to parse. Examples -------- .. code-block:: python from bedrock.utils import LocalCoordinate, LocalCoordinates x = LocalCoordinate.from_string("^1") y = LocalCoordinate.from_string("^-19.5752") z = LocalCoordinate.from_string("^0") goto = LocalCoordinates((x, y, z)) """ n = value.removeprefix("^") if len(n) != len(value): raise ValueError("local coordinate must start with a caret (^)") return cls(numeric(n))
WorldCoordinates = NewType( "WorldCoordinates", tuple[WorldCoordinate, WorldCoordinate, WorldCoordinate] ) LocalCoordinates = NewType( "LocalCoordinates", tuple[LocalCoordinate, LocalCoordinate, LocalCoordinate] )
[docs]def boolean(value: str) -> bool: """Converts a string into a boolean. Parameters ---------- value The string to convert into a boolean. * ``'y'``/``'yes'``/``'true'`` \N{RIGHTWARDS DOUBLE ARROW} ``True`` * ``'n'``/``'no'``/``'false'`` \N{RIGHTWARDS DOUBLE ARROW} ``False`` .. note:: The string is converted into lower case before comparing. That means that ``'TRUe'`` results in ``True`` as well. Examples -------- .. code-block:: python >>> from bedrock.utils import boolean >>> boolean("y") True >>> boolean("yes") True >>> boolean("true") True >>> boolean("trUE") True >>> boolean("1") Traceback (most recent call last): File "<stdin>", line 1 in <module> ValueError: cannot turn '1' into a boolean >>> boolean("n") False >>> boolean("NO") False >>> boolean("False") False >>> Raises ------ ValueError The string cannot be converted into a boolean. """ if value.lower() in {"y", "yes", "true"}: return True elif value.lower() in {"n", "no", "false"}: return False raise ValueError(f"cannot turn {value!r} into a boolean")
[docs]def numeric(value: str) -> float: """ Converts a string into an integer or if that fails into a floating point. The major reason to use this instead of :external+python:class:`float` is for usage within game commands such as ``teleport`` where an integer coordinate like ``42`` is parsed as ``42.50`` whereas floating points are interpreted as is so that ``21.0`` means ``21.0``. You may override this behaviour by overriding this function which affects the parsing of :meth:`WorldCoordinate.from_string` and :meth:`LocalCoordinate.from_string`: .. code-block:: python from bedrock import utils utils.numeric = float Parameters ---------- value The string to converr into a numeric. Examples -------- .. code-block:: python >>> from bedrock.utils import numeric >>> numeric("10") 10 >>> numeric("10.500") 10.5 >>> Raises ------ ValueError The string cannot be converted into a boolean. """ try: return int(value) except ValueError: try: return float(value) except ValueError as e: raise e from None