mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Add /rotate
command (#1225)
* Revert "Remove rotate command" This reverts commit 3a84e03d158e5cc038ae3e936384c348431a9ac4. * Fix stair rotation * Add rotate fn to Blueprint * Apply suggestions from code review Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Replace cos sin with switch * Add angle parameter to /rotate * Update src/blueprint.zig * Apply review suggestions * Fix formatting issues * Update src/rotation.zig --------- Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
This commit is contained in:
parent
e815d98b89
commit
5845da7ca9
@ -10,6 +10,8 @@ const Array3D = main.utils.Array3D;
|
|||||||
const Block = main.blocks.Block;
|
const Block = main.blocks.Block;
|
||||||
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
|
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
|
||||||
const User = main.server.User;
|
const User = main.server.User;
|
||||||
|
const ServerChunk = main.chunk.ServerChunk;
|
||||||
|
const Degrees = main.rotation.Degrees;
|
||||||
|
|
||||||
const GameIdToBlueprintIdMapType = std.AutoHashMap(u16, u16);
|
const GameIdToBlueprintIdMapType = std.AutoHashMap(u16, u16);
|
||||||
const BlockIdSizeType = u32;
|
const BlockIdSizeType = u32;
|
||||||
@ -36,6 +38,32 @@ pub const Blueprint = struct {
|
|||||||
pub fn clone(self: *Blueprint, allocator: NeverFailingAllocator) Blueprint {
|
pub fn clone(self: *Blueprint, allocator: NeverFailingAllocator) Blueprint {
|
||||||
return .{.blocks = self.blocks.clone(allocator)};
|
return .{.blocks = self.blocks.clone(allocator)};
|
||||||
}
|
}
|
||||||
|
pub fn rotateZ(self: Blueprint, allocator: NeverFailingAllocator, angle: Degrees) Blueprint {
|
||||||
|
var new = Blueprint{
|
||||||
|
.blocks = switch(angle) {
|
||||||
|
.@"0", .@"180" => .init(allocator, self.blocks.width, self.blocks.depth, self.blocks.height),
|
||||||
|
.@"90", .@"270" => .init(allocator, self.blocks.depth, self.blocks.width, self.blocks.height),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for(0..self.blocks.width) |xOld| {
|
||||||
|
for(0..self.blocks.depth) |yOld| {
|
||||||
|
const xNew, const yNew = switch(angle) {
|
||||||
|
.@"0" => .{xOld, yOld},
|
||||||
|
.@"90" => .{new.blocks.width - yOld - 1, xOld},
|
||||||
|
.@"180" => .{new.blocks.width - xOld - 1, new.blocks.depth - yOld - 1},
|
||||||
|
.@"270" => .{yOld, new.blocks.depth - xOld - 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
for(0..self.blocks.height) |z| {
|
||||||
|
const block = self.blocks.get(xOld, yOld, z);
|
||||||
|
new.blocks.set(xNew, yNew, z, block.rotateZ(angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
const CaptureResult = union(enum) {
|
const CaptureResult = union(enum) {
|
||||||
success: Blueprint,
|
success: Blueprint,
|
||||||
failure: struct {pos: Vec3i, message: []const u8},
|
failure: struct {pos: Vec3i, message: []const u8},
|
||||||
|
@ -806,7 +806,7 @@ pub const RotationModes = struct {
|
|||||||
comptime var rotationTable: [4][256]u8 = undefined;
|
comptime var rotationTable: [4][256]u8 = undefined;
|
||||||
comptime for(0..4) |a| {
|
comptime for(0..4) |a| {
|
||||||
for(0..256) |old| {
|
for(0..256) |old| {
|
||||||
var new: u8 = 0;
|
var new: u8 = 0b11_11_11_11;
|
||||||
|
|
||||||
for(0..2) |i| for(0..2) |j| for(0..2) |k| {
|
for(0..2) |i| for(0..2) |j| for(0..2) |k| {
|
||||||
const sin: f32 = @sin((std.math.pi/2.0)*@as(f32, @floatFromInt(a)));
|
const sin: f32 = @sin((std.math.pi/2.0)*@as(f32, @floatFromInt(a)));
|
||||||
@ -819,7 +819,7 @@ pub const RotationModes = struct {
|
|||||||
const rY = @intFromBool(x*sin + y*cos > 0);
|
const rY = @intFromBool(x*sin + y*cos > 0);
|
||||||
|
|
||||||
if(hasSubBlock(@intCast(old), @intCast(i), @intCast(j), @intCast(k))) {
|
if(hasSubBlock(@intCast(old), @intCast(i), @intCast(j), @intCast(k))) {
|
||||||
new |= subBlockMask(rX, rY, @intCast(k));
|
new &= ~subBlockMask(rX, rY, @intCast(k));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
rotationTable[a][old] = new;
|
rotationTable[a][old] = new;
|
||||||
|
@ -12,3 +12,4 @@ pub const deselect = @import("worldedit/deselect.zig");
|
|||||||
pub const copy = @import("worldedit/copy.zig");
|
pub const copy = @import("worldedit/copy.zig");
|
||||||
pub const paste = @import("worldedit/paste.zig");
|
pub const paste = @import("worldedit/paste.zig");
|
||||||
pub const blueprint = @import("worldedit/blueprint.zig");
|
pub const blueprint = @import("worldedit/blueprint.zig");
|
||||||
|
pub const rotate = @import("worldedit/rotate.zig");
|
||||||
|
28
src/server/command/worldedit/rotate.zig
Normal file
28
src/server/command/worldedit/rotate.zig
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const main = @import("root");
|
||||||
|
const User = main.server.User;
|
||||||
|
const Degrees = main.rotation.Degrees;
|
||||||
|
|
||||||
|
pub const description = "rotate clipboard content around Z axis counterclockwise.";
|
||||||
|
pub const usage =
|
||||||
|
\\/rotate
|
||||||
|
\\/rotate <0/90/180/270>
|
||||||
|
;
|
||||||
|
|
||||||
|
pub fn execute(args: []const u8, source: *User) void {
|
||||||
|
var angle: Degrees = .@"90";
|
||||||
|
if(args.len != 0) {
|
||||||
|
angle = std.meta.stringToEnum(Degrees, args) orelse {
|
||||||
|
source.sendMessage("#ff0000Error: Invalid angle '{s}'. Use 0, 90, 180 or 270.", .{args});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if(source.worldEditData.clipboard == null) {
|
||||||
|
source.sendMessage("#ff0000Error: No clipboard content to rotate.", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const current = source.worldEditData.clipboard.?;
|
||||||
|
defer current.deinit(main.globalAllocator);
|
||||||
|
source.worldEditData.clipboard = current.rotateZ(main.globalAllocator, angle);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user