Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/server/command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ pub const Coordinate = union(enum) {
}
};

pub const Rotation = union(enum) {
relative: f32, // Relative rotations are indicated by leading `~`.
absolute: f32,

pub fn parse(_: NeverFailingAllocator, name: []const u8, arg: []const u8, errorMessage: *ListManaged(u8)) error{ParseError}!Rotation {
const isRelative = arg[0] == '~';
const numberSlice = if (isRelative) arg[1..] else arg;
if (isRelative and numberSlice.len == 0) return .{.relative = 0};
if (isRelative) {
return .{.relative = std.fmt.parseFloat(f32, numberSlice) catch {
errorMessage.print("Expected number for <{s}>, found \"{s}\"", .{name, numberSlice});
return error.ParseError;
}};
}
return .{.absolute = std.fmt.parseFloat(f32, numberSlice) catch {
errorMessage.print("Expected number or \"~\" for <{s}>, found \"{s}\"", .{name, arg});
return error.ParseError;
}};
}
};

pub fn resolveCoordinates(x: Coordinate, y: Coordinate, z: Coordinate, source: Source) error{InvalidArg}!main.vec.Vec3d {
if (source != .user and (x == .relative or y == .relative or z == .relative)) {
source.sendMessage("Command was run without a user; unable to interpret relative coordinates.", .{});
Expand All @@ -121,6 +142,19 @@ pub fn resolveCoordinates(x: Coordinate, y: Coordinate, z: Coordinate, source: S
};
}

pub fn resolveRotation(yaw: Rotation, pitch: Rotation, source: Source) error{InvalidArg}!main.vec.Vec3f {
if (source != .user and (yaw == .relative or pitch == .relative)) {
source.sendMessage("Command was run without a user; unable to interpret relative rotation.", .{});
return error.InvalidArg;
}
const bound = std.math.pi/2.0 - 0.001;
return .{
std.math.clamp(if (yaw == .relative) source.user.player().rot[0] + yaw.relative*std.math.pi/180 else yaw.absolute*std.math.pi/180, -bound, bound),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do the conversion from degrees during parsing, also there is a helper function in std.math for this, which is more readable.

0,
if (pitch == .relative) source.user.player().rot[2] + @mod(pitch.relative, 360)*std.math.pi/180 else @mod(pitch.absolute, 360)*std.math.pi/180,
};
}

pub const Target = struct {
user: *User,

Expand Down
18 changes: 17 additions & 1 deletion src/server/command/tp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub const usage =
\\/tp @<sourcePlayerIndex> <x> <y> <z>
\\/tp @<destinationPlayerIndex>
\\/tp @<sourcePlayerIndex> @<destinationPlayerIndex>
\\/tp <x> <y> <z> <yaw> <pitch>
\\/tp @<sourcePlayerIndex> <x> <y> <z> <yaw> <pitch>
;

pub const Args = union(enum) {
Expand All @@ -32,12 +34,21 @@ pub const Args = union(enum) {
sourcePlayerIndex: command.PlayerIndex,
destinationPlayerIndex: command.PlayerIndex,
},
@"/tp <sourcePlayerIndex> <x> <y> <z> <yaw> <pitch>": struct {
Comment thread
Mabeeck marked this conversation as resolved.
sourcePlayerIndex: ?command.PlayerIndex,
x: command.Coordinate,
y: command.Coordinate,
z: command.Coordinate,
yaw: command.Rotation,
pitch: command.Rotation,
},
};

pub fn execute(args: Args, source: Source) void {
const target = switch (args) {
inline .@"/tp <sourcePlayerIndex> <biome>",
.@"/tp <sourcePlayerIndex> <x> <y> <z>",
.@"/tp <sourcePlayerIndex> <x> <y> <z> <yaw> <pitch>",
.@"/tp <sourcePlayerIndex> <destinationPlayerIndex>",
=> |params| command.Target.fromPlayerIndex(params.sourcePlayerIndex, source) catch return,
else => command.Target.fromPlayerIndex(null, source) catch return,
Expand Down Expand Up @@ -99,10 +110,15 @@ pub fn execute(args: Args, source: Source) void {
.@"/tp <sourcePlayerIndex> <x> <y> <z>" => |pos| {
break :blk command.resolveCoordinates(pos.x, pos.y, pos.z, source) catch return;
},
.@"/tp <sourcePlayerIndex> <x> <y> <z> <yaw> <pitch>" => |pos| {
main.sync.server.sendSyncOperation(.{.rotation = .{.target = target.user, .rotation = command.resolveRotation(pos.yaw, pos.pitch, source) catch return}}, null);
break :blk command.resolveCoordinates(pos.x, pos.y, pos.z, source) catch return;
},
inline .@"/tp <destinationPlayerIndex>", .@"/tp <sourcePlayerIndex> <destinationPlayerIndex>" => |index| {
const dest = command.Target.fromPlayerIndex(index.destinationPlayerIndex, source) catch return;
break :blk dest.user.player().pos;
},
};
main.network.protocols.genericUpdate.sendTPCoordinates(target.user.conn, pos);

if (!std.meta.eql(target.user.player().pos, pos)) main.network.protocols.genericUpdate.sendTPCoordinates(target.user.conn, pos);
}
45 changes: 33 additions & 12 deletions src/sync.zig
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ pub const server = struct { // MARK: server
threadContext = .other;
}

pub fn sendSyncOperation(op: Command.SyncOperation, source: ?*main.server.User) void {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead we should have a helper function that allows sending a sync operation to clients directly.

You mean like this?

const syncData = op.serialize(main.stackAllocator);
defer main.stackAllocator.free(syncData);

const users = op.getUsers(main.stackAllocator);
defer main.stackAllocator.free(users);

for (users) |user| {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this should only be sent to one user, you are sending it to all users, so everyone's rotation will get changed when executed.

I would suggest to not try to deduplicate code here, this function should just take a single user and only send it to that single user.

if (user == source and op.ignoreSource()) continue;
main.network.protocols.inventory.sendSyncOperation(user.conn, syncData);
}
}

pub fn executeCommand(payload: Command.Payload, source: ?*main.server.User) void {
var command = Command{
.payload = payload,
Expand All @@ -153,16 +166,7 @@ pub const server = struct { // MARK: server
main.network.protocols.inventory.sendConfirmation(source.?.conn, confirmationData);
}
for (command.syncOperations.items) |op| {
const syncData = op.serialize(main.stackAllocator);
defer main.stackAllocator.free(syncData);

const users = op.getUsers(main.stackAllocator);
defer main.stackAllocator.free(users);

for (users) |user| {
if (user == source and op.ignoreSource()) continue;
main.network.protocols.inventory.sendSyncOperation(user.conn, syncData);
}
sendSyncOperation(op, source);
}
if (source != null and command.payload == .open) { // Send initial items
for (command.payload.open.inv._items, 0..) |stack, slot| {
Expand Down Expand Up @@ -333,6 +337,7 @@ pub const Command = struct { // MARK: Command
health = 3,
kill = 4,
energy = 5,
rotation = 6,
};

const SyncOperation = union(SyncOperationType) { // MARK: SyncOperation
Expand Down Expand Up @@ -362,6 +367,10 @@ pub const Command = struct { // MARK: Command
target: ?*main.server.User,
energy: f32,
},
rotation: struct {
target: ?*main.server.User,
rotation: Vec3f,
},

pub fn executeFromData(reader: *BinaryReader) !void {
switch (try deserialize(reader)) {
Expand Down Expand Up @@ -408,6 +417,9 @@ pub const Command = struct { // MARK: Command
.energy => |energy| {
main.game.Player.super.energy = std.math.clamp(main.game.Player.super.energy + energy.energy, 0, main.game.Player.super.maxEnergy);
},
.rotation => |rotation| {
main.game.camera.rotation = rotation.rotation;
},
}
}

Expand All @@ -421,7 +433,7 @@ pub const Command = struct { // MARK: Command
}
return result;
},
inline .health, .kill, .energy => |data| {
inline .health, .kill, .energy, .rotation => |data| {
const out = allocator.alloc(*main.server.User, 1);
out[0] = data.target.?;
return out;
Expand All @@ -431,7 +443,7 @@ pub const Command = struct { // MARK: Command

pub fn ignoreSource(self: SyncOperation) bool {
return switch (self) {
.create, .delete, .useDurability, .health, .energy => true,
.create, .delete, .useDurability, .health, .energy, .rotation => true,
.kill => false,
};
}
Expand Down Expand Up @@ -482,6 +494,12 @@ pub const Command = struct { // MARK: Command
.energy = try reader.readFloat(f32),
}};
},
.rotation => {
return .{.rotation = .{
.target = null,
.rotation = try reader.readVec(Vec3f),
}};
},
}
}

Expand Down Expand Up @@ -513,6 +531,9 @@ pub const Command = struct { // MARK: Command
.energy => |energy| {
writer.writeFloat(f32, energy.energy);
},
.rotation => |rotation| {
writer.writeVec(Vec3f, rotation.rotation);
},
}
return writer.data.toOwnedSlice();
}
Expand Down
Loading