Add /redo command (#1238)

* Add undo and redo commands

* Remove unintended change

* Remove redo code

* Revert "Remove redo code"

This reverts commit 80aeca1dc2d0f7b3f3570b95937a8f7fd87cac5d.

* Fix variable name in /redo

* Update import
This commit is contained in:
Krzysztof Wiśniewski 2025-03-30 17:03:19 +02:00 committed by GitHub
parent 1b7102768f
commit a7052d25f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 56 additions and 1 deletions

View File

@ -7,6 +7,7 @@ pub const time = @import("time.zig");
pub const tp = @import("tp.zig"); pub const tp = @import("tp.zig");
pub const undo = @import("worldedit/undo.zig"); pub const undo = @import("worldedit/undo.zig");
pub const redo = @import("worldedit/redo.zig");
pub const pos1 = @import("worldedit/pos1.zig"); pub const pos1 = @import("worldedit/pos1.zig");
pub const pos2 = @import("worldedit/pos2.zig"); pub const pos2 = @import("worldedit/pos2.zig");
pub const deselect = @import("worldedit/deselect.zig"); pub const deselect = @import("worldedit/deselect.zig");

View File

@ -31,6 +31,7 @@ pub fn execute(args: []const u8, source: *User) void {
switch(undo) { switch(undo) {
.success => |blueprint| { .success => |blueprint| {
source.worldEditData.undoHistory.push(.init(blueprint, pos, "paste")); source.worldEditData.undoHistory.push(.init(blueprint, pos, "paste"));
source.worldEditData.redoHistory.clear();
}, },
.failure => { .failure => {
source.sendMessage("#ff0000Error: Could not capture undo history.", .{}); source.sendMessage("#ff0000Error: Could not capture undo history.", .{});

View File

@ -0,0 +1,37 @@
const std = @import("std");
const main = @import("main");
const User = main.server.User;
const Block = main.blocks.Block;
const Blueprint = main.blueprint.Blueprint;
pub const description = "Redo last change done to world with world editing commands.";
pub const usage = "/redo";
pub fn execute(args: []const u8, source: *User) void {
if(args.len != 0) {
source.sendMessage("#ff0000Too many arguments for command /redo. Expected no arguments.", .{});
return;
}
if(source.worldEditData.redoHistory.pop()) |action| {
const undo = Blueprint.capture(main.globalAllocator, action.position, .{
action.position[0] + @as(i32, @intCast(action.blueprint.blocks.width)) - 1,
action.position[1] + @as(i32, @intCast(action.blueprint.blocks.depth)) - 1,
action.position[2] + @as(i32, @intCast(action.blueprint.blocks.height)) - 1,
});
action.blueprint.paste(action.position);
switch(undo) {
.success => |blueprint| {
source.worldEditData.undoHistory.push(.init(blueprint, action.position, action.message));
},
.failure => {
source.sendMessage("#ff0000Error: Could not capture undo history.", .{});
},
}
source.sendMessage("#00ff00Re-done last {s}.", .{action.message});
} else {
source.sendMessage("#ccccccNothing to redo.", .{});
}
}

View File

@ -15,7 +15,21 @@ pub fn execute(args: []const u8, source: *User) void {
return; return;
} }
if(source.worldEditData.undoHistory.pop()) |action| { if(source.worldEditData.undoHistory.pop()) |action| {
const redo = Blueprint.capture(main.globalAllocator, action.position, .{
action.position[0] + @as(i32, @intCast(action.blueprint.blocks.width)) - 1,
action.position[1] + @as(i32, @intCast(action.blueprint.blocks.depth)) - 1,
action.position[2] + @as(i32, @intCast(action.blueprint.blocks.height)) - 1,
});
action.blueprint.paste(action.position); action.blueprint.paste(action.position);
switch(redo) {
.success => |blueprint| {
source.worldEditData.redoHistory.push(.init(blueprint, action.position, action.message));
},
.failure => {
source.sendMessage("#ff0000Error: Could not capture redo history.", .{});
},
}
source.sendMessage("#00ff00Un-done last {s}.", .{action.message}); source.sendMessage("#00ff00Un-done last {s}.", .{action.message});
} else { } else {
source.sendMessage("#ccccccNothing to undo.", .{}); source.sendMessage("#ccccccNothing to undo.", .{});

View File

@ -30,6 +30,7 @@ pub const WorldEditData = struct {
selectionPosition2: ?Vec3i = null, selectionPosition2: ?Vec3i = null,
clipboard: ?Blueprint = null, clipboard: ?Blueprint = null,
undoHistory: History, undoHistory: History,
redoHistory: History,
const History = struct { const History = struct {
changes: CircularBufferQueue(Value), changes: CircularBufferQueue(Value),
@ -69,13 +70,14 @@ pub const WorldEditData = struct {
} }
}; };
pub fn init() WorldEditData { pub fn init() WorldEditData {
return .{.undoHistory = History.init()}; return .{.undoHistory = History.init(), .redoHistory = History.init()};
} }
pub fn deinit(self: *WorldEditData) void { pub fn deinit(self: *WorldEditData) void {
if(self.clipboard != null) { if(self.clipboard != null) {
self.clipboard.?.deinit(main.globalAllocator); self.clipboard.?.deinit(main.globalAllocator);
} }
self.undoHistory.deinit(); self.undoHistory.deinit();
self.redoHistory.deinit();
} }
}; };