From e56846c61d1de584ce21b3d4539b65b1d4a4a135 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Wed, 25 Jun 2025 21:33:48 +0800 Subject: [PATCH 01/17] feat: add classes for each type of debug shape --- include/endstone/debugshape/debug_arrow.h | 121 +++++++++++++++++++++ include/endstone/debugshape/debug_box.h | 75 +++++++++++++ include/endstone/debugshape/debug_circle.h | 72 ++++++++++++ include/endstone/debugshape/debug_line.h | 49 +++++++++ include/endstone/debugshape/debug_shape.h | 102 +++++++++++++++++ include/endstone/debugshape/debug_sphere.h | 72 ++++++++++++ include/endstone/debugshape/debug_text.h | 51 +++++++++ 7 files changed, 542 insertions(+) create mode 100644 include/endstone/debugshape/debug_arrow.h create mode 100644 include/endstone/debugshape/debug_box.h create mode 100644 include/endstone/debugshape/debug_circle.h create mode 100644 include/endstone/debugshape/debug_line.h create mode 100644 include/endstone/debugshape/debug_shape.h create mode 100644 include/endstone/debugshape/debug_sphere.h create mode 100644 include/endstone/debugshape/debug_text.h diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h new file mode 100644 index 000000000..c11fc2376 --- /dev/null +++ b/include/endstone/debugshape/debug_arrow.h @@ -0,0 +1,121 @@ +// 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(std::optional end_position) + { + end_position_ = std::move(end_position); + 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(std::optional arrow_head_length) + { + arrow_head_length_ = std::move(arrow_head_length); + 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(std::optional arrow_head_radius) + { + arrow_head_radius_ = std::move(arrow_head_radius); + 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(std::optional arrow_head_segments) + { + arrow_head_segments_ = std::move(arrow_head_segments); + return *this; + } + +private: + std::optional end_position_; + std::optional arrow_head_length_; + std::optional arrow_head_radius_; + std::optional arrow_head_segments_; +}; + +} // 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 000000000..e50bfee5d --- /dev/null +++ b/include/endstone/debugshape/debug_box.h @@ -0,0 +1,75 @@ +// 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(std::optional scale) + { + scale_ = std::move(scale); + 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(std::optional box_bounds) + { + box_bounds_ = std::move(box_bounds); + 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 000000000..45f9446f6 --- /dev/null +++ b/include/endstone/debugshape/debug_circle.h @@ -0,0 +1,72 @@ +// 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 { + +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(std::optional scale) + { + scale_ = std::move(scale); + 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 arrow_head_segments The desired number of segments. + * @return A reference to the current debug shape. + */ + DebugCircle &setSegments(std::optional segments_) + { + segments_ = std::move(segments_); + 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 000000000..188ef9bf4 --- /dev/null +++ b/include/endstone/debugshape/debug_line.h @@ -0,0 +1,49 @@ +// 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 { + +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(std::optional end_position) + { + end_position_ = std::move(end_position); + 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 000000000..916ad7bbe --- /dev/null +++ b/include/endstone/debugshape/debug_shape.h @@ -0,0 +1,102 @@ +// 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 "endstone/color.h" +#include "endstone/vector.h" + +namespace endstone { + +/** + * @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 a id, position and color. + */ +template +class DebugShape { +public: + using DebugShapeId = int64_t; + explicit DebugShape() + { + id_ = --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(std::optional position) + { + position_ = std::move(position); + 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(std::optional color) + { + color_ = std::move(color); + return *static_cast(this); + } + +protected: + static DebugShapeId id_counter_; + DebugShapeId id_; + std::optional position_; + std::optional color_; +}; + +} // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_sphere.h b/include/endstone/debugshape/debug_sphere.h new file mode 100644 index 000000000..9ddce45a5 --- /dev/null +++ b/include/endstone/debugshape/debug_sphere.h @@ -0,0 +1,72 @@ +// 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 { + +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_ = std::move(scale); + 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 arrow_head_segments The desired number of segments. + * @return A reference to the current debug shape. + */ + DebugSphere &setSegments(std::optional segments_) + { + segments_ = std::move(segments_); + 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 000000000..05acff212 --- /dev/null +++ b/include/endstone/debugshape/debug_text.h @@ -0,0 +1,51 @@ +// 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 { + +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 scale The desired the text of the debug text. + * @return A reference to the current debug shape. + */ + DebugText &setText(std::string text) + { + text_ = std::move(text); + return *this; + } + +private: + std::string text_; +}; + +} // namespace endstone \ No newline at end of file From ade36b50173eac9a6b2e3bfd2e181497ae367741 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 26 Jun 2025 00:12:05 +0800 Subject: [PATCH 02/17] feat: more works --- endstone/_internal/endstone_python.pyi | 260 +++++++++++++++++- endstone/debugshape.py | 17 ++ include/endstone/debugshape/debug_arrow.h | 20 +- include/endstone/debugshape/debug_box.h | 12 +- include/endstone/debugshape/debug_circle.h | 14 +- include/endstone/debugshape/debug_line.h | 11 +- include/endstone/debugshape/debug_shape.h | 25 +- include/endstone/debugshape/debug_sphere.h | 11 +- include/endstone/debugshape/debug_text.h | 9 +- include/endstone/endstone.hpp | 7 + .../server_script_debug_drawer_packet.h | 49 ++++ src/endstone/python/CMakeLists.txt | 1 + src/endstone/python/debug_shape.cpp | 97 +++++++ src/endstone/python/endstone_python.cpp | 2 + third_party/detours | 2 +- 15 files changed, 492 insertions(+), 45 deletions(-) create mode 100644 endstone/debugshape.py create mode 100644 src/bedrock/network/packet/server_script_debug_drawer_packet.h create mode 100644 src/endstone/python/debug_shape.cpp diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index c70db5a68..13fae9659 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', 'BlockData', 'BlockEvent', 'BlockFace', 'BlockPlaceEvent', 'BlockState', 'BossBar', 'BroadcastMessageEvent', 'Cancellable', 'Chunk', 'ChunkEvent', 'ChunkLoadEvent', 'ChunkUnloadEvent', 'ColorFormat', 'Command', 'CommandExecutor', 'CommandSender', 'CommandSenderWrapper', 'ConsoleCommandSender', 'Criteria', 'DamageSource', 'Dimension', 'DimensionEvent', 'DisplaySlot', 'Divider', 'Dropdown', 'Enchantment', 'EnchantmentRegistry', 'EquipmentSlot', 'Event', 'EventPriority', 'GameMode', 'Header', 'Inventory', 'IpBanEntry', 'IpBanList', 'ItemFactory', 'ItemMeta', 'ItemRegistry', 'ItemStack', 'ItemType', 'Label', 'Language', 'Level', 'LevelEvent', 'Location', 'Logger', 'MapCanvas', 'MapMeta', 'MapRenderer', 'MapView', 'MessageForm', 'Mob', 'MobEvent', 'ModalForm', 'NamespacedKey', 'Objective', 'ObjectiveSortOrder', 'OfflinePlayer', 'PacketReceiveEvent', 'PacketSendEvent', 'Permissible', 'Permission', 'PermissionAttachment', 'PermissionAttachmentInfo', 'PermissionDefault', 'PermissionLevel', 'Player', 'PlayerBanEntry', 'PlayerBanList', 'PlayerChatEvent', 'PlayerCommandEvent', 'PlayerDeathEvent', 'PlayerDropItemEvent', 'PlayerEmoteEvent', 'PlayerEvent', 'PlayerGameModeChangeEvent', 'PlayerInteractActorEvent', 'PlayerInteractEvent', 'PlayerInventory', 'PlayerItemConsumeEvent', 'PlayerJoinEvent', 'PlayerJumpEvent', 'PlayerKickEvent', 'PlayerLoginEvent', 'PlayerMoveEvent', 'PlayerPickupItemEvent', 'PlayerQuitEvent', 'PlayerRespawnEvent', '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', 'BlockData', 'BlockEvent', 'BlockFace', 'BlockPlaceEvent', 'BlockState', 'BossBar', 'BroadcastMessageEvent', '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', 'GameMode', 'Header', 'Inventory', 'IpBanEntry', 'IpBanList', 'ItemFactory', 'ItemMeta', 'ItemRegistry', 'ItemStack', 'ItemType', 'Label', 'Language', 'Level', 'LevelEvent', 'Location', 'Logger', 'MapCanvas', 'MapMeta', 'MapRenderer', 'MapView', 'MessageForm', 'Mob', 'MobEvent', 'ModalForm', 'NamespacedKey', 'Objective', 'ObjectiveSortOrder', 'OfflinePlayer', 'PacketReceiveEvent', 'PacketSendEvent', 'Permissible', 'Permission', 'PermissionAttachment', 'PermissionAttachmentInfo', 'PermissionDefault', 'PermissionLevel', 'Player', 'PlayerBanEntry', 'PlayerBanList', 'PlayerChatEvent', 'PlayerCommandEvent', 'PlayerDeathEvent', 'PlayerDropItemEvent', 'PlayerEmoteEvent', 'PlayerEvent', 'PlayerGameModeChangeEvent', 'PlayerInteractActorEvent', 'PlayerInteractEvent', 'PlayerInventory', 'PlayerItemConsumeEvent', 'PlayerJoinEvent', 'PlayerJumpEvent', 'PlayerKickEvent', 'PlayerLoginEvent', 'PlayerMoveEvent', 'PlayerPickupItemEvent', 'PlayerQuitEvent', 'PlayerRespawnEvent', '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. @@ -1056,6 +1056,264 @@ class DamageSource: """ Get the damage type. """ +class DebugArrow: + """ + Represents a debug arrow. + """ + def __init__(self) -> None: + ... + @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_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 arrow. + """ + @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 arrow. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug arrow. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugArrow: + ... +class DebugBox: + """ + Represents a debug box. + """ + def __init__(self) -> None: + ... + @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 box. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugBox: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug box. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug box. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug circle. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugCircle: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug circle. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug circle. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug line. + """ + @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 line. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug line. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugLine: + ... +class DebugSphere: + """ + Represents a debug sphere. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug sphere. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugSphere: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug sphere. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug sphere. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug text. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugText: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug text. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug text. + """ + @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. diff --git a/endstone/debugshape.py b/endstone/debugshape.py new file mode 100644 index 000000000..17acc6ee5 --- /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 index c11fc2376..f83ff8a8d 100644 --- a/include/endstone/debugshape/debug_arrow.h +++ b/include/endstone/debugshape/debug_arrow.h @@ -28,7 +28,7 @@ class DebugArrow : public DebugShape { * * @return The end position of the arrow. */ - [[nodiscard]] std::optional getEndPosition() const + [[nodiscard]] std::optional> getEndPosition() const { return end_position_; } @@ -39,9 +39,9 @@ class DebugArrow : public DebugShape { * @param end_position The desired end position of the arrow * @return A reference to the current debug shape. */ - DebugArrow &setEndPosition(std::optional end_position) + DebugArrow &setEndPosition(const std::optional> end_position) { - end_position_ = std::move(end_position); + end_position_ = end_position; return *this; } @@ -61,9 +61,9 @@ class DebugArrow : public DebugShape { * @param arrow_head_length The desired length of the arrowhead. * @return A reference to the current debug shape. */ - DebugArrow &setArrowHeadLength(std::optional arrow_head_length) + DebugArrow &setArrowHeadLength(const std::optional arrow_head_length) { - arrow_head_length_ = std::move(arrow_head_length); + arrow_head_length_ = arrow_head_length; return *this; } @@ -83,9 +83,9 @@ class DebugArrow : public DebugShape { * @param arrow_head_radius The desired radius of the arrowhead. * @return A reference to the current debug shape. */ - DebugArrow &setArrowHeadRadius(std::optional arrow_head_radius) + DebugArrow &setArrowHeadRadius(const std::optional arrow_head_radius) { - arrow_head_radius_ = std::move(arrow_head_radius); + arrow_head_radius_ = arrow_head_radius; return *this; } @@ -105,14 +105,14 @@ class DebugArrow : public DebugShape { * @param arrow_head_segments The desired number of segments. * @return A reference to the current debug shape. */ - DebugArrow &setArrowHeadSegments(std::optional arrow_head_segments) + DebugArrow &setArrowHeadSegments(const std::optional arrow_head_segments) { - arrow_head_segments_ = std::move(arrow_head_segments); + arrow_head_segments_ = arrow_head_segments; return *this; } private: - std::optional end_position_; + std::optional> end_position_; std::optional arrow_head_length_; std::optional arrow_head_radius_; std::optional arrow_head_segments_; diff --git a/include/endstone/debugshape/debug_box.h b/include/endstone/debugshape/debug_box.h index e50bfee5d..cc277a9b4 100644 --- a/include/endstone/debugshape/debug_box.h +++ b/include/endstone/debugshape/debug_box.h @@ -39,9 +39,9 @@ class DebugBox : public DebugShape { * @param scale The desired scale of the box. * @return A reference to the current debug shape. */ - DebugBox &setScale(std::optional scale) + DebugBox &setScale(const std::optional scale) { - scale_ = std::move(scale); + scale_ = scale; return *this; } @@ -50,7 +50,7 @@ class DebugBox : public DebugShape { * * @return The bounds of the box. */ - [[nodiscard]] std::optional getBoxBounds() const + [[nodiscard]] std::optional> getBoxBounds() const { return box_bounds_; } @@ -61,15 +61,15 @@ class DebugBox : public DebugShape { * @param box_bounds The desired bounds of the box. * @return A reference to the current debug shape. */ - DebugBox &setBoxBounds(std::optional box_bounds) + DebugBox &setBoxBounds(const std::optional> box_bounds) { - box_bounds_ = std::move(box_bounds); + box_bounds_ = box_bounds; return *this; } private: std::optional scale_; - std::optional box_bounds_; + 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 index 45f9446f6..2591b96b3 100644 --- a/include/endstone/debugshape/debug_circle.h +++ b/include/endstone/debugshape/debug_circle.h @@ -18,6 +18,10 @@ namespace endstone { + +/** + * @brief Represents a debug circle. + */ class DebugCircle : public DebugShape { public: /** @@ -36,9 +40,9 @@ class DebugCircle : public DebugShape { * @param scale The desired scale of the circle. * @return A reference to the current debug shape. */ - DebugCircle &setScale(std::optional scale) + DebugCircle &setScale(const std::optional scale) { - scale_ = std::move(scale); + scale_ = scale; return *this; } @@ -55,12 +59,12 @@ class DebugCircle : public DebugShape { /** * @brief Sets the number of segments used to render the circle. * - * @param arrow_head_segments The desired number of segments. + * @param segments The desired number of segments. * @return A reference to the current debug shape. */ - DebugCircle &setSegments(std::optional segments_) + DebugCircle &setSegments(const std::optional segments) { - segments_ = std::move(segments_); + segments_ = segments; return *this; } diff --git a/include/endstone/debugshape/debug_line.h b/include/endstone/debugshape/debug_line.h index 188ef9bf4..0d682f8a7 100644 --- a/include/endstone/debugshape/debug_line.h +++ b/include/endstone/debugshape/debug_line.h @@ -18,6 +18,9 @@ namespace endstone { +/** + * @brief Represents a debug line. + */ class DebugLine : public DebugShape { public: /** @@ -25,7 +28,7 @@ class DebugLine : public DebugShape { * * @return The end position of the line. */ - [[nodiscard]] std::optional getEndPosition() const + [[nodiscard]] std::optional> getEndPosition() const { return end_position_; } @@ -36,14 +39,14 @@ class DebugLine : public DebugShape { * @param end_position The desired end position of the line * @return A reference to the current debug shape. */ - DebugLine &setEndPosition(std::optional end_position) + DebugLine &setEndPosition(const std::optional> end_position) { - end_position_ = std::move(end_position); + end_position_ = end_position; return *this; } private: - std::optional end_position_; + 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 index 916ad7bbe..4d5c64c96 100644 --- a/include/endstone/debugshape/debug_shape.h +++ b/include/endstone/debugshape/debug_shape.h @@ -14,14 +14,18 @@ #pragma once -#include #include +#include -#include "endstone/color.h" -#include "endstone/vector.h" +#include "endstone/util/color.h" +#include "endstone/util/vector.h" namespace endstone { +namespace debugshape_internal { + inline std::atomic id_counter{0}; +} // namespace debugshape_internal + /** * @brief Represents a generic debug shape. * @@ -35,7 +39,7 @@ class DebugShape { using DebugShapeId = int64_t; explicit DebugShape() { - id_ = --id_counter_; + id_ = --debugshape_internal::id_counter; } /** @@ -53,7 +57,7 @@ class DebugShape { * * @return The position of the debug shape. */ - [[nodiscard]] std::optional getPosition() const + [[nodiscard]] std::optional> getPosition() const { return position_; } @@ -64,9 +68,9 @@ class DebugShape { * @param position The position to set for the debug shape. * @return A reference to the current debug shape. */ - T &setPosition(std::optional position) + T &setPosition(const std::optional> position) { - position_ = std::move(position); + position_ = position; return *static_cast(this); } @@ -86,16 +90,15 @@ class DebugShape { * @param color The color to set for the debug shape. * @return A reference to the current debug shape. */ - T &setColor(std::optional color) + T &setColor(const std::optional color) { - color_ = std::move(color); + color_ = color; return *static_cast(this); } protected: - static DebugShapeId id_counter_; DebugShapeId id_; - std::optional position_; + std::optional> position_; std::optional color_; }; diff --git a/include/endstone/debugshape/debug_sphere.h b/include/endstone/debugshape/debug_sphere.h index 9ddce45a5..c85a4a58c 100644 --- a/include/endstone/debugshape/debug_sphere.h +++ b/include/endstone/debugshape/debug_sphere.h @@ -18,6 +18,9 @@ namespace endstone { +/** + * @brief Represents a debug sphere. + */ class DebugSphere : public DebugShape { public: /** @@ -38,7 +41,7 @@ class DebugSphere : public DebugShape { */ DebugSphere &setScale(std::optional scale) { - scale_ = std::move(scale); + scale_ = scale; return *this; } @@ -55,12 +58,12 @@ class DebugSphere : public DebugShape { /** * @brief Sets the number of segments used to render the sphere. * - * @param arrow_head_segments The desired number of segments. + * @param segments The desired number of segments. * @return A reference to the current debug shape. */ - DebugSphere &setSegments(std::optional segments_) + DebugSphere &setSegments(const std::optional segments) { - segments_ = std::move(segments_); + segments_ = segments; return *this; } diff --git a/include/endstone/debugshape/debug_text.h b/include/endstone/debugshape/debug_text.h index 05acff212..fc5003e5b 100644 --- a/include/endstone/debugshape/debug_text.h +++ b/include/endstone/debugshape/debug_text.h @@ -20,6 +20,9 @@ namespace endstone { +/** + * @brief Represents a debug text. + */ class DebugText : public DebugShape { public: /** @@ -35,12 +38,12 @@ class DebugText : public DebugShape { /** * @brief Sets the the text of the debug text. * - * @param scale The desired 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(std::string text) + DebugText &setText(const std::string &text) { - text_ = std::move(text); + text_ = text; return *this; } diff --git a/include/endstone/endstone.hpp b/include/endstone/endstone.hpp index f5527ee7b..9226909ee 100644 --- a/include/endstone/endstone.hpp +++ b/include/endstone/endstone.hpp @@ -114,6 +114,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/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 000000000..cbd336d5e --- /dev/null +++ b/src/bedrock/network/packet/server_script_debug_drawer_packet.h @@ -0,0 +1,49 @@ +// 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" + +enum class DebugShapeType : std::uint8_t { + Line = 0, + Box = 1, + Sphere = 2, + Circle = 3, + Text = 4, + Arrow = 5 +}; + +struct DebugShapeData { + std::int64_t id; + std::optional type; + std::optional position; + std::optional scale; + std::optional rotation; + std::optional total_time_left; + std::optional color; + std::optional text; + std::optional box_bounds; + std::optional line_end_position; + std::optional arrow_head_length; + std::optional arrow_head_radius; + std::optional segments; +}; + +class ServerScriptDebugDrawerPacket : public Packet { +public: + std::vector shapes; +}; \ No newline at end of file diff --git a/src/endstone/python/CMakeLists.txt b/src/endstone/python/CMakeLists.txt index 229af6fd2..e6358c3bd 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 000000000..190632db7 --- /dev/null +++ b/src/endstone/python/debug_shape.cpp @@ -0,0 +1,97 @@ +// 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 { + +void init_debug_shape(py::module_ &m) +{ + py::class_(m, "DebugArrow", "Represents a debug arrow.") + .def(py::init<>()) + .def_property_readonly("id", &DebugArrow::getId, "Gets the id of the debug arrow.") + .def_property("position", &DebugArrow::getPosition, &DebugArrow::setPosition, + "Gets or sets the position of the debug arrow.", py::return_value_policy::reference) + .def_property("color", &DebugArrow::getColor, &DebugArrow::setColor, + "Gets or sets the color of the debug arrow.", py::return_value_policy::reference) + .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); + + py::class_(m, "DebugBox", "Represents a debug box.") + .def(py::init<>()) + .def_property_readonly("id", &DebugBox::getId, "Gets the id of the debug box.") + .def_property("position", &DebugBox::getPosition, &DebugBox::setPosition, + "Gets or sets the position of the debug box.", py::return_value_policy::reference) + .def_property("color", &DebugBox::getColor, &DebugBox::setColor, + "Gets or sets the color of the debug box.", py::return_value_policy::reference) + .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_(m, "DebugCircle", "Represents a debug circle.") + .def(py::init<>()) + .def_property_readonly("id", &DebugCircle::getId, "Gets the id of the debug circle.") + .def_property("position", &DebugCircle::getPosition, &DebugCircle::setPosition, + "Gets or sets the position of the debug circle.", py::return_value_policy::reference) + .def_property("color", &DebugCircle::getColor, &DebugCircle::setColor, + "Gets or sets the color of the debug circle.", py::return_value_policy::reference) + .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_(m, "DebugLine", "Represents a debug line.") + .def(py::init<>()) + .def_property_readonly("id", &DebugLine::getId, "Gets the id of the debug line.") + .def_property("position", &DebugLine::getPosition, &DebugLine::setPosition, + "Gets or sets the position of the debug line.", py::return_value_policy::reference) + .def_property("color", &DebugLine::getColor, &DebugLine::setColor, + "Gets or sets the color of the debug line.", py::return_value_policy::reference) + .def_property("end_position", &DebugLine::getEndPosition, &DebugLine::setEndPosition, + "Gets or sets the end position of the line.", py::return_value_policy::reference); + + py::class_(m, "DebugSphere", "Represents a debug sphere.") + .def(py::init<>()) + .def_property_readonly("id", &DebugSphere::getId, "Gets the id of the debug sphere.") + .def_property("position", &DebugSphere::getPosition, &DebugSphere::setPosition, + "Gets or sets the position of the debug sphere.", py::return_value_policy::reference) + .def_property("color", &DebugSphere::getColor, &DebugSphere::setColor, + "Gets or sets the color of the debug sphere.", py::return_value_policy::reference) + .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_(m, "DebugText", "Represents a debug text.") + .def(py::init<>()) + .def_property_readonly("id", &DebugText::getId, "Gets the id of the debug text.") + .def_property("position", &DebugText::getPosition, &DebugText::setPosition, + "Gets or sets the position of the debug text.", py::return_value_policy::reference) + .def_property("color", &DebugText::getColor, &DebugText::setColor, + "Gets or sets the color of the debug text.", py::return_value_policy::reference) + .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 c918bc642..d19e666d3 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_ &); @@ -97,6 +98,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_level(m); init_map(m); diff --git a/third_party/detours b/third_party/detours index ea6c4ae7f..9764cebcb 160000 --- a/third_party/detours +++ b/third_party/detours @@ -1 +1 @@ -Subproject commit ea6c4ae7f3f1b1772b8a7cda4199230b932f5a50 +Subproject commit 9764cebcb1a75940e68fa83d6730ffaf0f669401 From 87235581b4b445fe830e9bcca812407b130ef46a Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 26 Jun 2025 00:14:37 +0800 Subject: [PATCH 03/17] feat: change segments from int to std::uint8_t to match the vanilla --- include/endstone/debugshape/debug_arrow.h | 6 +++--- include/endstone/debugshape/debug_circle.h | 6 +++--- include/endstone/debugshape/debug_sphere.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h index f83ff8a8d..59a8493aa 100644 --- a/include/endstone/debugshape/debug_arrow.h +++ b/include/endstone/debugshape/debug_arrow.h @@ -94,7 +94,7 @@ class DebugArrow : public DebugShape { * * @return The number of arrowhead segments. */ - [[nodiscard]] std::optional getArrowHeadSegments() const + [[nodiscard]] std::optional getArrowHeadSegments() const { return arrow_head_segments_; } @@ -105,7 +105,7 @@ class DebugArrow : public DebugShape { * @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) + DebugArrow &setArrowHeadSegments(const std::optional arrow_head_segments) { arrow_head_segments_ = arrow_head_segments; return *this; @@ -115,7 +115,7 @@ class DebugArrow : public DebugShape { std::optional> end_position_; std::optional arrow_head_length_; std::optional arrow_head_radius_; - std::optional arrow_head_segments_; + std::optional arrow_head_segments_; }; } // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_circle.h b/include/endstone/debugshape/debug_circle.h index 2591b96b3..787f89ff1 100644 --- a/include/endstone/debugshape/debug_circle.h +++ b/include/endstone/debugshape/debug_circle.h @@ -51,7 +51,7 @@ class DebugCircle : public DebugShape { * * @return The number of circle segments. */ - [[nodiscard]] std::optional getSegments() const + [[nodiscard]] std::optional getSegments() const { return segments_; } @@ -62,7 +62,7 @@ class DebugCircle : public DebugShape { * @param segments The desired number of segments. * @return A reference to the current debug shape. */ - DebugCircle &setSegments(const std::optional segments) + DebugCircle &setSegments(const std::optional segments) { segments_ = segments; return *this; @@ -70,7 +70,7 @@ class DebugCircle : public DebugShape { private: std::optional scale_; - std::optional segments_; + std::optional segments_; }; } // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_sphere.h b/include/endstone/debugshape/debug_sphere.h index c85a4a58c..3f59faa7a 100644 --- a/include/endstone/debugshape/debug_sphere.h +++ b/include/endstone/debugshape/debug_sphere.h @@ -50,7 +50,7 @@ class DebugSphere : public DebugShape { * * @return The number of sphere segments. */ - [[nodiscard]] std::optional getSegments() const + [[nodiscard]] std::optional getSegments() const { return segments_; } @@ -61,7 +61,7 @@ class DebugSphere : public DebugShape { * @param segments The desired number of segments. * @return A reference to the current debug shape. */ - DebugSphere &setSegments(const std::optional segments) + DebugSphere &setSegments(const std::optional segments) { segments_ = segments; return *this; @@ -69,7 +69,7 @@ class DebugSphere : public DebugShape { private: std::optional scale_; - std::optional segments_; + std::optional segments_; }; } // namespace endstone \ No newline at end of file From 2fb812badc4ad913252eba1b143598dcdc719406 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 26 Jun 2025 00:36:07 +0800 Subject: [PATCH 04/17] feat: add methods to Player --- include/endstone/player.h | 35 +++++++++++++++++++++++++ src/endstone/core/player.cpp | 28 ++++++++++++++++++++ src/endstone/core/player.h | 4 +++ src/endstone/python/endstone_python.cpp | 4 +++ 4 files changed, 71 insertions(+) diff --git a/include/endstone/player.h b/include/endstone/player.h index 5d65254a3..26165f9fc 100644 --- a/include/endstone/player.h +++ b/include/endstone/player.h @@ -21,6 +21,12 @@ #include "endstone/form/action_form.h" #include "endstone/form/message_form.h" #include "endstone/form/modal_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" #include "endstone/game_mode.h" #include "endstone/inventory/player_inventory.h" #include "endstone/offline_player.h" @@ -37,6 +43,7 @@ namespace endstone { class Player : public Mob, public OfflinePlayer { protected: using FormVariant = std::variant; + using DebugShapeVariant = std::variant; public: // CommandSender @@ -459,6 +466,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/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index b2139235e..39e96af55 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -27,6 +27,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" @@ -45,6 +46,12 @@ #include "endstone/event/player/player_join_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 { @@ -745,6 +752,27 @@ void EndstonePlayer::closeForm() forms_.clear(); } +void EndstonePlayer::sendDebugShape(DebugShapeVariant debug_shape) +{ + auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); + std::shared_ptr pk = std::static_pointer_cast(packet); +} + +void EndstonePlayer::sendDebugShapes(std::vector debug_shapes) +{ + // TODO +} + +void EndstonePlayer::removeDebugShape(DebugShapeVariant debug_shape) +{ + // TODO +} + +void EndstonePlayer::removeDebugShapes(std::vector debug_shapes) +{ + // TODO +} + 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 9d41ebd22..6e6aa11fd 100644 --- a/src/endstone/core/player.h +++ b/src/endstone/core/player.h @@ -151,6 +151,10 @@ class EndstonePlayer : public EndstoneMob, public Player { [[nodiscard]] const 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; void handlePacket(const ::Packet &packet); void onFormClose(std::uint32_t form_id, PlayerFormCloseReason reason); diff --git a/src/endstone/python/endstone_python.cpp b/src/endstone/python/endstone_python.cpp index d19e666d3..7c4494dd3 100644 --- a/src/endstone/python/endstone_python.cpp +++ b/src/endstone/python/endstone_python.cpp @@ -412,6 +412,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) { From c11e4de7d373719b551a5e0dcf3e9e9a97a19924 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 26 Jun 2025 01:13:18 +0800 Subject: [PATCH 05/17] feat: implement Player::sendDebugShapes and Player::removeDebugShapes --- src/endstone/core/player.cpp | 93 ++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index 39e96af55..64adbd962 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -754,23 +754,106 @@ void EndstonePlayer::closeForm() void EndstonePlayer::sendDebugShape(DebugShapeVariant debug_shape) { - auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); - std::shared_ptr pk = std::static_pointer_cast(packet); + EndstonePlayer::sendDebugShapes({debug_shape}); } void EndstonePlayer::sendDebugShapes(std::vector debug_shapes) { - // TODO + 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) { + if (std::holds_alternative(debug_shape)) { + auto &arrow = std::get(debug_shape); + auto pos = arrow.getPosition(); + auto end_pos = arrow.getEndPosition(); + auto color = arrow.getColor(); + debug_shape_data.push_back({ + arrow.getId(), DebugShapeType::Arrow, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + std::nullopt, std::nullopt, Vec3(end_pos->getX(), end_pos->getY(), end_pos->getZ()), + arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments() + }); + } + if (std::holds_alternative(debug_shape)) { + auto &box = std::get(debug_shape); + auto pos = box.getPosition(); + auto box_bounds = box.getBoxBounds(); + auto color = box.getColor(); + debug_shape_data.push_back({ + box.getId(), DebugShapeType::Box, Vec3(pos->getX(), pos->getY(), pos->getZ()), box.getScale(), std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + std::nullopt, Vec3(box_bounds->getX(), box_bounds->getY(), box_bounds->getZ()), std::nullopt, + std::nullopt, std::nullopt, std::nullopt + }); + } + if (std::holds_alternative(debug_shape)) { + auto &circle = std::get(debug_shape); + auto pos = circle.getPosition(); + auto color = circle.getColor(); + debug_shape_data.push_back({ + circle.getId(), DebugShapeType::Circle, Vec3(pos->getX(), pos->getY(), pos->getZ()), circle.getScale(), std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + std::nullopt, std::nullopt, std::nullopt, + std::nullopt, std::nullopt, circle.getSegments() + }); + } + if (std::holds_alternative(debug_shape)) { + auto &line = std::get(debug_shape); + auto pos = line.getPosition(); + auto end_pos = line.getEndPosition(); + auto color = line.getColor(); + debug_shape_data.push_back({ + line.getId(), DebugShapeType::Line, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + std::nullopt, std::nullopt, Vec3(end_pos->getX(), end_pos->getY(), end_pos->getZ()), + std::nullopt, std::nullopt, std::nullopt + }); + } + if (std::holds_alternative(debug_shape)) { + auto &sphere = std::get(debug_shape); + auto pos = sphere.getPosition(); + auto color = sphere.getColor(); + debug_shape_data.push_back({ + sphere.getId(), DebugShapeType::Sphere, Vec3(pos->getX(), pos->getY(), pos->getZ()), sphere.getScale(), std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + std::nullopt, std::nullopt, std::nullopt, + std::nullopt, std::nullopt, sphere.getSegments() + }); + } + if (std::holds_alternative(debug_shape)) { + auto &text = std::get(debug_shape); + auto pos = text.getPosition(); + auto color = text.getColor(); + debug_shape_data.push_back({ + text.getId(), DebugShapeType::Text, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, + std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), + text.getText(), std::nullopt, std::nullopt, + std::nullopt, std::nullopt, std::nullopt + }); + } + } + pk->shapes = std::move(debug_shape_data); + getPlayer().sendNetworkPacket(*pk); } void EndstonePlayer::removeDebugShape(DebugShapeVariant debug_shape) { - // TODO + EndstonePlayer::removeDebugShapes({debug_shape}); } void EndstonePlayer::removeDebugShapes(std::vector debug_shapes) { - // TODO + 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*/) From 3e1d98e104fc5c508732e4e8b26b2ccf66abb9e1 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 26 Jun 2025 01:17:52 +0800 Subject: [PATCH 06/17] feat: update python stubs --- endstone/_internal/endstone_python.pyi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index 13fae9659..3746390e9 100644 --- a/endstone/_internal/endstone_python.pyi +++ b/endstone/_internal/endstone_python.pyi @@ -3058,10 +3058,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. From 7376df975b663a698c440ad1ae490689441f03c4 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 27 Jun 2025 23:17:20 +0800 Subject: [PATCH 07/17] refactor: refactor EndstonePlayer.sendDebugShapes() --- src/endstone/core/player.cpp | 103 ++++++++++++----------------------- 1 file changed, 35 insertions(+), 68 deletions(-) diff --git a/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index 64adbd962..913da5a74 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -760,79 +760,46 @@ void EndstonePlayer::sendDebugShape(DebugShapeVariant debug_shape) void EndstonePlayer::sendDebugShapes(std::vector debug_shapes) { auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); - std::shared_ptr pk = std::static_pointer_cast(packet); + auto pk = std::static_pointer_cast(packet); std::vector debug_shape_data; - for (auto &debug_shape : debug_shapes) { - if (std::holds_alternative(debug_shape)) { - auto &arrow = std::get(debug_shape); - auto pos = arrow.getPosition(); - auto end_pos = arrow.getEndPosition(); - auto color = arrow.getColor(); - debug_shape_data.push_back({ - arrow.getId(), DebugShapeType::Arrow, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - std::nullopt, std::nullopt, Vec3(end_pos->getX(), end_pos->getY(), end_pos->getZ()), - arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments() - }); - } - if (std::holds_alternative(debug_shape)) { - auto &box = std::get(debug_shape); - auto pos = box.getPosition(); - auto box_bounds = box.getBoxBounds(); - auto color = box.getColor(); - debug_shape_data.push_back({ - box.getId(), DebugShapeType::Box, Vec3(pos->getX(), pos->getY(), pos->getZ()), box.getScale(), std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - std::nullopt, Vec3(box_bounds->getX(), box_bounds->getY(), box_bounds->getZ()), std::nullopt, - std::nullopt, std::nullopt, std::nullopt - }); - } - if (std::holds_alternative(debug_shape)) { - auto &circle = std::get(debug_shape); - auto pos = circle.getPosition(); - auto color = circle.getColor(); - debug_shape_data.push_back({ - circle.getId(), DebugShapeType::Circle, Vec3(pos->getX(), pos->getY(), pos->getZ()), circle.getScale(), std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - std::nullopt, std::nullopt, std::nullopt, - std::nullopt, std::nullopt, circle.getSegments() - }); - } - if (std::holds_alternative(debug_shape)) { - auto &line = std::get(debug_shape); - auto pos = line.getPosition(); - auto end_pos = line.getEndPosition(); - auto color = line.getColor(); - debug_shape_data.push_back({ - line.getId(), DebugShapeType::Line, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - std::nullopt, std::nullopt, Vec3(end_pos->getX(), end_pos->getY(), end_pos->getZ()), - std::nullopt, std::nullopt, std::nullopt - }); + + auto toVec3 = [](const auto &opt) -> std::optional { + if (opt) { + return Vec3(opt->getX(), opt->getY(), opt->getZ()); } - if (std::holds_alternative(debug_shape)) { - auto &sphere = std::get(debug_shape); - auto pos = sphere.getPosition(); - auto color = sphere.getColor(); - debug_shape_data.push_back({ - sphere.getId(), DebugShapeType::Sphere, Vec3(pos->getX(), pos->getY(), pos->getZ()), sphere.getScale(), std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - std::nullopt, std::nullopt, std::nullopt, - std::nullopt, std::nullopt, sphere.getSegments() - }); + 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())); } - if (std::holds_alternative(debug_shape)) { - auto &text = std::get(debug_shape); - auto pos = text.getPosition(); - auto color = text.getColor(); - debug_shape_data.push_back({ - text.getId(), DebugShapeType::Text, Vec3(pos->getX(), pos->getY(), pos->getZ()), std::nullopt, std::nullopt, - std::nullopt, mce::Color(color->getRed(), color->getGreen(), color->getBlue(), color->getAlpha()), - text.getText(), std::nullopt, std::nullopt, - std::nullopt, std::nullopt, std::nullopt - }); + return std::nullopt; + }; + + for (auto &debug_shape : debug_shapes) { + if (std::holds_alternative(debug_shape)) { + auto arrow = std::get(debug_shape); + debug_shape_data.push_back({arrow.getId(), DebugShapeType::Arrow, (toVec3(arrow.getPosition())), {}, {}, {}, 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); + debug_shape_data.push_back({box.getId(), DebugShapeType::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); + debug_shape_data.push_back({circle.getId(), DebugShapeType::Circle, (toVec3(circle.getPosition())), circle.getScale(), {}, {}, toColor(circle.getColor()), {}, {}, {}, {}, {}, circle.getSegments()}); + } else if (std::holds_alternative(debug_shape)) { + auto line = std::get(debug_shape); + debug_shape_data.push_back({line.getId(), DebugShapeType::Line, (toVec3(line.getPosition())), {}, {}, {}, toColor(line.getColor()), {}, {}, toVec3(line.getEndPosition()), {}, {}, {}}); + } else if (std::holds_alternative(debug_shape)) { + auto sphere = std::get(debug_shape); + debug_shape_data.push_back({sphere.getId(), DebugShapeType::Sphere, (toVec3(sphere.getPosition())), sphere.getScale(), {}, {}, toColor(sphere.getColor()), {}, {}, {}, {}, {}, sphere.getSegments()}); + } else if (std::holds_alternative(debug_shape)) { + auto text = std::get(debug_shape); + debug_shape_data.push_back({text.getId(), DebugShapeType::Text, (toVec3(text.getPosition())), {}, {}, {}, toColor(text.getColor()), text.getText(), {}, {}, {}, {}, {}}); } } + pk->shapes = std::move(debug_shape_data); getPlayer().sendNetworkPacket(*pk); } From 31d31356de36aa87120238b1062fd3fe8af85897 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sat, 28 Jun 2025 01:25:13 +0800 Subject: [PATCH 08/17] refactor: rename some variables to match the vanilla --- .../packet/server_script_debug_drawer_packet.h | 10 +++++----- src/endstone/core/player.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bedrock/network/packet/server_script_debug_drawer_packet.h b/src/bedrock/network/packet/server_script_debug_drawer_packet.h index cbd336d5e..e70d53bc1 100644 --- a/src/bedrock/network/packet/server_script_debug_drawer_packet.h +++ b/src/bedrock/network/packet/server_script_debug_drawer_packet.h @@ -18,7 +18,7 @@ #include "bedrock/core/math/vec3.h" #include "bedrock/network/packet.h" -enum class DebugShapeType : std::uint8_t { +enum class ScriptDebugShapeType : std::uint8_t { Line = 0, Box = 1, Sphere = 2, @@ -27,9 +27,9 @@ enum class DebugShapeType : std::uint8_t { Arrow = 5 }; -struct DebugShapeData { - std::int64_t id; - std::optional type; +struct PacketShapeData { + std::int64_t network_id; + std::optional type; std::optional position; std::optional scale; std::optional rotation; @@ -45,5 +45,5 @@ struct DebugShapeData { class ServerScriptDebugDrawerPacket : public Packet { public: - std::vector shapes; + std::vector shapes; }; \ No newline at end of file diff --git a/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index 913da5a74..333628536 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -761,7 +761,7 @@ void EndstonePlayer::sendDebugShapes(std::vector debug_shapes { auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); auto pk = std::static_pointer_cast(packet); - std::vector debug_shape_data; + std::vector packet_shape_data; auto toVec3 = [](const auto &opt) -> std::optional { if (opt) { @@ -781,26 +781,26 @@ void EndstonePlayer::sendDebugShapes(std::vector debug_shapes for (auto &debug_shape : debug_shapes) { if (std::holds_alternative(debug_shape)) { auto arrow = std::get(debug_shape); - debug_shape_data.push_back({arrow.getId(), DebugShapeType::Arrow, (toVec3(arrow.getPosition())), {}, {}, {}, toColor(arrow.getColor()), {}, {}, toVec3(arrow.getEndPosition()), arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments()}); + packet_shape_data.push_back({arrow.getId(), ScriptDebugShapeType::Arrow, (toVec3(arrow.getPosition())), {}, {}, {}, 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); - debug_shape_data.push_back({box.getId(), DebugShapeType::Box, (toVec3(box.getPosition())), box.getScale(), {}, {}, toColor(box.getColor()), {}, toVec3(box.getBoxBounds()), {}, {}, {}, {}}); + 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); - debug_shape_data.push_back({circle.getId(), DebugShapeType::Circle, (toVec3(circle.getPosition())), circle.getScale(), {}, {}, toColor(circle.getColor()), {}, {}, {}, {}, {}, circle.getSegments()}); + 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); - debug_shape_data.push_back({line.getId(), DebugShapeType::Line, (toVec3(line.getPosition())), {}, {}, {}, toColor(line.getColor()), {}, {}, toVec3(line.getEndPosition()), {}, {}, {}}); + 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); - debug_shape_data.push_back({sphere.getId(), DebugShapeType::Sphere, (toVec3(sphere.getPosition())), sphere.getScale(), {}, {}, toColor(sphere.getColor()), {}, {}, {}, {}, {}, sphere.getSegments()}); + 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); - debug_shape_data.push_back({text.getId(), DebugShapeType::Text, (toVec3(text.getPosition())), {}, {}, {}, toColor(text.getColor()), text.getText(), {}, {}, {}, {}, {}}); + packet_shape_data.push_back({text.getId(), ScriptDebugShapeType::Text, (toVec3(text.getPosition())), {}, {}, {}, toColor(text.getColor()), text.getText(), {}, {}, {}, {}, {}}); } } - pk->shapes = std::move(debug_shape_data); + pk->shapes = std::move(packet_shape_data); getPlayer().sendNetworkPacket(*pk); } @@ -813,7 +813,7 @@ void EndstonePlayer::removeDebugShapes(std::vector debug_shap { auto packet = MinecraftPackets::createPacket(MinecraftPacketIds::ServerScriptDebugDrawerPacket); std::shared_ptr pk = std::static_pointer_cast(packet); - std::vector debug_shape_data; + 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())}); From cd4717ecb216474c0716c250e0c593c851c0e7ba Mon Sep 17 00:00:00 2001 From: Vincent Date: Sun, 29 Jun 2025 15:48:21 +0100 Subject: [PATCH 09/17] refactor: update debug drawer packet --- .../server_script_debug_drawer_packet.h | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/bedrock/network/packet/server_script_debug_drawer_packet.h b/src/bedrock/network/packet/server_script_debug_drawer_packet.h index e70d53bc1..552e85d90 100644 --- a/src/bedrock/network/packet/server_script_debug_drawer_packet.h +++ b/src/bedrock/network/packet/server_script_debug_drawer_packet.h @@ -18,32 +18,34 @@ #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 + Arrow = 5, + NumShapeTypes = 6, }; struct PacketShapeData { - std::int64_t network_id; - std::optional type; - std::optional position; - std::optional scale; + std::optional shape_type; + std::optional location; std::optional rotation; - std::optional total_time_left; - std::optional color; + std::optional scale; + std::optional color; + std::optional time_left_total_sec; std::optional text; - std::optional box_bounds; - std::optional line_end_position; + std::optional box_bound; + std::optional end_location; std::optional arrow_head_length; std::optional arrow_head_radius; - std::optional segments; + std::optional num_segments; }; class ServerScriptDebugDrawerPacket : public Packet { public: std::vector shapes; -}; \ No newline at end of file +}; +} // namespace ScriptModuleDebugUtilities From 9c30226535a898ddd7624e6134de251d8b230cac Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 2 Sep 2025 21:55:19 +0800 Subject: [PATCH 10/17] feat: fix build failure --- endstone/_internal/endstone_python.pyi | 276 +++++++++++++++++- include/endstone/debugshape/debug_shape.h | 7 +- .../server_script_debug_drawer_packet.h | 1 + src/endstone/core/player.cpp | 14 +- 4 files changed, 288 insertions(+), 10 deletions(-) diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index 4bc05db47..1f655b2f4 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,264 @@ class DamageSource: """ Get the damage type. """ +class DebugArrow: + """ + Represents a debug arrow. + """ + def __init__(self) -> None: + ... + @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_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 arrow. + """ + @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 arrow. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug arrow. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugArrow: + ... +class DebugBox: + """ + Represents a debug box. + """ + def __init__(self) -> None: + ... + @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 box. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugBox: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug box. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug box. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug circle. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugCircle: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug circle. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug circle. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug line. + """ + @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 line. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug line. + """ + @position.setter + def position(self, arg1: Vector | None) -> DebugLine: + ... +class DebugSphere: + """ + Represents a debug sphere. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug sphere. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugSphere: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug sphere. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug sphere. + """ + @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. + """ + def __init__(self) -> None: + ... + @property + def color(self) -> tuple[int, ...] | None: + """ + Gets or sets the color of the debug text. + """ + @color.setter + def color(self, arg1: tuple[int, ...] | None) -> DebugText: + ... + @property + def id(self) -> int: + """ + Gets the id of the debug text. + """ + @property + def position(self) -> Vector | None: + """ + Gets or sets the position of the debug text. + """ + @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 +3136,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/include/endstone/debugshape/debug_shape.h b/include/endstone/debugshape/debug_shape.h index 4d5c64c96..448a1b9af 100644 --- a/include/endstone/debugshape/debug_shape.h +++ b/include/endstone/debugshape/debug_shape.h @@ -23,7 +23,8 @@ namespace endstone { namespace debugshape_internal { - inline std::atomic id_counter{0}; + // Decreases from the maximum value to avoid conflicts with sapi's id allocation + inline std::atomic id_counter{UINT64_MAX}; } // namespace debugshape_internal /** @@ -31,12 +32,12 @@ namespace debugshape_internal { * * 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 a id, position and color. + * Each debug shape has an id, position and color. */ template class DebugShape { public: - using DebugShapeId = int64_t; + using DebugShapeId = uint64_t; explicit DebugShape() { id_ = --debugshape_internal::id_counter; diff --git a/src/bedrock/network/packet/server_script_debug_drawer_packet.h b/src/bedrock/network/packet/server_script_debug_drawer_packet.h index 552e85d90..48f96d418 100644 --- a/src/bedrock/network/packet/server_script_debug_drawer_packet.h +++ b/src/bedrock/network/packet/server_script_debug_drawer_packet.h @@ -30,6 +30,7 @@ enum class ScriptDebugShapeType : std::uint8_t { }; struct PacketShapeData { + std::uint64_t network_id; std::optional shape_type; std::optional location; std::optional rotation; diff --git a/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index 3e6b26600..bbf1d89da 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -719,6 +719,7 @@ void EndstonePlayer::sendDebugShape(DebugShapeVariant 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; @@ -741,22 +742,22 @@ void EndstonePlayer::sendDebugShapes(std::vector debug_shapes 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())), {}, {}, {}, toColor(arrow.getColor()), {}, {}, toVec3(arrow.getEndPosition()), arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments()}); + packet_shape_data.push_back({arrow.getId(), ScriptDebugShapeType::Arrow, (toVec3(arrow.getPosition())), {}, {}, 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()), {}, {}, {}, {}}); + 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()}); + 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()), {}, {}, {}}); + 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()}); + 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(), {}, {}, {}, {}, {}}); + packet_shape_data.push_back({text.getId(), ScriptDebugShapeType::Text, (toVec3(text.getPosition())), {}, {}, toColor(text.getColor()), {}, text.getText(), {}, {}, {}, {}, {}}); } } @@ -771,6 +772,7 @@ void EndstonePlayer::removeDebugShape(DebugShapeVariant 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; From a8a115de47b85edc657231207ef65a09114ad180 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 2 Sep 2025 21:58:02 +0800 Subject: [PATCH 11/17] feat: add scale property to debug arrow --- include/endstone/debugshape/debug_arrow.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h index 59a8493aa..132c24d4c 100644 --- a/include/endstone/debugshape/debug_arrow.h +++ b/include/endstone/debugshape/debug_arrow.h @@ -111,11 +111,34 @@ class DebugArrow : public DebugShape { 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; + 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 From 48e4279c6769cc16289ab714894adca9df709a3d Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 2 Sep 2025 21:58:02 +0800 Subject: [PATCH 12/17] feat: update EndstonePlayer::sendDebugShapes() --- include/endstone/debugshape/debug_arrow.h | 23 +++++++++++++++++++++++ src/endstone/core/player.cpp | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h index 59a8493aa..132c24d4c 100644 --- a/include/endstone/debugshape/debug_arrow.h +++ b/include/endstone/debugshape/debug_arrow.h @@ -111,11 +111,34 @@ class DebugArrow : public DebugShape { 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; + 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/src/endstone/core/player.cpp b/src/endstone/core/player.cpp index bbf1d89da..711e270ed 100644 --- a/src/endstone/core/player.cpp +++ b/src/endstone/core/player.cpp @@ -742,7 +742,7 @@ void EndstonePlayer::sendDebugShapes(std::vector debug_shapes 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())), {}, {}, toColor(arrow.getColor()), {}, {}, {}, toVec3(arrow.getEndPosition()), arrow.getArrowHeadLength(), arrow.getArrowHeadRadius(), arrow.getArrowHeadSegments()}); + 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()), {}, {}, {}, {}}); From 3f72c3cf463e6e690e18258a24863188ef9f8159 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 2 Sep 2025 22:06:15 +0800 Subject: [PATCH 13/17] feat: update python stub --- endstone/_internal/endstone_python.pyi | 8 ++++++++ src/endstone/python/debug_shape.cpp | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index 1f655b2f4..f91f04bff 100644 --- a/endstone/_internal/endstone_python.pyi +++ b/endstone/_internal/endstone_python.pyi @@ -1122,6 +1122,14 @@ class DebugArrow: 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. diff --git a/src/endstone/python/debug_shape.cpp b/src/endstone/python/debug_shape.cpp index 190632db7..7860e2ec6 100644 --- a/src/endstone/python/debug_shape.cpp +++ b/src/endstone/python/debug_shape.cpp @@ -34,8 +34,9 @@ void init_debug_shape(py::module_ &m) .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); + "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_(m, "DebugBox", "Represents a debug box.") .def(py::init<>()) From b26b9f8fcb87f87fc6adcccbce17a702179df459 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Wed, 3 Sep 2025 09:17:07 +0800 Subject: [PATCH 14/17] feat: add viewers to debug shape (WIP) --- include/endstone/debugshape/debug_arrow.h | 5 ++ include/endstone/debugshape/debug_box.h | 2 + include/endstone/debugshape/debug_circle.h | 2 + include/endstone/debugshape/debug_line.h | 1 + include/endstone/debugshape/debug_shape.h | 66 +++++++++++++++++++- include/endstone/debugshape/debug_sphere.h | 2 + include/endstone/debugshape/debug_text.h | 1 + src/endstone/python/debug_shape.cpp | 70 +++++++++++----------- 8 files changed, 112 insertions(+), 37 deletions(-) diff --git a/include/endstone/debugshape/debug_arrow.h b/include/endstone/debugshape/debug_arrow.h index 132c24d4c..827cdc191 100644 --- a/include/endstone/debugshape/debug_arrow.h +++ b/include/endstone/debugshape/debug_arrow.h @@ -42,6 +42,7 @@ class DebugArrow : public DebugShape { DebugArrow &setEndPosition(const std::optional> end_position) { end_position_ = end_position; + onChange(); return *this; } @@ -64,6 +65,7 @@ class DebugArrow : public DebugShape { DebugArrow &setArrowHeadLength(const std::optional arrow_head_length) { arrow_head_length_ = arrow_head_length; + onChange(); return *this; } @@ -86,6 +88,7 @@ class DebugArrow : public DebugShape { DebugArrow &setArrowHeadRadius(const std::optional arrow_head_radius) { arrow_head_radius_ = arrow_head_radius; + onChange(); return *this; } @@ -108,6 +111,7 @@ class DebugArrow : public DebugShape { DebugArrow &setArrowHeadSegments(const std::optional arrow_head_segments) { arrow_head_segments_ = arrow_head_segments; + onChange(); return *this; } @@ -130,6 +134,7 @@ class DebugArrow : public DebugShape { DebugArrow &setArrowHeadScale(const std::optional arrow_head_scale) { arrow_head_scale_ = arrow_head_scale; + onChange(); return *this; } diff --git a/include/endstone/debugshape/debug_box.h b/include/endstone/debugshape/debug_box.h index cc277a9b4..f1be9e56a 100644 --- a/include/endstone/debugshape/debug_box.h +++ b/include/endstone/debugshape/debug_box.h @@ -42,6 +42,7 @@ class DebugBox : public DebugShape { DebugBox &setScale(const std::optional scale) { scale_ = scale; + onChange(); return *this; } @@ -64,6 +65,7 @@ class DebugBox : public DebugShape { DebugBox &setBoxBounds(const std::optional> box_bounds) { box_bounds_ = box_bounds; + onChange(); return *this; } diff --git a/include/endstone/debugshape/debug_circle.h b/include/endstone/debugshape/debug_circle.h index 787f89ff1..c45710ee2 100644 --- a/include/endstone/debugshape/debug_circle.h +++ b/include/endstone/debugshape/debug_circle.h @@ -43,6 +43,7 @@ class DebugCircle : public DebugShape { DebugCircle &setScale(const std::optional scale) { scale_ = scale; + onChange(); return *this; } @@ -65,6 +66,7 @@ class DebugCircle : public DebugShape { DebugCircle &setSegments(const std::optional segments) { segments_ = segments; + onChange(); return *this; } diff --git a/include/endstone/debugshape/debug_line.h b/include/endstone/debugshape/debug_line.h index 0d682f8a7..d9b5cecf7 100644 --- a/include/endstone/debugshape/debug_line.h +++ b/include/endstone/debugshape/debug_line.h @@ -42,6 +42,7 @@ class DebugLine : public DebugShape { DebugLine &setEndPosition(const std::optional> end_position) { end_position_ = end_position; + onChange(); return *this; } diff --git a/include/endstone/debugshape/debug_shape.h b/include/endstone/debugshape/debug_shape.h index 448a1b9af..650515777 100644 --- a/include/endstone/debugshape/debug_shape.h +++ b/include/endstone/debugshape/debug_shape.h @@ -14,10 +14,14 @@ #pragma once -#include #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 { @@ -72,6 +76,7 @@ class DebugShape { T &setPosition(const std::optional> position) { position_ = position; + onChange(); return *static_cast(this); } @@ -94,13 +99,72 @@ class DebugShape { 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(const Player &player) + { + players_.emplace(player.getUniqueId()); + player.sendDebugShape(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(const Player &player) + { + players_.erase(player.getUniqueId()); + player.removeDebugShape(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_; + std::unordered_set players_; + + void onChange() const + { + for (const auto &player : getPlayers()) { + player->sendDebugShape(this); + } + } }; } // namespace endstone \ No newline at end of file diff --git a/include/endstone/debugshape/debug_sphere.h b/include/endstone/debugshape/debug_sphere.h index 3f59faa7a..29b22bb6e 100644 --- a/include/endstone/debugshape/debug_sphere.h +++ b/include/endstone/debugshape/debug_sphere.h @@ -42,6 +42,7 @@ class DebugSphere : public DebugShape { DebugSphere &setScale(std::optional scale) { scale_ = scale; + onChange(); return *this; } @@ -64,6 +65,7 @@ class DebugSphere : public DebugShape { DebugSphere &setSegments(const std::optional segments) { segments_ = segments; + onChange(); return *this; } diff --git a/include/endstone/debugshape/debug_text.h b/include/endstone/debugshape/debug_text.h index fc5003e5b..40f49ce03 100644 --- a/include/endstone/debugshape/debug_text.h +++ b/include/endstone/debugshape/debug_text.h @@ -44,6 +44,7 @@ class DebugText : public DebugShape { DebugText &setText(const std::string &text) { text_ = text; + onChange(); return *this; } diff --git a/src/endstone/python/debug_shape.cpp b/src/endstone/python/debug_shape.cpp index 7860e2ec6..5f49163bb 100644 --- a/src/endstone/python/debug_shape.cpp +++ b/src/endstone/python/debug_shape.cpp @@ -18,15 +18,28 @@ 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_(m, "DebugArrow", "Represents a debug arrow.") + py::class_ debug_arrow(m, "DebugArrow", "Represents a debug arrow."); + bind_debug_shape_common(debug_arrow); + debug_arrow .def(py::init<>()) - .def_property_readonly("id", &DebugArrow::getId, "Gets the id of the debug arrow.") - .def_property("position", &DebugArrow::getPosition, &DebugArrow::setPosition, - "Gets or sets the position of the debug arrow.", py::return_value_policy::reference) - .def_property("color", &DebugArrow::getColor, &DebugArrow::setColor, - "Gets or sets the color of the debug arrow.", py::return_value_policy::reference) .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, @@ -38,59 +51,44 @@ void init_debug_shape(py::module_ &m) .def_property("arrow_head_scale", &DebugArrow::getArrowHeadScale, &DebugArrow::setArrowHeadScale, "Gets or sets the scale of the arrowhead.", py::return_value_policy::reference); - py::class_(m, "DebugBox", "Represents a debug box.") + py::class_ debug_box(m, "DebugBox", "Represents a debug box."); + bind_debug_shape_common(debug_box); + debug_box .def(py::init<>()) - .def_property_readonly("id", &DebugBox::getId, "Gets the id of the debug box.") - .def_property("position", &DebugBox::getPosition, &DebugBox::setPosition, - "Gets or sets the position of the debug box.", py::return_value_policy::reference) - .def_property("color", &DebugBox::getColor, &DebugBox::setColor, - "Gets or sets the color of the debug box.", py::return_value_policy::reference) .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_(m, "DebugCircle", "Represents a debug circle.") + py::class_ debug_circle(m, "DebugCircle", "Represents a debug circle."); + bind_debug_shape_common(debug_circle); + debug_circle .def(py::init<>()) - .def_property_readonly("id", &DebugCircle::getId, "Gets the id of the debug circle.") - .def_property("position", &DebugCircle::getPosition, &DebugCircle::setPosition, - "Gets or sets the position of the debug circle.", py::return_value_policy::reference) - .def_property("color", &DebugCircle::getColor, &DebugCircle::setColor, - "Gets or sets the color of the debug circle.", py::return_value_policy::reference) .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_(m, "DebugLine", "Represents a debug line.") + py::class_ debug_line(m, "DebugLine", "Represents a debug line."); + bind_debug_shape_common(debug_line); + debug_line .def(py::init<>()) - .def_property_readonly("id", &DebugLine::getId, "Gets the id of the debug line.") - .def_property("position", &DebugLine::getPosition, &DebugLine::setPosition, - "Gets or sets the position of the debug line.", py::return_value_policy::reference) - .def_property("color", &DebugLine::getColor, &DebugLine::setColor, - "Gets or sets the color of the debug line.", py::return_value_policy::reference) .def_property("end_position", &DebugLine::getEndPosition, &DebugLine::setEndPosition, "Gets or sets the end position of the line.", py::return_value_policy::reference); - py::class_(m, "DebugSphere", "Represents a debug sphere.") + py::class_ debug_sphere(m, "DebugSphere", "Represents a debug sphere."); + bind_debug_shape_common(debug_sphere); + debug_sphere .def(py::init<>()) - .def_property_readonly("id", &DebugSphere::getId, "Gets the id of the debug sphere.") - .def_property("position", &DebugSphere::getPosition, &DebugSphere::setPosition, - "Gets or sets the position of the debug sphere.", py::return_value_policy::reference) - .def_property("color", &DebugSphere::getColor, &DebugSphere::setColor, - "Gets or sets the color of the debug sphere.", py::return_value_policy::reference) .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_(m, "DebugText", "Represents a debug text.") + py::class_ debug_text(m, "DebugText", "Represents a debug text."); + bind_debug_shape_common(debug_text); + debug_text .def(py::init<>()) - .def_property_readonly("id", &DebugText::getId, "Gets the id of the debug text.") - .def_property("position", &DebugText::getPosition, &DebugText::setPosition, - "Gets or sets the position of the debug text.", py::return_value_policy::reference) - .def_property("color", &DebugText::getColor, &DebugText::setColor, - "Gets or sets the color of the debug text.", py::return_value_policy::reference) .def_property("text", &DebugText::getText, &DebugText::setText, "Gets or sets the text of the debug text.", py::return_value_policy::reference); } From 19701157f076124310119d8cf28be583a8996562 Mon Sep 17 00:00:00 2001 From: Dofes <91889957+Dofes@users.noreply.github.com> Date: Wed, 3 Sep 2025 23:18:04 +0800 Subject: [PATCH 15/17] fix: fix compile --- include/endstone/debugshape/debug_shape.h | 18 +++++++++--------- include/endstone/player.h | 13 +++++++------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/endstone/debugshape/debug_shape.h b/include/endstone/debugshape/debug_shape.h index 650515777..f8f1b11e9 100644 --- a/include/endstone/debugshape/debug_shape.h +++ b/include/endstone/debugshape/debug_shape.h @@ -27,8 +27,8 @@ 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}; +// Decreases from the maximum value to avoid conflicts with sapi's id allocation +inline std::atomic id_counter{UINT64_MAX}; } // namespace debugshape_internal /** @@ -107,20 +107,20 @@ class DebugShape { * @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(const Player &player) + void addPlayer(Player &player) { players_.emplace(player.getUniqueId()); - player.sendDebugShape(this); + 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(const Player &player) + void removePlayer(Player &player) { players_.erase(player.getUniqueId()); - player.removeDebugShape(this); + player.removeDebugShape(static_cast(*this)); } /** @@ -157,14 +157,14 @@ class DebugShape { DebugShapeId id_; std::optional> position_; std::optional color_; - std::unordered_set players_; + mutable std::unordered_set players_; void onChange() const { for (const auto &player : getPlayers()) { - player->sendDebugShape(this); + player->sendDebugShape(static_cast(*this)); } } }; -} // namespace endstone \ No newline at end of file +} // namespace endstone diff --git a/include/endstone/player.h b/include/endstone/player.h index e75031719..3a5781848 100644 --- a/include/endstone/player.h +++ b/include/endstone/player.h @@ -21,12 +21,6 @@ #include "endstone/form/action_form.h" #include "endstone/form/message_form.h" #include "endstone/form/modal_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" #include "endstone/game_mode.h" #include "endstone/inventory/player_inventory.h" #include "endstone/offline_player.h" @@ -37,6 +31,13 @@ namespace endstone { +class DebugArrow; +class DebugBox; +class DebugCircle; +class DebugLine; +class DebugSphere; +class DebugText; + /** * @brief Represents a player. */ From b4a587cc459fe569fcec388e7eec5ccd1cf5e7f5 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 4 Sep 2025 01:16:20 +0800 Subject: [PATCH 16/17] feat: update python stub --- endstone/_internal/endstone_python.pyi | 162 ++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 18 deletions(-) diff --git a/endstone/_internal/endstone_python.pyi b/endstone/_internal/endstone_python.pyi index f91f04bff..fba97d79a 100644 --- a/endstone/_internal/endstone_python.pyi +++ b/endstone/_internal/endstone_python.pyi @@ -1103,8 +1103,24 @@ 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: """ @@ -1140,7 +1156,7 @@ class DebugArrow: @property def color(self) -> tuple[int, ...] | None: """ - Gets or sets the color of the debug arrow. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugArrow: @@ -1156,12 +1172,17 @@ class DebugArrow: @property def id(self) -> int: """ - Gets the id of the debug arrow. + 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 arrow. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugArrow: @@ -1170,8 +1191,24 @@ 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: """ @@ -1183,7 +1220,7 @@ class DebugBox: @property def color(self) -> tuple[int, ...] | None: """ - Gets or sets the color of the debug box. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugBox: @@ -1191,12 +1228,17 @@ class DebugBox: @property def id(self) -> int: """ - Gets the id of the debug box. + 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 box. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugBox: @@ -1213,12 +1255,28 @@ 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 circle. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugCircle: @@ -1226,12 +1284,17 @@ class DebugCircle: @property def id(self) -> int: """ - Gets the id of the debug circle. + 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 circle. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugCircle: @@ -1256,12 +1319,28 @@ 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 line. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugLine: @@ -1277,12 +1356,17 @@ class DebugLine: @property def id(self) -> int: """ - Gets the id of the debug line. + 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 line. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugLine: @@ -1291,12 +1375,28 @@ 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 sphere. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugSphere: @@ -1304,12 +1404,17 @@ class DebugSphere: @property def id(self) -> int: """ - Gets the id of the debug sphere. + 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 sphere. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugSphere: @@ -1334,12 +1439,28 @@ 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 text. + Gets or sets the color of the debug shape. """ @color.setter def color(self, arg1: tuple[int, ...] | None) -> DebugText: @@ -1347,12 +1468,17 @@ class DebugText: @property def id(self) -> int: """ - Gets the id of the debug text. + 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 text. + Gets or sets the position of the debug shape. """ @position.setter def position(self, arg1: Vector | None) -> DebugText: From 693d3a5d5e40855b4f20319da8906bbaf0ab051b Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Thu, 4 Sep 2025 01:51:32 +0800 Subject: [PATCH 17/17] docs: add debug shape to python reference --- docs/reference/python/debug_shape.md | 1 + mkdocs.yml | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/reference/python/debug_shape.md diff --git a/docs/reference/python/debug_shape.md b/docs/reference/python/debug_shape.md new file mode 100644 index 000000000..82905c3e2 --- /dev/null +++ b/docs/reference/python/debug_shape.md @@ -0,0 +1 @@ +::: endstone.debug_shape \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 1e8d4736f..024a0822b 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