Skip to content

Wand stack#7

Open
MakiTazo wants to merge 3 commits into
iciency:mainfrom
MakiTazo:wand-stack
Open

Wand stack#7
MakiTazo wants to merge 3 commits into
iciency:mainfrom
MakiTazo:wand-stack

Conversation

@MakiTazo
Copy link
Copy Markdown

@MakiTazo MakiTazo commented May 9, 2026

Fixes the main issue with the wand using the normal wooden axe instead a cutom NBT item.
I also added a /stack implementation (TODO: Adding multistack /stack )

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Implement stack command and fix wand NBT identification

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Implemented /stack command to clone selected areas in player direction
• Fixed wand tool to use custom NBT tag instead of vanilla wooden axe
• Enhanced wand item with display name, lore, and NBT verification
• Updated wand detection logic to check NBT tag for proper identification
• Added mcstructures path configuration for future implementation
Diagram
flowchart LR
  A["Wand Command"] -->|"Add NBT Tag"| B["Custom Wand Item"]
  B -->|"Verify NBT"| C["Block Break Handler"]
  C -->|"Check worldedit Tag"| D["Set pos1"]
  E["Player Interact"] -->|"Check NBT"| F["Set pos2"]
  G["Stack Command"] -->|"Get Direction"| H["Calculate Offset"]
  H -->|"Clone Blocks"| I["Async/Sync Operation"]
Loading

Grey Divider

File Changes

1. src/endstone_worldedit/commands/stack.py ✨ Enhancement +116/-0

New stack command with directional cloning

• New command implementation for cloning selected areas in player-facing direction
• Calculates direction based on player yaw (NORTH, SOUTH, EAST, WEST)
• Supports both synchronous and asynchronous block operations based on async-threshold
• Maintains undo/redo history for all stack operations

src/endstone_worldedit/commands/stack.py


2. src/endstone_worldedit/commands/wand.py 🐞 Bug fix +13/-3

Enhanced wand with NBT tag and metadata

• Added NBT tag ("worldedit": "wand") to distinguish custom wand from vanilla wooden axe
• Enhanced wand item with display name "§bWand Tool" and lore instructions
• Applied item metadata to improve user experience and tool identification
• Added debug logging for NBT verification

src/endstone_worldedit/commands/wand.py


3. src/endstone_worldedit/plugin.py 🐞 Bug fix +7/-4

Update wand verification and add mcstructures config

• Updated API version from 0.10 to 0.11
• Modified wand detection in on_block_break to verify NBT tag instead of item type
• Modified wand detection in on_player_interact to verify NBT tag instead of item type
• Added mcstructures-path configuration option for future mcstructures support
• Added TODO comment for mcstructures load implementation

src/endstone_worldedit/plugin.py


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 9, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0)

Grey Divider


Action required

1. Stack out-of-bounds crash 🐞 Bug ☼ Reliability
Description
/stack reads destination blocks via dimension.get_block_at() to build undo history before executing,
but destination coordinates are computed by applying an offset and can go out of bounds, causing an
unhandled RuntimeError and aborting the command. This happens before async execution/error handling
kicks in, so it can hard-fail the command and potentially spam server logs.
Code

src/endstone_worldedit/commands/stack.py[R53-87]

+    if direction == BlockFace.NORTH:
+        offset = (0, 0, -length)
+
+    elif direction == BlockFace.SOUTH:
+        offset = (0, 0, length)
+
+    elif direction == BlockFace.WEST:
+        offset = (-width, 0, 0)
+
+    elif direction == BlockFace.EAST:
+        offset = (width, 0, 0)
+
+    else:
+        sender.send_message("Unsupported direction.")
+        return False
+
+    for x, y, z, block_type, block_data in original_blocks:
+        new_x = x + offset[0]
+        new_y = y + offset[1]
+        new_z = z + offset[2]
+
+        blocks_to_change.append((
+            new_x,
+            new_y,
+            new_z,
+            block_type,
+            block_data
+        ))
+
+    affected_blocks = len(blocks_to_change)
+
+    for x, y, z, _, _ in blocks_to_change:
+        block = dimension.get_block_at(x, y, z)
+        undo_entry.append((x, y, z, block.type, block.data))
+
Evidence
The command computes destination coordinates by applying an offset based on selection size, then
immediately calls get_block_at() on those destination coordinates to capture undo state, with no
try/except. The plugin’s async runner explicitly catches RuntimeError around get_block_at/set_type,
indicating these calls can raise, but /stack’s pre-flight undo capture is not protected.

src/endstone_worldedit/commands/stack.py[53-87]
src/endstone_worldedit/plugin.py[176-213]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`/stack` calls `dimension.get_block_at()` on destination coordinates to build undo history and during sync placement, but destination coordinates can be outside valid world bounds. This can raise `RuntimeError` and abort the command.

### Issue Context
`run_tasks()` already anticipates `RuntimeError` during async placement and catches it, but `/stack` performs destination `get_block_at()` calls *before* deciding async vs sync (undo capture), and the sync placement path also lacks error handling.

### Fix Focus Areas
- src/endstone_worldedit/commands/stack.py[53-110]
- src/endstone_worldedit/plugin.py[176-213]

### Implementation notes
- Wrap destination `get_block_at()` calls (undo capture and sync placement) in `try/except RuntimeError` and either:
 - skip invalid blocks (consistent with `run_tasks()` behavior), or
 - abort the command cleanly with a user-facing message before recording undo history.
- Consider sharing a helper that validates a coordinate or returns `None`/raises a handled exception, to keep behavior consistent across sync and async paths.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Stack ignores vertical look 🐞 Bug ≡ Correctness
Description
/stack says it clones “to the direction you are looking,” but it only uses yaw (cardinal horizontal
facing) and always uses a Y offset of 0, so looking up/down still stacks horizontally. This is a
behavior/documentation mismatch and prevents vertical stacking.
Code

src/endstone_worldedit/commands/stack.py[R6-63]

+        "description": "Clone the selected area to the direction you are looking.",
+        "usages": ["/stack"],
+        "permissions": ["worldedit.command.stack"]
+    }
+}
+
+@command_executor("stack", selection_required=True)
+def handler(plugin, sender, args):
+    # TODO: Add support for stacking
+    player_uuid = sender.unique_id
+    pos1 = plugin.selections[player_uuid]['pos1']
+    pos2 = plugin.selections[player_uuid]['pos2']
+
+    dimension = sender.dimension
+    
+    yaw = sender.location.yaw % 360
+    
+    if 315 <= yaw or yaw < 45:
+        direction = BlockFace.SOUTH
+    elif 45 <= yaw < 135:
+        direction = BlockFace.WEST
+    elif 135 <= yaw < 225:
+        direction = BlockFace.NORTH
+    elif 225 <= yaw < 315:
+        direction = BlockFace.EAST
+    else:
+        direction = BlockFace.SOUTH
+
+    undo_entry = []
+    plugin.redo_history[player_uuid] = []
+
+    original_blocks = []
+    blocks_to_change = []
+
+    min_x, max_x = min(pos1[0], pos2[0]), max(pos1[0], pos2[0])
+    min_y, max_y = min(pos1[1], pos2[1]), max(pos1[1], pos2[1])
+    min_z, max_z = min(pos1[2], pos2[2]), max(pos1[2], pos2[2])
+
+    width = max_x - min_x + 1
+    length = max_z - min_z + 1
+
+    for x in range(int(min_x), int(max_x) + 1):
+        for y in range(int(min_y), int(max_y) + 1):
+            for z in range(int(min_z), int(max_z) + 1):
+                block = dimension.get_block_at(x, y, z)
+                original_blocks.append((x, y, z, block.type, block.data))
+
+    if direction == BlockFace.NORTH:
+        offset = (0, 0, -length)
+
+    elif direction == BlockFace.SOUTH:
+        offset = (0, 0, length)
+
+    elif direction == BlockFace.WEST:
+        offset = (-width, 0, 0)
+
+    elif direction == BlockFace.EAST:
+        offset = (width, 0, 0)
Evidence
Direction selection is derived exclusively from sender.location.yaw, and the chosen offsets only
modify X/Z while Y is always 0, so vertical stacking can never occur.

src/endstone_worldedit/commands/stack.py[5-8]
src/endstone_worldedit/commands/stack.py[21-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`/stack` determines direction using yaw only and never stacks up/down, despite claiming it uses the direction the player is looking.

### Issue Context
Current offset computation always uses `(…, 0, …)` so the Y axis is never affected.

### Fix Focus Areas
- src/endstone_worldedit/commands/stack.py[21-67]

### Implementation notes
- Either update the command description to explicitly say "horizontal direction" OR
- Add pitch handling:
 - If pitch indicates looking up/down beyond a threshold, use `BlockFace.UP` / `BlockFace.DOWN` and compute `offset = (0, height, 0)` where `height = (max_y - min_y + 1)`.
 - Keep existing yaw logic for horizontal directions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Wand logs errors on use 🐞 Bug ◔ Observability
Description
The /wand command logs the wand’s NBT using logger.error on the normal success path, which will
pollute error logs and can trigger false alerting. This should not be an ERROR-level log (or should
be removed).
Code

src/endstone_worldedit/commands/wand.py[R22-25]

+    nbt = CompoundTag({"worldedit": StringTag("wand")})
+    wand_item.nbt = nbt
+    plugin.logger.error(str(wand_item.nbt))
+    sender.inventory.add_item(wand_item)
Evidence
plugin.logger.error(...) is executed unconditionally whenever a player runs /wand, even though
it is not an error condition.

src/endstone_worldedit/commands/wand.py[16-26]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`/wand` logs NBT at ERROR level on successful execution, creating noisy error logs.

### Issue Context
This appears to be a debug statement left in place.

### Fix Focus Areas
- src/endstone_worldedit/commands/wand.py[22-25]

### Implementation notes
- Remove the log line entirely, or change it to `plugin.logger.debug(...)` behind a debug flag/config option.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread src/endstone_worldedit/commands/stack.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant