location_api 源代码

"""Location API for storing and manipulating Minecraft coordinates and locations.

This module provides a set of dataclasses to represent points in 2D and 3D space,
Minecraft positions (point + dimension), and named locations with metadata.
"""

from dataclasses import dataclass, fields
from typing import Self

from beartype import beartype
from primitive_type import (
    PrimitiveMap,
    get_str_object,
    get_float_object,
    is_nested_dict,
)


[文档] @dataclass @beartype class Point3D: """Define a 3D point with x, y, z coordinates. This class represents a point in 3D space with x, y, and z coordinates. It uses floating-point precision for coordinate values. """ x: float """The x-coordinate of the point. """ y: float """The y-coordinate of the point. """ z: float """The z-coordinate of the point. """ def __str__(self) -> str: return "[{}, {}, {}]".format(self.x, self.y, self.z)
[文档] def distance_to(self, point: Self) -> float: """Calculate the Euclidean distance between this point and another point. :param point: The other 3D point to calculate the distance to. :return: The Euclidean distance between this point and another point. """ return ( (self.x - point.x) ** 2 + (self.y - point.y) ** 2 + (self.z - point.z) ** 2 ) ** 0.5
[文档] def distance2d_to(self, point: "Point3D | Point2D") -> float: """Calculate the 2D Euclidean distance between this point and another point. :param point: The other 2D or 3D point to calculate the distance to. :return: The 2D Euclidean distance between this point and another point. """ return ((self.x - point.x) ** 2 + (self.z - point.z) ** 2) ** 0.5
[文档] def height_to(self, point: Self) -> float: """Calculate the height difference between this point and another point. :param point: The other 3D point to calculate the height difference to. :return: The height difference between this point and another point. """ return abs(self.y - point.y)
[文档] @classmethod def from_point2d(cls, point: "Point2D", y: float) -> Self: """Create a 3D point from a 2D point and a height as y coordinate. :param point: The 2D point to create a 3D point from. :param y: The height of the 3D point. :return: The 3D point instance. """ return cls(x=point.x, y=y, z=point.z)
[文档] def to_point2d(self) -> "Point2D": """Create a 2D point from a 3D point. :return: The 2D point instance. """ return Point2D(x=self.x, z=self.z)
[文档] @dataclass @beartype class Point2D: """Define a 2D point with x and z coordinates. This class represents a point in 2D space with x and z coordinates. It uses floating-point precision for coordinate values. """ x: float """The x-coordinate of the point. """ z: float """The z-coordinate of the point. """ def __str__(self) -> str: return "[{}, {}]".format(self.x, self.z)
[文档] def distance_to(self, point: Self) -> float: """Calculate the Euclidean distance between this point and another point. :param point: The other 2D point to calculate the distance to. :return: The Euclidean distance between this point and another point. """ return ((self.x - point.x) ** 2 + (self.z - point.z) ** 2) ** 0.5
[文档] def distance2d_to(self, point: "Point2D | Point3D") -> float: """Calculate the 2D Euclidean distance between this point and another point. :param point: The other 2D or 3D point to calculate the distance to. :return: The 2D Euclidean distance between this point and another point. """ return ((self.x - point.x) ** 2 + (self.z - point.z) ** 2) ** 0.5
[文档] @classmethod def from_point3d(cls, point: "Point3D") -> Self: """Create a 2D point from a 3D point. :param point: The 3D point to create a 2D point from. :return: The 2D point instance. """ return cls(x=point.x, z=point.z)
[文档] def to_point3d(self, y: float) -> "Point3D": """Create a 3d point from a 2d point and a height as y coordinate. :param y: The height of the 3d point. :return: The 3d point instance. """ return Point3D(x=self.x, y=y, z=self.z)
[文档] @dataclass class MCPosition: """Define a Minecraft position with a 3D point and a dimension. This class represents a position in Minecraft with a 3D point and a dimension. It uses floating-point precision for coordinate values. """ point: "Point3D" """The 3D point of the position. """ dimension: str # e.g. minecraft:overworld """The dimension string of the position. """ @property def x(self) -> float: """The x coordinate of the position.""" return self.point.x @property def y(self) -> float: """The y coordinate of the position.""" return self.point.y @property def z(self) -> float: """The z coordinate of the position.""" return self.point.z def __str__(self) -> str: field_names = [f.name for f in fields(self)] values = [f"{_name}={getattr(self, _name)}" for _name in field_names] return f"{self.__class__.__name__}({', '.join(values)})"
[文档] def asdict(self) -> dict: """Serialize :data:`MCPosition` object into a dict. :returns: The serialized dict. """ return { "x": self.x, "y": self.y, "z": self.z, "dimension": self.dimension, }
[文档] @classmethod def from_dict(cls, data: dict) -> Self: """Deserialize :data:`MCPosition` object from a dict. :param data: The dict to deserialize. :returns: The deserialized :data:`MCPosition` object. """ dimension = get_str_object( data.get("dimension", data.get("dim", None)) ) # check data for k, v in data.items(): if any(item in k for item in ["x", "y", "z"]) and "point" in k: raise TypeError("Invalid data: exists both coords and point!") point = data.get("point", None) if point: x = get_float_object(point.get("x")) y = get_float_object(point.get("y")) z = get_float_object(point.get("z")) else: x = get_float_object(data.get("x")) y = get_float_object(data.get("y")) z = get_float_object(data.get("z")) return cls(point=Point3D(x, y, z), dimension=dimension)
[文档] @dataclass class Location: """Define a location with a name, description, and other fields. This class represents a location in Minecraft with a name, description, and other fields. It uses floating-point precision for coordinate values. """ position: "MCPosition" """The position data of the location. """ name: str """The name of the location. """ description: str | None = None """The description of the location. """ other: PrimitiveMap | None = None """Other informations about the location. """ @property def x(self) -> float: """The x-coordinate of the location.""" return self.position.x @property def y(self) -> float: """The y-coordinate of the location.""" return self.position.y @property def z(self) -> float: """The z-coordinate of the location.""" return self.position.z @property def dimension(self) -> str: """The dimension of the location.""" return self.position.dimension def __post_init__(self): if self.other: if is_nested_dict(self.other): raise TypeError( "Nested structures are not allowed in other field." ) def __str__(self): field_names = [f.name for f in fields(self)] values = [f"{_name}={getattr(self, _name)}" for _name in field_names] return f"{self.__class__.__name__}({', '.join(values)})"
[文档] def asdict(self) -> dict: """Serialize :data:`Location` object into a dict. :returns: The serialized dict. """ return { "x": self.x, "y": self.y, "z": self.z, "dimension": self.dimension, "name": self.name, "description": self.description, "other": self.other, }
[文档] @classmethod def from_dict(cls, data: dict) -> Self: """Deserialize :data:`Location` object from a dict. :param data: The dict to deserialize. :returns: The deserialized :data:`Location` object. """ # check data for k, v in data.items(): if any(item in k for item in ["x", "y", "z"]) and "point" in k: raise TypeError( "Invalid data: exists both coords and position!" ) position = data.get("position", None) if position: position = MCPosition.from_dict(position) x = position.x y = position.y z = position.z dimension = position.dimension else: x = get_float_object(data.get("x")) y = get_float_object(data.get("y")) z = get_float_object(data.get("z")) dimension = data.get("dimension", data.get("dim", None)) if dimension: dimension = get_str_object(dimension) name = get_str_object(data.get("name")) description = data.get("description", data.get("desc", None)) if description: description = get_str_object(description) other = data.get("other", None) if other: if not is_nested_dict(other): raise TypeError( "Nested structures are not allowed in other field." ) return cls( MCPosition(Point3D(x, y, z), dimension), name, description, other )
# if __name__ == "__main__":