diff --git a/docs/reference/python/debug_shape.md b/docs/reference/python/debug_shape.md new file mode 100644 index 0000000000..82905c3e2b --- /dev/null +++ b/docs/reference/python/debug_shape.md @@ -0,0 +1 @@ +::: endstone.debug_shape \ No newline at end of file diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index 4bc05db47a..fba97d79a2 100644 --- a/endstone/_internal/endstone_python.pyi +++ b/endstone/_internal/endstone_python.pyi @@ -4,7 +4,7 @@ import numpy import os import typing import uuid -__all__ = ['ActionForm', 'Actor', 'ActorDamageEvent', 'ActorDeathEvent', 'ActorEvent', 'ActorExplodeEvent', 'ActorKnockbackEvent', 'ActorRemoveEvent', 'ActorSpawnEvent', 'ActorTeleportEvent', 'BanEntry', 'BarColor', 'BarFlag', 'BarStyle', 'Block', 'BlockBreakEvent', 'BlockCommandSender', 'BlockCookEvent', 'BlockData', 'BlockEvent', 'BlockFace', 'BlockPistonEvent', 'BlockPistonExtendEvent', 'BlockPistonRetractEvent', 'BlockPlaceEvent', 'BlockState', 'BossBar', 'BroadcastMessageEvent', 'Button', 'Cancellable', 'Chunk', 'ChunkEvent', 'ChunkLoadEvent', 'ChunkUnloadEvent', 'ColorFormat', 'Command', 'CommandExecutor', 'CommandSender', 'CommandSenderWrapper', 'ConsoleCommandSender', 'Criteria', 'DamageSource', 'Dimension', 'DimensionEvent', 'DisplaySlot', 'Divider', 'Dropdown', 'Enchantment', 'EnchantmentRegistry', 'EquipmentSlot', 'Event', 'EventPriority', 'EventResult', 'GameMode', 'Header', 'Inventory', 'IpBanEntry', 'IpBanList', 'Item', 'ItemFactory', 'ItemMeta', 'ItemRegistry', 'ItemStack', 'ItemType', 'Label', 'Language', 'LeavesDecayEvent', 'Level', 'LevelEvent', 'Location', 'Logger', 'MapCanvas', 'MapMeta', 'MapRenderer', 'MapView', 'MessageForm', 'Mob', 'MobEvent', 'ModalForm', 'Objective', 'ObjectiveSortOrder', 'OfflinePlayer', 'PacketReceiveEvent', 'PacketSendEvent', 'Permissible', 'Permission', 'PermissionAttachment', 'PermissionAttachmentInfo', 'PermissionDefault', 'PermissionLevel', 'Player', 'PlayerBanEntry', 'PlayerBanList', 'PlayerBedEnterEvent', 'PlayerBedLeaveEvent', 'PlayerChatEvent', 'PlayerCommandEvent', 'PlayerDeathEvent', 'PlayerDropItemEvent', 'PlayerEmoteEvent', 'PlayerEvent', 'PlayerGameModeChangeEvent', 'PlayerInteractActorEvent', 'PlayerInteractEvent', 'PlayerInventory', 'PlayerItemConsumeEvent', 'PlayerItemHeldEvent', 'PlayerJoinEvent', 'PlayerJumpEvent', 'PlayerKickEvent', 'PlayerLoginEvent', 'PlayerMoveEvent', 'PlayerPickupItemEvent', 'PlayerQuitEvent', 'PlayerRespawnEvent', 'PlayerSkinChangeEvent', 'PlayerTeleportEvent', 'Plugin', 'PluginCommand', 'PluginDescription', 'PluginDisableEvent', 'PluginEnableEvent', 'PluginLoadOrder', 'PluginLoader', 'PluginManager', 'Position', 'RenderType', 'Scheduler', 'Score', 'Scoreboard', 'ScriptMessageEvent', 'Server', 'ServerCommandEvent', 'ServerEvent', 'ServerListPingEvent', 'ServerLoadEvent', 'Service', 'ServiceManager', 'ServicePriority', 'Skin', 'Slider', 'SocketAddress', 'StepSlider', 'Task', 'TextInput', 'ThunderChangeEvent', 'Toggle', 'Translatable', 'Vector', 'WeatherChangeEvent', 'WeatherEvent'] +__all__ = ['ActionForm', 'Actor', 'ActorDamageEvent', 'ActorDeathEvent', 'ActorEvent', 'ActorExplodeEvent', 'ActorKnockbackEvent', 'ActorRemoveEvent', 'ActorSpawnEvent', 'ActorTeleportEvent', 'BanEntry', 'BarColor', 'BarFlag', 'BarStyle', 'Block', 'BlockBreakEvent', 'BlockCommandSender', 'BlockCookEvent', 'BlockData', 'BlockEvent', 'BlockFace', 'BlockPistonEvent', 'BlockPistonExtendEvent', 'BlockPistonRetractEvent', 'BlockPlaceEvent', 'BlockState', 'BossBar', 'BroadcastMessageEvent', 'Button', 'Cancellable', 'Chunk', 'ChunkEvent', 'ChunkLoadEvent', 'ChunkUnloadEvent', 'ColorFormat', 'Command', 'CommandExecutor', 'CommandSender', 'CommandSenderWrapper', 'ConsoleCommandSender', 'Criteria', 'DamageSource', 'DebugArrow', 'DebugBox', 'DebugCircle', 'DebugLine', 'DebugSphere', 'DebugText', 'Dimension', 'DimensionEvent', 'DisplaySlot', 'Divider', 'Dropdown', 'Enchantment', 'EnchantmentRegistry', 'EquipmentSlot', 'Event', 'EventPriority', 'EventResult', 'GameMode', 'Header', 'Inventory', 'IpBanEntry', 'IpBanList', 'Item', 'ItemFactory', 'ItemMeta', 'ItemRegistry', 'ItemStack', 'ItemType', 'Label', 'Language', 'LeavesDecayEvent', 'Level', 'LevelEvent', 'Location', 'Logger', 'MapCanvas', 'MapMeta', 'MapRenderer', 'MapView', 'MessageForm', 'Mob', 'MobEvent', 'ModalForm', 'Objective', 'ObjectiveSortOrder', 'OfflinePlayer', 'PacketReceiveEvent', 'PacketSendEvent', 'Permissible', 'Permission', 'PermissionAttachment', 'PermissionAttachmentInfo', 'PermissionDefault', 'PermissionLevel', 'Player', 'PlayerBanEntry', 'PlayerBanList', 'PlayerBedEnterEvent', 'PlayerBedLeaveEvent', 'PlayerChatEvent', 'PlayerCommandEvent', 'PlayerDeathEvent', 'PlayerDropItemEvent', 'PlayerEmoteEvent', 'PlayerEvent', 'PlayerGameModeChangeEvent', 'PlayerInteractActorEvent', 'PlayerInteractEvent', 'PlayerInventory', 'PlayerItemConsumeEvent', 'PlayerItemHeldEvent', 'PlayerJoinEvent', 'PlayerJumpEvent', 'PlayerKickEvent', 'PlayerLoginEvent', 'PlayerMoveEvent', 'PlayerPickupItemEvent', 'PlayerQuitEvent', 'PlayerRespawnEvent', 'PlayerSkinChangeEvent', 'PlayerTeleportEvent', 'Plugin', 'PluginCommand', 'PluginDescription', 'PluginDisableEvent', 'PluginEnableEvent', 'PluginLoadOrder', 'PluginLoader', 'PluginManager', 'Position', 'RenderType', 'Scheduler', 'Score', 'Scoreboard', 'ScriptMessageEvent', 'Server', 'ServerCommandEvent', 'ServerEvent', 'ServerListPingEvent', 'ServerLoadEvent', 'Service', 'ServiceManager', 'ServicePriority', 'Skin', 'Slider', 'SocketAddress', 'StepSlider', 'Task', 'TextInput', 'ThunderChangeEvent', 'Toggle', 'Translatable', 'Vector', 'WeatherChangeEvent', 'WeatherEvent'] class ActionForm: """ Represents a form with buttons that let the player take action. @@ -1099,6 +1099,398 @@ class DamageSource: """ Get the damage type. """ +class DebugArrow: + """ + Represents a debug arrow. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def arrow_head_length(self) -> float | None: + """ + Gets or sets the length of the arrowhead. + """ + @arrow_head_length.setter + def arrow_head_length(self, arg1: float | None) -> DebugArrow: + ... + @property + def arrow_head_radius(self) -> float | None: + """ + Gets or sets the radius of the arrowhead. + """ + @arrow_head_radius.setter + def arrow_head_radius(self, arg1: float | None) -> DebugArrow: + ... + @property + def arrow_head_scale(self) -> float | None: + """ + Gets or sets the scale of the arrowhead. + """ + @arrow_head_scale.setter + def arrow_head_scale(self, arg1: float | None) -> DebugArrow: + ... + @property + def arrow_head_segments(self) -> int | None: + """ + Gets or sets the number of segments used to render the arrowhead. + """ + @arrow_head_segments.setter + def arrow_head_segments(self, arg1: int | None) -> DebugArrow: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugArrow: + ... + @property + def end_position(self) -> Vector | None: + """ + Gets or sets the end position of the arrow. + """ + @end_position.setter + def end_position(self, arg1: Vector | None) -> DebugArrow: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugArrow: + ... +class DebugBox: + """ + Represents a debug box. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def box_bounds(self) -> Vector | None: + """ + Gets or sets the bounds of the box. + """ + @box_bounds.setter + def box_bounds(self, arg1: Vector | None) -> DebugBox: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugBox: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugBox: + ... + @property + def scale(self) -> float | None: + """ + Gets or sets the scale of the box. + """ + @scale.setter + def scale(self, arg1: float | None) -> DebugBox: + ... +class DebugCircle: + """ + Represents a debug circle. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugCircle: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugCircle: + ... + @property + def scale(self) -> float | None: + """ + Gets or sets the scale of the circle. + """ + @scale.setter + def scale(self, arg1: float | None) -> DebugCircle: + ... + @property + def segments(self) -> int | None: + """ + Gets or sets the number of segments used to render the circle. + """ + @segments.setter + def segments(self, arg1: int | None) -> DebugCircle: + ... +class DebugLine: + """ + Represents a debug line. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugLine: + ... + @property + def end_position(self) -> Vector | None: + """ + Gets or sets the end position of the line. + """ + @end_position.setter + def end_position(self, arg1: Vector | None) -> DebugLine: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugLine: + ... +class DebugSphere: + """ + Represents a debug sphere. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugSphere: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugSphere: + ... + @property + def scale(self) -> float | None: + """ + Gets or sets the scale of the sphere. + """ + @scale.setter + def scale(self, arg1: float | None) -> DebugSphere: + ... + @property + def segments(self) -> int | None: + """ + Gets or sets the number of segments used to render the sphere. + """ + @segments.setter + def segments(self, arg1: int | None) -> DebugSphere: + ... +class DebugText: + """ + Represents a debug text. + """ + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self) -> None: + ... + def add_player(self, player: Player) -> None: + """ + Adds a player to this debug shape causing it to display on the player's screen. + """ + def remove_all(self) -> None: + """ + Removes all players from this debug shape. + """ + def remove_player(self, player: Player) -> None: + """ + Removes a player from this debug shape causing it to be removed from the player's screen. + """ + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug shape. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugText: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug shape. + """ + @property + def players(self) -> list[Player]: + """ + Gets the players of the debug shape. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug shape. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugText: + ... + @property + def text(self) -> str: + """ + Gets or sets the text of the debug text. + """ + @text.setter + def text(self, arg1: str) -> DebugText: + ... class Dimension: """ Represents a dimension within a Level. @@ -2878,10 +3270,26 @@ class Player(Mob, OfflinePlayer): """ Play a sound for a player at the location. """ + def remove_debug_shape(self, debug_shape: DebugArrow | DebugBox | DebugCircle | DebugLine | DebugSphere | DebugText) -> None: + """ + Removes a debug shape from the player. + """ + def remove_debug_shapes(self, debug_shapes: list[DebugArrow | DebugBox | DebugCircle | DebugLine | DebugSphere | DebugText]) -> None: + """ + Removes a number of debug shapes from the player. + """ def reset_title(self) -> None: """ Resets the title displayed to the player. This will clear the displayed title / subtitle and reset timings to their default values. """ + def send_debug_shape(self, debug_shape: DebugArrow | DebugBox | DebugCircle | DebugLine | DebugSphere | DebugText) -> None: + """ + Sends a debug shape to the player. + """ + def send_debug_shapes(self, debug_shapes: list[DebugArrow | DebugBox | DebugCircle | DebugLine | DebugSphere | DebugText]) -> None: + """ + Sends a number of debug shapes to the player. + """ def send_form(self, form: MessageForm | ActionForm | ModalForm) -> None: """ Sends a form to the player. diff --git a/endstone/debugshape.py b/endstone/debugshape.py new file mode 100644 index 0000000000..17acc6ee5f --- /dev/null +++ b/endstone/debugshape.py @@ -0,0 +1,17 @@ +from endstone._internal.endstone_python import ( + DebugArrow, + DebugBox, + DebugCircle, + DebugLine, + DebugSphere, + DebugText, +) + +__all__ = [ + "DebugArrow", + "DebugBox", + "DebugCircle", + "DebugLine", + "DebugSphere", + "DebugText", +] diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h new file mode 100644 index 0000000000..827cdc191f --- /dev/null +++ b/include/endstone/debugshape/debug_arrow.h @@ -0,0 +1,149 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + +/** + * @brief Represents a debug arrow. + */ +class DebugArrow : public DebugShape { +public: + /** + * @brief Gets the end position of the arrow. + * + * @return The end position of the arrow. + */ + [[nodiscard]] std::optional> getEndPosition() const + { + return end_position_; + } + + /** + * @brief Sets the end position of the arrow. + * + * @param end_position The desired end position of the arrow + * @return A reference to the current debug shape. + */ + DebugArrow &setEndPosition(const std::optional> end_position) + { + end_position_ = end_position; + onChange(); + return *this; + } + + /** + * @brief Gets the length of the arrowhead. + * + * @return The arrowhead length. + */ + [[nodiscard]] std::optional getArrowHeadLength() const + { + return arrow_head_length_; + } + + /** + * @brief Sets the length of the arrowhead. + * + * @param arrow_head_length The desired length of the arrowhead. + * @return A reference to the current debug shape. + */ + DebugArrow &setArrowHeadLength(const std::optional arrow_head_length) + { + arrow_head_length_ = arrow_head_length; + onChange(); + return *this; + } + + /** + * @brief Gets the radius of the arrowhead. + * + * @return The arrowhead radius. + */ + [[nodiscard]] std::optional getArrowHeadRadius() const + { + return arrow_head_radius_; + } + + /** + * @brief Sets the radius of the arrowhead. + * + * @param arrow_head_radius The desired radius of the arrowhead. + * @return A reference to the current debug shape. + */ + DebugArrow &setArrowHeadRadius(const std::optional arrow_head_radius) + { + arrow_head_radius_ = arrow_head_radius; + onChange(); + return *this; + } + + /** + * @brief Gets the number of segments used to render the arrowhead. + * + * @return The number of arrowhead segments. + */ + [[nodiscard]] std::optional getArrowHeadSegments() const + { + return arrow_head_segments_; + } + + /** + * @brief Sets the number of segments used to render the arrowhead. + * + * @param arrow_head_segments The desired number of segments. + * @return A reference to the current debug shape. + */ + DebugArrow &setArrowHeadSegments(const std::optional arrow_head_segments) + { + arrow_head_segments_ = arrow_head_segments; + onChange(); + return *this; + } + + /** + * @brief Gets the scale of the arrowhead. + * + * @return The arrowhead scale. + */ + [[nodiscard]] std::optional getArrowHeadScale() const + { + return arrow_head_scale_; + } + + /** + * @brief Sets the scale of the arrowhead. + * + * @param arrow_head_scale The desired scale of the arrowhead. + * @return A reference to the current debug shape. + */ + DebugArrow &setArrowHeadScale(const std::optional arrow_head_scale) + { + arrow_head_scale_ = arrow_head_scale; + onChange(); + return *this; + } + +private: + std::optional> end_position_; + std::optional arrow_head_length_; + std::optional arrow_head_radius_; + std::optional arrow_head_segments_; + std::optional arrow_head_scale_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_box.h b/include/endstone/debugshape/debug_box.h new file mode 100644 index 0000000000..f1be9e56af --- /dev/null +++ b/include/endstone/debugshape/debug_box.h @@ -0,0 +1,77 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + +/** + * @brief Represents a debug box. + */ +class DebugBox : public DebugShape { +public: + /** + * @brief Gets the scale of the box. + * + * @return The scale of the box. + */ + [[nodiscard]] std::optional getScale() const + { + return scale_; + } + + /** + * @brief Sets the scale of the box. + * + * @param scale The desired scale of the box. + * @return A reference to the current debug shape. + */ + DebugBox &setScale(const std::optional scale) + { + scale_ = scale; + onChange(); + return *this; + } + + /** + * @brief Gets the bounds of the box. + * + * @return The bounds of the box. + */ + [[nodiscard]] std::optional> getBoxBounds() const + { + return box_bounds_; + } + + /** + * @brief Sets the bounds of the box. + * + * @param box_bounds The desired bounds of the box. + * @return A reference to the current debug shape. + */ + DebugBox &setBoxBounds(const std::optional> box_bounds) + { + box_bounds_ = box_bounds; + onChange(); + return *this; + } + +private: + std::optional scale_; + std::optional> box_bounds_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_circle.h b/include/endstone/debugshape/debug_circle.h new file mode 100644 index 0000000000..c45710ee2a --- /dev/null +++ b/include/endstone/debugshape/debug_circle.h @@ -0,0 +1,78 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + + +/** + * @brief Represents a debug circle. + */ +class DebugCircle : public DebugShape { +public: + /** + * @brief Gets the scale of the circle. + * + * @return The scale of the circle. + */ + [[nodiscard]] std::optional getScale() const + { + return scale_; + } + + /** + * @brief Sets the scale of the circle. + * + * @param scale The desired scale of the circle. + * @return A reference to the current debug shape. + */ + DebugCircle &setScale(const std::optional scale) + { + scale_ = scale; + onChange(); + return *this; + } + + /** + * @brief Gets the number of segments used to render the circle. + * + * @return The number of circle segments. + */ + [[nodiscard]] std::optional getSegments() const + { + return segments_; + } + + /** + * @brief Sets the number of segments used to render the circle. + * + * @param segments The desired number of segments. + * @return A reference to the current debug shape. + */ + DebugCircle &setSegments(const std::optional segments) + { + segments_ = segments; + onChange(); + return *this; + } + +private: + std::optional scale_; + std::optional segments_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_line.h b/include/endstone/debugshape/debug_line.h new file mode 100644 index 0000000000..d9b5cecf7a --- /dev/null +++ b/include/endstone/debugshape/debug_line.h @@ -0,0 +1,53 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + +/** + * @brief Represents a debug line. + */ +class DebugLine : public DebugShape { +public: + /** + * @brief Gets the end position of the line. + * + * @return The end position of the line. + */ + [[nodiscard]] std::optional> getEndPosition() const + { + return end_position_; + } + + /** + * @brief Sets the end position of the line. + * + * @param end_position The desired end position of the line + * @return A reference to the current debug shape. + */ + DebugLine &setEndPosition(const std::optional> end_position) + { + end_position_ = end_position; + onChange(); + return *this; + } + +private: + std::optional> end_position_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_shape.h b/include/endstone/debugshape/debug_shape.h new file mode 100644 index 0000000000..f8f1b11e9d --- /dev/null +++ b/include/endstone/debugshape/debug_shape.h @@ -0,0 +1,170 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "endstone/detail/endstone.h" +#include "endstone/player.h" +#include "endstone/util/color.h" +#include "endstone/util/uuid.h" +#include "endstone/util/vector.h" + +namespace endstone { + +namespace debugshape_internal { +// Decreases from the maximum value to avoid conflicts with sapi's id allocation +inline std::atomic id_counter{UINT64_MAX}; +} // namespace debugshape_internal + +/** + * @brief Represents a generic debug shape. + * + * The DebugShape class provides a base abstraction for different types of debug shapes. + * It supports six types of debug shapes: Arrow, Box, Circle, Line, Sphere and Text. + * Each debug shape has an id, position and color. + */ +template +class DebugShape { +public: + using DebugShapeId = uint64_t; + explicit DebugShape() + { + id_ = --debugshape_internal::id_counter; + } + + /** + * @brief Gets the id of the debug shape. + * + * @return The id of the debug shape. + */ + [[nodiscard]] DebugShapeId getId() const + { + return id_; + } + + /** + * @brief Gets the position of the debug shape. + * + * @return The position of the debug shape. + */ + [[nodiscard]] std::optional> getPosition() const + { + return position_; + } + + /** + * @brief Sets the position of the debug shape. + * + * @param position The position to set for the debug shape. + * @return A reference to the current debug shape. + */ + T &setPosition(const std::optional> position) + { + position_ = position; + onChange(); + return *static_cast(this); + } + + /** + * @brief Gets the color of the debug shape. + * + * @return The color of the debug shape. + */ + [[nodiscard]] std::optional getColor() const + { + return color_; + } + + /** + * @brief Sets the color of the debug shape. + * + * @param color The color to set for the debug shape. + * @return A reference to the current debug shape. + */ + T &setColor(const std::optional color) + { + color_ = color; + onChange(); + return *static_cast(this); + } + + /** + * @brief Adds the player to this debug shape causing it to display on the player's screen. + * @param player the player to add. + */ + void addPlayer(Player &player) + { + players_.emplace(player.getUniqueId()); + player.sendDebugShape(static_cast(*this)); + } + + /** + * @brief Removes the player from this debug shape causing it to be removed from the player's screen. + * @param player the player to remove. + */ + void removePlayer(Player &player) + { + players_.erase(player.getUniqueId()); + player.removeDebugShape(static_cast(*this)); + } + + /** + * @brief Removes all players from this debug shape. + */ + void removeAll() + { + for (const auto &player : getPlayers()) { + removePlayer(*player); + } + } + + /** + * @brief Returns all players viewing this debug shape. + * @return a list of players. + */ + std::vector getPlayers() const + { + std::vector players; + const auto &server = Endstone::getServer(); + for (auto it = players_.begin(); it != players_.end();) { + if (auto *player = server.getPlayer(*it); player) { + players.emplace_back(player); + ++it; + } + else { + it = players_.erase(it); + } + } + return players; + } + +protected: + DebugShapeId id_; + std::optional> position_; + std::optional color_; + mutable std::unordered_set players_; + + void onChange() const + { + for (const auto &player : getPlayers()) { + player->sendDebugShape(static_cast(*this)); + } + } +}; + +} // namespace endstone diff --git a/include/endstone/debugshape/debug_sphere.h b/include/endstone/debugshape/debug_sphere.h new file mode 100644 index 0000000000..29b22bb6e4 --- /dev/null +++ b/include/endstone/debugshape/debug_sphere.h @@ -0,0 +1,77 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + +/** + * @brief Represents a debug sphere. + */ +class DebugSphere : public DebugShape { +public: + /** + * @brief Gets the scale of the sphere. + * + * @return The scale of the sphere. + */ + [[nodiscard]] std::optional getScale() const + { + return scale_; + } + + /** + * @brief Sets the scale of the sphere. + * + * @param scale The desired scale of the sphere. + * @return A reference to the current debug shape. + */ + DebugSphere &setScale(std::optional scale) + { + scale_ = scale; + onChange(); + return *this; + } + + /** + * @brief Gets the number of segments used to render the sphere. + * + * @return The number of sphere segments. + */ + [[nodiscard]] std::optional getSegments() const + { + return segments_; + } + + /** + * @brief Sets the number of segments used to render the sphere. + * + * @param segments The desired number of segments. + * @return A reference to the current debug shape. + */ + DebugSphere &setSegments(const std::optional segments) + { + segments_ = segments; + onChange(); + return *this; + } + +private: + std::optional scale_; + std::optional segments_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_text.h b/include/endstone/debugshape/debug_text.h new file mode 100644 index 0000000000..40f49ce037 --- /dev/null +++ b/include/endstone/debugshape/debug_text.h @@ -0,0 +1,55 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "endstone/debugshape/debug_shape.h" + +namespace endstone { + +/** + * @brief Represents a debug text. + */ +class DebugText : public DebugShape { +public: + /** + * @brief Gets the text of the debug text. + * + * @return The the text of the debug text. + */ + [[nodiscard]] std::string getText() const + { + return text_; + } + + /** + * @brief Sets the the text of the debug text. + * + * @param text The desired the text of the debug text. + * @return A reference to the current debug shape. + */ + DebugText &setText(const std::string &text) + { + text_ = text; + onChange(); + return *this; + } + +private: + std::string text_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/endstone.hpp b/include/endstone/endstone.hpp index 0d905bb959..a0e15ae77a 100644 --- a/include/endstone/endstone.hpp +++ b/include/endstone/endstone.hpp @@ -125,6 +125,13 @@ static_assert(_ITERATOR_DEBUG_LEVEL == 0, #include "form/form.h" #include "form/message_form.h" #include "form/modal_form.h" +#include "debugshape/debug_arrow.h" +#include "debugshape/debug_box.h" +#include "debugshape/debug_circle.h" +#include "debugshape/debug_line.h" +#include "debugshape/debug_shape.h" +#include "debugshape/debug_sphere.h" +#include "debugshape/debug_text.h" #include "game_mode.h" #include "inventory/equipment_slot.h" #include "inventory/inventory.h" diff --git a/include/endstone/player.h b/include/endstone/player.h index 2e31b755c0..3a57818483 100644 --- a/include/endstone/player.h +++ b/include/endstone/player.h @@ -31,12 +31,20 @@ namespace endstone { +class DebugArrow; +class DebugBox; +class DebugCircle; +class DebugLine; +class DebugSphere; +class DebugText; + /** * @brief Represents a player. */ class Player : public Mob, public OfflinePlayer { protected: using FormVariant = std::variant; + using DebugShapeVariant = std::variant; public: /** @@ -460,6 +468,34 @@ class Player : public Mob, public OfflinePlayer { */ virtual void closeForm() = 0; + /** + * @brief Sends a debug shape to the player. + * + * @param debug_shape The debug shape to send + */ + virtual void sendDebugShape(DebugShapeVariant debug_shape) = 0; + + /** + * @brief Sends a number of debug shapes to the player. + * + * @param debug_shapes The debug shapes to send + */ + virtual void sendDebugShapes(std::vector debug_shapes) = 0; + + /** + * @brief Removes a debug shape from the player. + * + * @param debug_shape The debug shape to remove + */ + virtual void removeDebugShape(DebugShapeVariant debug_shape) = 0; + + /** + * @brief Removes a number of debug shapes from the player. + * + * @param debug_shapes The debug shapes to remove + */ + virtual void removeDebugShapes(std::vector debug_shapes) = 0; + /** * @brief Sends a packet to the player. * diff --git a/mkdocs.yml b/mkdocs.yml index 1e8d4736fb..024a0822bd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -209,6 +209,7 @@ nav: - Boss: reference/python/boss.md - Command: reference/python/command.md - Damage: reference/python/damage.md + - Debug Shape: reference/python/debug_shape.md - Enchantments: reference/python/enchantments.md - Event: reference/python/event.md - Form: reference/python/form.md diff --git a/src/bedrock/network/packet/server_script_debug_drawer_packet.h b/src/bedrock/network/packet/server_script_debug_drawer_packet.h new file mode 100644 index 0000000000..48f96d4186 --- /dev/null +++ b/src/bedrock/network/packet/server_script_debug_drawer_packet.h @@ -0,0 +1,52 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "bedrock/core/math/color.h" +#include "bedrock/core/math/vec3.h" +#include "bedrock/network/packet.h" + +namespace ScriptModuleDebugUtilities { +enum class ScriptDebugShapeType : std::uint8_t { + Line = 0, + Box = 1, + Sphere = 2, + Circle = 3, + Text = 4, + Arrow = 5, + NumShapeTypes = 6, +}; + +struct PacketShapeData { + std::uint64_t network_id; + std::optional shape_type; + std::optional location; + std::optional rotation; + std::optional scale; + std::optional color; + std::optional time_left_total_sec; + std::optional text; + std::optional box_bound; + std::optional end_location; + std::optional arrow_head_length; + std::optional arrow_head_radius; + std::optional num_segments; +}; + +class ServerScriptDebugDrawerPacket : public Packet { +public: + std::vector shapes; +}; +} // namespace ScriptModuleDebugUtilities diff --git a/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index 474331b63e..711e270ed1 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -31,6 +31,7 @@ #include "bedrock/network/packet/toast_request_packet.h" #include "bedrock/network/packet/transfer_packet.h" #include "bedrock/network/packet/update_abilities_packet.h" +#include "bedrock/network/packet/server_script_debug_drawer_packet.h" #include "bedrock/network/server_network_handler.h" #include "bedrock/platform/build_platform.h" #include "bedrock/world/actor/player/player.h" @@ -56,6 +57,12 @@ #include "endstone/event/player/player_skin_change_event.h" #include "endstone/form/action_form.h" #include "endstone/form/message_form.h" +#include "endstone/debugshape/debug_arrow.h" +#include "endstone/debugshape/debug_box.h" +#include "endstone/debugshape/debug_circle.h" +#include "endstone/debugshape/debug_line.h" +#include "endstone/debugshape/debug_sphere.h" +#include "endstone/debugshape/debug_text.h" namespace endstone::core { @@ -705,6 +712,79 @@ void EndstonePlayer::closeForm() forms_.clear(); } +void EndstonePlayer::sendDebugShape(DebugShapeVariant debug_shape) +{ + EndstonePlayer::sendDebugShapes({debug_shape}); +} + +void EndstonePlayer::sendDebugShapes(std::vector debug_shapes) +{ + using namespace ScriptModuleDebugUtilities; + auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); + auto pk = std::static_pointer_cast(packet); + std::vector packet_shape_data; + + auto toVec3 = [](const auto &opt) -> std::optional { + if (opt) { + return Vec3(opt->getX(), opt->getY(), opt->getZ()); + } + return std::nullopt; + }; + + auto toColor = [](const auto &color) -> std::optional { + if (color) { + return mce::Color(static_cast(color->getRed()), static_cast(color->getGreen()), + static_cast(color->getBlue()), static_cast(color->getAlpha())); + } + return std::nullopt; + }; + + for (auto &debug_shape : debug_shapes) { + if (std::holds_alternative(debug_shape)) { + auto arrow = std::get(debug_shape); + packet_shape_data.push_back({arrow.getId(), ScriptDebugShapeType::Arrow, (toVec3(arrow.getPosition())), {}, arrow.getArrowHeadScale(), toColor(arrow.getColor()), {}, {}, {}, toVec3(arrow.getEndPosition()), arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments()}); + } else if (std::holds_alternative(debug_shape)) { + auto box = std::get(debug_shape); + packet_shape_data.push_back({box.getId(), ScriptDebugShapeType::Box, (toVec3(box.getPosition())), {}, box.getScale(), toColor(box.getColor()), {}, {}, toVec3(box.getBoxBounds()), {}, {}, {}, {}}); + } else if (std::holds_alternative(debug_shape)) { + auto circle = std::get(debug_shape); + packet_shape_data.push_back({circle.getId(), ScriptDebugShapeType::Circle, (toVec3(circle.getPosition())), {}, circle.getScale(), toColor(circle.getColor()), {}, {}, {}, {}, {}, {}, circle.getSegments()}); + } else if (std::holds_alternative(debug_shape)) { + auto line = std::get(debug_shape); + packet_shape_data.push_back({line.getId(), ScriptDebugShapeType::Line, (toVec3(line.getPosition())), {}, {}, toColor(line.getColor()), {}, {}, {}, toVec3(line.getEndPosition()), {}, {}, {}}); + } else if (std::holds_alternative(debug_shape)) { + auto sphere = std::get(debug_shape); + packet_shape_data.push_back({sphere.getId(), ScriptDebugShapeType::Sphere, (toVec3(sphere.getPosition())), {}, sphere.getScale(), toColor(sphere.getColor()), {}, {}, {}, {}, {}, {}, sphere.getSegments()}); + } else if (std::holds_alternative(debug_shape)) { + auto text = std::get(debug_shape); + packet_shape_data.push_back({text.getId(), ScriptDebugShapeType::Text, (toVec3(text.getPosition())), {}, {}, toColor(text.getColor()), {}, text.getText(), {}, {}, {}, {}, {}}); + } + } + + pk->shapes = std::move(packet_shape_data); + getPlayer().sendNetworkPacket(*pk); +} + +void EndstonePlayer::removeDebugShape(DebugShapeVariant debug_shape) +{ + EndstonePlayer::removeDebugShapes({debug_shape}); +} + +void EndstonePlayer::removeDebugShapes(std::vector debug_shapes) +{ + using namespace ScriptModuleDebugUtilities; + auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); + std::shared_ptr pk = std::static_pointer_cast(packet); + std::vector debug_shape_data; + for (auto &debug_shape : debug_shapes) { + std::visit([&debug_shape_data](auto &&arg) { + debug_shape_data.push_back({(arg.getId())}); + }, debug_shape); + } + pk->shapes = std::move(debug_shape_data); + getPlayer().sendNetworkPacket(*pk); +} + void EndstonePlayer::onFormClose(std::uint32_t form_id, PlayerFormCloseReason /*reason*/) { auto it = forms_.find(form_id); diff --git a/src/endstone/core/player.h b/src/endstone/core/player.h index 35d682ce64..463796d129 100644 --- a/src/endstone/core/player.h +++ b/src/endstone/core/player.h @@ -117,6 +117,10 @@ class EndstonePlayer : public EndstoneMob, public Player { [[nodiscard]] Skin getSkin() const override; void sendForm(FormVariant form) override; void closeForm() override; + void sendDebugShape(DebugShapeVariant debug_shape) override; + void sendDebugShapes(std::vector debug_shapes) override; + void removeDebugShape(DebugShapeVariant debug_shape) override; + void removeDebugShapes(std::vector debug_shapes) override; void sendPacket(int packet_id, std::string_view payload) const override; bool handlePacket(Packet &packet); void onFormClose(std::uint32_t form_id, PlayerFormCloseReason reason); diff --git a/src/endstone/python/CMakeLists.txt b/src/endstone/python/CMakeLists.txt index ba9d912ed9..7a650fade7 100644 --- a/src/endstone/python/CMakeLists.txt +++ b/src/endstone/python/CMakeLists.txt @@ -15,6 +15,7 @@ pybind11_add_module(endstone_python MODULE endstone_python.cpp event.cpp form.cpp + debug_shape.cpp inventory.cpp lang.cpp level.cpp diff --git a/src/endstone/python/debug_shape.cpp b/src/endstone/python/debug_shape.cpp new file mode 100644 index 0000000000..5f49163bb1 --- /dev/null +++ b/src/endstone/python/debug_shape.cpp @@ -0,0 +1,96 @@ +// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "endstone_python.h" + +namespace py = pybind11; + +namespace endstone::python { + +template +void bind_debug_shape_common(py::class_ &cls) { + cls.def(py::init<>()) + .def_property_readonly("id", &T::getId, "Gets the id of the debug shape.") + .def_property_readonly("players", &T::getPlayers, "Gets the players of the debug shape.") + .def_property("position", &T::getPosition, &T::setPosition, + "Gets or sets the position of the debug shape.", py::return_value_policy::reference) + .def_property("color", &T::getColor, &T::setColor, + "Gets or sets the color of the debug shape.", py::return_value_policy::reference) + .def("add_player", &T::addPlayer, "Adds a player to this debug shape causing it to display on the player's screen.", + py::arg("player"), py::return_value_policy::reference) + .def("remove_player", &T::removePlayer, "Removes a player from this debug shape causing it to be removed from the player's screen.", + py::arg("player"), py::return_value_policy::reference) + .def("remove_all", &T::removeAll, "Removes all players from this debug shape.", py::return_value_policy::reference); +} + +void init_debug_shape(py::module_ &m) +{ + py::class_ debug_arrow(m, "DebugArrow", "Represents a debug arrow."); + bind_debug_shape_common(debug_arrow); + debug_arrow + .def(py::init<>()) + .def_property("end_position", &DebugArrow::getEndPosition, &DebugArrow::setEndPosition, + "Gets or sets the end position of the arrow.", py::return_value_policy::reference) + .def_property("arrow_head_length", &DebugArrow::getArrowHeadLength, &DebugArrow::setArrowHeadLength, + "Gets or sets the length of the arrowhead.", py::return_value_policy::reference) + .def_property("arrow_head_radius", &DebugArrow::getArrowHeadRadius, &DebugArrow::setArrowHeadRadius, + "Gets or sets the radius of the arrowhead.", py::return_value_policy::reference) + .def_property("arrow_head_segments", &DebugArrow::getArrowHeadSegments, &DebugArrow::setArrowHeadSegments, + "Gets or sets the number of segments used to render the arrowhead.", py::return_value_policy::reference) + .def_property("arrow_head_scale", &DebugArrow::getArrowHeadScale, &DebugArrow::setArrowHeadScale, + "Gets or sets the scale of the arrowhead.", py::return_value_policy::reference); + + py::class_ debug_box(m, "DebugBox", "Represents a debug box."); + bind_debug_shape_common(debug_box); + debug_box + .def(py::init<>()) + .def_property("scale", &DebugBox::getScale, &DebugBox::setScale, + "Gets or sets the scale of the box.", py::return_value_policy::reference) + .def_property("box_bounds", &DebugBox::getBoxBounds, &DebugBox::setBoxBounds, + "Gets or sets the bounds of the box.", py::return_value_policy::reference); + + py::class_ debug_circle(m, "DebugCircle", "Represents a debug circle."); + bind_debug_shape_common(debug_circle); + debug_circle + .def(py::init<>()) + .def_property("scale", &DebugCircle::getScale, &DebugCircle::setScale, + "Gets or sets the scale of the circle.", py::return_value_policy::reference) + .def_property("segments", &DebugCircle::getSegments, &DebugCircle::setSegments, + "Gets or sets the number of segments used to render the circle.", py::return_value_policy::reference); + + py::class_ debug_line(m, "DebugLine", "Represents a debug line."); + bind_debug_shape_common(debug_line); + debug_line + .def(py::init<>()) + .def_property("end_position", &DebugLine::getEndPosition, &DebugLine::setEndPosition, + "Gets or sets the end position of the line.", py::return_value_policy::reference); + + py::class_ debug_sphere(m, "DebugSphere", "Represents a debug sphere."); + bind_debug_shape_common(debug_sphere); + debug_sphere + .def(py::init<>()) + .def_property("scale", &DebugSphere::getScale, &DebugSphere::setScale, + "Gets or sets the scale of the sphere.", py::return_value_policy::reference) + .def_property("segments", &DebugSphere::getSegments, &DebugSphere::setSegments, + "Gets or sets the number of segments used to render the sphere.", py::return_value_policy::reference); + + py::class_ debug_text(m, "DebugText", "Represents a debug text."); + bind_debug_shape_common(debug_text); + debug_text + .def(py::init<>()) + .def_property("text", &DebugText::getText, &DebugText::setText, + "Gets or sets the text of the debug text.", py::return_value_policy::reference); +} + +} // namespace endstone::python \ No newline at end of file diff --git a/src/endstone/python/endstone_python.cpp b/src/endstone/python/endstone_python.cpp index ea4c2f1d67..10cc40eece 100644 --- a/src/endstone/python/endstone_python.cpp +++ b/src/endstone/python/endstone_python.cpp @@ -36,6 +36,7 @@ void init_damage(py::module_ &); void init_enchantments(py::module_ &); void init_event(py::module_ &, py::class_ &event, py::enum_ &event_priority); void init_form(py::module_ &); +void init_debug_shape(py::module_ &); void init_game_mode(py::module_ &); void init_inventory(py::module_ &, py::class_ &item_stack); void init_lang(py::module_ &); @@ -95,6 +96,7 @@ PYBIND11_MODULE(endstone_python, m) // NOLINT(*-use-anonymous-namespace) init_enchantments(m); init_inventory(m, item_stack); init_util(m); + init_debug_shape(m); init_ban(m); init_map(m); init_scoreboard(m); @@ -391,6 +393,10 @@ void init_player(py::module_ &m, py::class_ &offline_player, .def_property_readonly("skin", &Player::getSkin, "Get the player's skin.") .def("send_form", &Player::sendForm, "Sends a form to the player.", py::arg("form")) .def("close_form", &Player::closeForm, "Closes the forms that are currently open for the player.") + .def("send_debug_shape", &Player::sendDebugShape, "Sends a debug shape to the player.", py::arg("debug_shape")) + .def("send_debug_shapes", &Player::sendDebugShapes, "Sends a number of debug shapes to the player.", py::arg("debug_shapes")) + .def("remove_debug_shape", &Player::removeDebugShape, "Removes a debug shape from the player.", py::arg("debug_shape")) + .def("remove_debug_shapes", &Player::removeDebugShapes, "Removes a number of debug shapes from the player.", py::arg("debug_shapes")) .def( "send_packet", [](const Player &self, const int packet_id, const py::bytes &payload) { diff --git a/third_party/detours b/third_party/detours index ea6c4ae7f3..9764cebcb1 160000 --- a/third_party/detours +++ b/third_party/detours @@ -1 +1 @@ -Subproject commit ea6c4ae7f3f1b1772b8a7cda4199230b932f5a50 +Subproject commit 9764cebcb1a75940e68fa83d6730ffaf0f669401