From a977715e73820f64ec904e1bfe78eac33e7325ca Mon Sep 17 00:00:00 2001 From: RanPix Date: Sat, 31 May 2025 23:31:30 +0300 Subject: [PATCH 01/10] add /particle command --- src/particles.zig | 7 +++ src/server/command/_list.zig | 1 + src/server/command/particle.zig | 97 +++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/server/command/particle.zig diff --git a/src/particles.zig b/src/particles.zig index fc2aad7e..601192d9 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -147,6 +147,13 @@ pub const ParticleManager = struct { particleTypesSSBO.bufferData(ParticleType, ParticleManager.types.items); particleTypesSSBO.bind(14); } + + pub fn getTypeById(id: []const u8) ?ParticleType { + if(particleTypeHashmap.get(id)) |typ| { + return types.items[typ]; + } + return null; + } }; pub const ParticleSystem = struct { diff --git a/src/server/command/_list.zig b/src/server/command/_list.zig index 3d187ecb..fccd9b10 100644 --- a/src/server/command/_list.zig +++ b/src/server/command/_list.zig @@ -3,6 +3,7 @@ pub const gamemode = @import("gamemode.zig"); pub const help = @import("help.zig"); pub const invite = @import("invite.zig"); pub const kill = @import("kill.zig"); +pub const particle = @import("particle.zig"); pub const time = @import("time.zig"); pub const tp = @import("tp.zig"); diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig new file mode 100644 index 00000000..e304e0e8 --- /dev/null +++ b/src/server/command/particle.zig @@ -0,0 +1,97 @@ +const std = @import("std"); + +const main = @import("main"); +const particles = main.particles; +const User = main.server.User; + +pub const description = "Spawns particles"; +pub const usage = + \\/particle + \\/particle + \\/particle +; + +pub fn execute(args: []const u8, source: *User) void { + var particleID: ?[]const u8 = null; + var x: ?f64 = null; + var y: ?f64 = null; + var z: ?f64 = null; + var collides: ?bool = null; + var particleCount: ?u32 = null; + + var split = std.mem.splitScalar(u8, args, ' '); + while(split.next()) |arg| { + if(particleID == null) { + if(std.mem.containsAtLeast(u8, arg, 1, ":")) { + if(particles.ParticleManager.getTypeById(arg)) |_| { + particleID = arg; + } else { + source.sendMessage("#ff0000Invalid particle id", .{}); + return; + } + } + } else if(x == null or y == null or z == null) { + const hasTilde = if(arg.len == 0) false else arg[0] == '~'; + const numberSlice = if(hasTilde) arg[1..] else arg; + const num: f64 = std.fmt.parseFloat(f64, numberSlice) catch ret: { + if(arg.len > 1 or arg.len == 0) { + source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); + return; + } + break :ret 0; + }; + const playerPos = main.game.Player.getEyePosBlocking(); + if(x == null) { + x = if(hasTilde) playerPos[0] + num else num; + } else if(y == null) { + y = if(hasTilde) playerPos[1] + num else num; + } else if(z == null) { + z = if(hasTilde) playerPos[2] + num else num; + } + } else if(collides == null) { + if(std.mem.eql(u8, arg, "true")) { + collides = true; + } else if(std.mem.eql(u8, arg, "false")) { + collides = false; + } else { + source.sendMessage("#ff0000Invalid argument. Expected \"true\" or \"false\"", .{}); + return; + } + } else if(particleCount == null) { + particleCount = std.fmt.parseUnsigned(u32, arg, 0) catch |err| ret: { + switch(err) { + error.Overflow => { + break :ret std.math.maxInt(u32); + }, + error.InvalidCharacter => { + source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); + return; + }, + } + }; + } else { + source.sendMessage("#ff0000Too many arguments for command /particle", .{}); + return; + } + } + + if(particleID == null or x == null or y == null or z == null) { + source.sendMessage("#ff0000Too few arguments for command /particle", .{}); + return; + } + x = std.math.clamp(x.?, -1e9, 1e9); // TODO: Remove after #310 is implemented + y = std.math.clamp(y.?, -1e9, 1e9); + z = std.math.clamp(z.?, -1e9, 1e9); + if(collides == null) { + collides = false; + } + if(particleCount == null) { + particleCount = 1; + } + + const emitter: particles.Emitter = .init(particleID.?, collides.?); + emitter.spawnParticles(particleCount.?, particles.Emitter.SpawnPoint, .{ + .mode = .spread, + .position = main.vec.Vec3d{x.?, y.?, z.?}, + }); +} From 8c2ee786ab6d6bd41fd6876631a46a42a7b1bfad Mon Sep 17 00:00:00 2001 From: RanPix Date: Sat, 31 May 2025 23:35:05 +0300 Subject: [PATCH 02/10] edit command description --- src/server/command/particle.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig index e304e0e8..d346f092 100644 --- a/src/server/command/particle.zig +++ b/src/server/command/particle.zig @@ -4,7 +4,7 @@ const main = @import("main"); const particles = main.particles; const User = main.server.User; -pub const description = "Spawns particles"; +pub const description = "Spawns particles."; pub const usage = \\/particle \\/particle From 9ab7b9953afdddfa9d65b047161f57139b2cbf12 Mon Sep 17 00:00:00 2001 From: RanPix Date: Sat, 31 May 2025 23:42:23 +0300 Subject: [PATCH 03/10] simplify getTypeById function --- src/particles.zig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/particles.zig b/src/particles.zig index 601192d9..47f7e7ad 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -149,10 +149,7 @@ pub const ParticleManager = struct { } pub fn getTypeById(id: []const u8) ?ParticleType { - if(particleTypeHashmap.get(id)) |typ| { - return types.items[typ]; - } - return null; + return particleTypeHashmap.get(id); } }; From 04072a78913ea1515141e4ebf918a54b9f2d8a0e Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 12:27:17 +0300 Subject: [PATCH 04/10] revert previous changes --- src/particles.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/particles.zig b/src/particles.zig index 47f7e7ad..601192d9 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -149,7 +149,10 @@ pub const ParticleManager = struct { } pub fn getTypeById(id: []const u8) ?ParticleType { - return particleTypeHashmap.get(id); + if(particleTypeHashmap.get(id)) |typ| { + return types.items[typ]; + } + return null; } }; From 03a1b45f9c3856df4cd604813b7db1ac8a58d396 Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 17:27:04 +0300 Subject: [PATCH 05/10] simplify code --- src/server/command/particle.zig | 141 +++++++++++++++----------------- 1 file changed, 64 insertions(+), 77 deletions(-) diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig index d346f092..10b64129 100644 --- a/src/server/command/particle.zig +++ b/src/server/command/particle.zig @@ -12,86 +12,73 @@ pub const usage = ; pub fn execute(args: []const u8, source: *User) void { - var particleID: ?[]const u8 = null; - var x: ?f64 = null; - var y: ?f64 = null; - var z: ?f64 = null; - var collides: ?bool = null; - var particleCount: ?u32 = null; - - var split = std.mem.splitScalar(u8, args, ' '); - while(split.next()) |arg| { - if(particleID == null) { - if(std.mem.containsAtLeast(u8, arg, 1, ":")) { - if(particles.ParticleManager.getTypeById(arg)) |_| { - particleID = arg; - } else { - source.sendMessage("#ff0000Invalid particle id", .{}); - return; - } - } - } else if(x == null or y == null or z == null) { - const hasTilde = if(arg.len == 0) false else arg[0] == '~'; - const numberSlice = if(hasTilde) arg[1..] else arg; - const num: f64 = std.fmt.parseFloat(f64, numberSlice) catch ret: { - if(arg.len > 1 or arg.len == 0) { - source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); - return; - } - break :ret 0; - }; - const playerPos = main.game.Player.getEyePosBlocking(); - if(x == null) { - x = if(hasTilde) playerPos[0] + num else num; - } else if(y == null) { - y = if(hasTilde) playerPos[1] + num else num; - } else if(z == null) { - z = if(hasTilde) playerPos[2] + num else num; - } - } else if(collides == null) { - if(std.mem.eql(u8, arg, "true")) { - collides = true; - } else if(std.mem.eql(u8, arg, "false")) { - collides = false; - } else { - source.sendMessage("#ff0000Invalid argument. Expected \"true\" or \"false\"", .{}); - return; - } - } else if(particleCount == null) { - particleCount = std.fmt.parseUnsigned(u32, arg, 0) catch |err| ret: { - switch(err) { - error.Overflow => { - break :ret std.math.maxInt(u32); - }, - error.InvalidCharacter => { - source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); - return; - }, - } - }; - } else { - source.sendMessage("#ff0000Too many arguments for command /particle", .{}); - return; + const particleID, const x, const y, const z, const collides, const particleCount = parseArguments(source, args) catch |err| { + switch(err) { + error.TooFewArguments => source.sendMessage("#ff0000Too few arguments for command /particle", .{}), + error.TooManyArguments => source.sendMessage("#ff0000Too many arguments for command /particle", .{}), + error.InvalidParticleID => source.sendMessage("#ff0000Invalid particle id", .{}), + error.InvalidBoolean => source.sendMessage("#ff0000Invalid argument. Expected \"true\" or \"false\"", .{}), + error.InvalidNumber => source.sendMessage("#ff0000Invalid number", .{}), } - } - - if(particleID == null or x == null or y == null or z == null) { - source.sendMessage("#ff0000Too few arguments for command /particle", .{}); return; - } - x = std.math.clamp(x.?, -1e9, 1e9); // TODO: Remove after #310 is implemented - y = std.math.clamp(y.?, -1e9, 1e9); - z = std.math.clamp(z.?, -1e9, 1e9); - if(collides == null) { - collides = false; - } - if(particleCount == null) { - particleCount = 1; - } + }; - const emitter: particles.Emitter = .init(particleID.?, collides.?); - emitter.spawnParticles(particleCount.?, particles.Emitter.SpawnPoint, .{ + const emitter: particles.Emitter = .init(particleID, collides); + emitter.spawnParticles(particleCount, particles.Emitter.SpawnPoint, .{ .mode = .spread, - .position = main.vec.Vec3d{x.?, y.?, z.?}, + .position = main.vec.Vec3d{x, y, z}, }); } + +pub const CommandError = error{ + TooManyArguments, + TooFewArguments, + InvalidBoolean, + InvalidNumber, + InvalidParticleID, +}; + +fn parseArguments(source: *User, args: []const u8) CommandError!struct {[]const u8, f64, f64, f64, bool, u32} { + var split = std.mem.splitScalar(u8, args, ' '); + const particleID = split.next() orelse return error.TooFewArguments; + _ = particles.ParticleManager.getTypeById(particleID) orelse return error.InvalidParticleID; + + const x = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[0]); + const y = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[1]); + const z = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[2]); + const collides = try parseBool(split.next() orelse "false"); + const particleCount = try parseNumber(split.next() orelse "1"); + if(split.next() != null) return error.TooManyArguments; + + return .{particleID, x, y, z, collides, particleCount}; +} + +fn parsePosition(arg: []const u8, playerPos: f64) CommandError!f64 { + const hasTilde = if(arg.len == 0) false else arg[0] == '~'; + const numberSlice = if(hasTilde) arg[1..] else arg; + const num: f64 = std.fmt.parseFloat(f64, numberSlice) catch ret: { + if(arg.len > 1 or arg.len == 0) return error.InvalidNumber; + break :ret 0; + }; + + return if(hasTilde) playerPos + num else num; +} + +fn parseBool(arg: []const u8) CommandError!bool { + if(std.mem.eql(u8, arg, "true")) { + return true; + } else if(std.mem.eql(u8, arg, "false")) { + return false; + } + + return error.InvalidBoolean; +} + +fn parseNumber(arg: []const u8) CommandError!u32 { + return std.fmt.parseUnsigned(u32, arg, 0) catch |err| { + switch(err) { + error.Overflow => return std.math.maxInt(u32), + error.InvalidCharacter => return error.InvalidNumber, + } + }; +} From af2d246c9f029e5e34a5e10a917d7dcee1748ddf Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 18:55:24 +0300 Subject: [PATCH 06/10] fixes, add particle packet --- src/network.zig | 29 ++++++++++++++++++++ src/particles.zig | 17 ++++++++---- src/server/command/particle.zig | 48 ++++++++++++++++++--------------- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/network.zig b/src/network.zig index 1e9be15d..367485ca 100644 --- a/src/network.zig +++ b/src/network.zig @@ -6,6 +6,7 @@ const assets = @import("assets.zig"); const Block = @import("blocks.zig").Block; const chunk = @import("chunk.zig"); const entity = @import("entity.zig"); +const particles = @import("particles.zig"); const items = @import("items.zig"); const Inventory = items.Inventory; const ItemStack = items.ItemStack; @@ -1015,6 +1016,7 @@ pub const Protocols = struct { worldEditPos = 2, time = 3, biome = 4, + particle = 5, }; const WorldEditPosition = enum(u2) { @@ -1087,6 +1089,20 @@ pub const Protocols = struct { } } }, + .particle => { + if(conn.manager.world) |_| { + const particleId = particles.ParticleManager.getIdByTypeIndex(try reader.readInt(u16)); + const pos = try reader.readVec(Vec3d); + const collides = try reader.readInt(u8) == 1; + const count = try reader.readInt(u32); + + const emitter: particles.Emitter = .init(particleId, collides); + emitter.spawnParticles(count, particles.Emitter.SpawnPoint, .{ + .mode = .spread, + .position = pos, + }); + } + }, } } @@ -1127,6 +1143,19 @@ pub const Protocols = struct { conn.send(.fast, id, writer.data.items); } + pub fn sendParticle(conn: *Connection, particleId: u16, pos: Vec3d, collides: bool, count: u32) void { + var writer = utils.BinaryWriter.initCapacity(main.stackAllocator, 32); + defer writer.deinit(); + + writer.writeEnum(UpdateType, .particle); + writer.writeInt(u16, particleId); + writer.writeVec(Vec3d, pos); + writer.writeInt(u8, if(collides) 1 else 0); + writer.writeInt(u32, count); + + conn.send(.fast, id, writer.data.items); + } + pub fn sendTime(conn: *Connection, world: *const main.server.ServerWorld) void { var writer = utils.BinaryWriter.initCapacity(main.stackAllocator, 13); defer writer.deinit(); diff --git a/src/particles.zig b/src/particles.zig index 601192d9..820a43f3 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -35,6 +35,7 @@ pub const ParticleManager = struct { const ParticleIndex = u16; var particleTypeHashmap: std.StringHashMapUnmanaged(ParticleIndex) = undefined; + var typeIds: main.List([]const u8) = undefined; pub fn init() void { types = .init(arenaAllocator); @@ -42,6 +43,7 @@ pub const ParticleManager = struct { emissionTextures = .init(arenaAllocator); textureArray = .init(); emissionTextureArray = .init(); + typeIds = .init(arenaAllocator); particleTypesSSBO = SSBO.init(); ParticleSystem.init(); } @@ -52,6 +54,7 @@ pub const ParticleManager = struct { emissionTextures.deinit(); textureArray.deinit(); emissionTextureArray.deinit(); + typeIds.deinit(); particleTypeHashmap.deinit(arenaAllocator.allocator); ParticleSystem.deinit(); particleTypesSSBO.deinit(); @@ -67,6 +70,7 @@ pub const ParticleManager = struct { const particleType = readTextureDataAndParticleType(assetsFolder, textureId); particleTypeHashmap.put(arenaAllocator.allocator, id, @intCast(types.items.len)) catch unreachable; + typeIds.append(id); types.append(particleType); std.log.debug("Registered particle type: {s}", .{id}); @@ -148,11 +152,14 @@ pub const ParticleManager = struct { particleTypesSSBO.bind(14); } - pub fn getTypeById(id: []const u8) ?ParticleType { - if(particleTypeHashmap.get(id)) |typ| { - return types.items[typ]; - } - return null; + pub fn getTypeIndexById(id: []const u8) ?ParticleIndex { + return particleTypeHashmap.get(id); + } + + pub fn getIdByTypeIndex(index: ParticleIndex) []const u8 { + std.debug.assert(index < typeIds.items.len); + + return typeIds.items[index]; } }; diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig index 10b64129..5bc6249b 100644 --- a/src/server/command/particle.zig +++ b/src/server/command/particle.zig @@ -12,22 +12,22 @@ pub const usage = ; pub fn execute(args: []const u8, source: *User) void { - const particleID, const x, const y, const z, const collides, const particleCount = parseArguments(source, args) catch |err| { + const particleId, const x, const y, const z, const collides, const particleCount = parseArguments(source, args) catch |err| { switch(err) { error.TooFewArguments => source.sendMessage("#ff0000Too few arguments for command /particle", .{}), error.TooManyArguments => source.sendMessage("#ff0000Too many arguments for command /particle", .{}), - error.InvalidParticleID => source.sendMessage("#ff0000Invalid particle id", .{}), + error.InvalidParticleId => source.sendMessage("#ff0000Invalid particle id", .{}), error.InvalidBoolean => source.sendMessage("#ff0000Invalid argument. Expected \"true\" or \"false\"", .{}), - error.InvalidNumber => source.sendMessage("#ff0000Invalid number", .{}), + error.InvalidNumber => return, } return; }; - const emitter: particles.Emitter = .init(particleID, collides); - emitter.spawnParticles(particleCount, particles.Emitter.SpawnPoint, .{ - .mode = .spread, - .position = main.vec.Vec3d{x, y, z}, - }); + const users = main.server.getUserListAndIncreaseRefCount(main.stackAllocator); + defer main.server.freeUserListAndDecreaseRefCount(main.stackAllocator, users); + for(users) |user| { + main.network.Protocols.genericUpdate.sendParticle(user.conn, particleId, .{x, y, z}, collides, particleCount); + } } pub const CommandError = error{ @@ -35,29 +35,32 @@ pub const CommandError = error{ TooFewArguments, InvalidBoolean, InvalidNumber, - InvalidParticleID, + InvalidParticleId, }; -fn parseArguments(source: *User, args: []const u8) CommandError!struct {[]const u8, f64, f64, f64, bool, u32} { +fn parseArguments(source: *User, args: []const u8) CommandError!struct {u16, f64, f64, f64, bool, u32} { var split = std.mem.splitScalar(u8, args, ' '); - const particleID = split.next() orelse return error.TooFewArguments; - _ = particles.ParticleManager.getTypeById(particleID) orelse return error.InvalidParticleID; + const particleId = split.next() orelse return error.TooFewArguments; + const indexId = particles.ParticleManager.getTypeIndexById(particleId) orelse return error.InvalidParticleId; - const x = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[0]); - const y = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[1]); - const z = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[2]); + const x = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[0], source); + const y = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[1], source); + const z = try parsePosition(split.next() orelse return error.TooFewArguments, source.player.pos[2], source); const collides = try parseBool(split.next() orelse "false"); - const particleCount = try parseNumber(split.next() orelse "1"); + const particleCount = try parseNumber(split.next() orelse "1", source); if(split.next() != null) return error.TooManyArguments; - return .{particleID, x, y, z, collides, particleCount}; + return .{indexId, x, y, z, collides, particleCount}; } -fn parsePosition(arg: []const u8, playerPos: f64) CommandError!f64 { +fn parsePosition(arg: []const u8, playerPos: f64, source: *User) CommandError!f64 { const hasTilde = if(arg.len == 0) false else arg[0] == '~'; const numberSlice = if(hasTilde) arg[1..] else arg; const num: f64 = std.fmt.parseFloat(f64, numberSlice) catch ret: { - if(arg.len > 1 or arg.len == 0) return error.InvalidNumber; + if(arg.len > 1 or arg.len == 0) { + source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); + return error.InvalidNumber; + } break :ret 0; }; @@ -74,11 +77,14 @@ fn parseBool(arg: []const u8) CommandError!bool { return error.InvalidBoolean; } -fn parseNumber(arg: []const u8) CommandError!u32 { +fn parseNumber(arg: []const u8, source: *User) CommandError!u32 { return std.fmt.parseUnsigned(u32, arg, 0) catch |err| { switch(err) { error.Overflow => return std.math.maxInt(u32), - error.InvalidCharacter => return error.InvalidNumber, + error.InvalidCharacter => { + source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg}); + return error.InvalidNumber; + }, } }; } From 2d104afcbc1c771c02457dba353069310e553c9b Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 18:56:26 +0300 Subject: [PATCH 07/10] fix formatting --- src/particles.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/particles.zig b/src/particles.zig index 820a43f3..40413cfe 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -155,7 +155,7 @@ pub const ParticleManager = struct { pub fn getTypeIndexById(id: []const u8) ?ParticleIndex { return particleTypeHashmap.get(id); } - + pub fn getIdByTypeIndex(index: ParticleIndex) []const u8 { std.debug.assert(index < typeIds.items.len); From 7ea6b74d5792b85276cdfc09fc8fbd793ac0b0ee Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 19:05:07 +0300 Subject: [PATCH 08/10] add spawn count limit --- src/server/command/particle.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig index 5bc6249b..86acf6fc 100644 --- a/src/server/command/particle.zig +++ b/src/server/command/particle.zig @@ -78,7 +78,7 @@ fn parseBool(arg: []const u8) CommandError!bool { } fn parseNumber(arg: []const u8, source: *User) CommandError!u32 { - return std.fmt.parseUnsigned(u32, arg, 0) catch |err| { + const num = std.fmt.parseUnsigned(u32, arg, 0) catch |err| { switch(err) { error.Overflow => return std.math.maxInt(u32), error.InvalidCharacter => { @@ -87,4 +87,6 @@ fn parseNumber(arg: []const u8, source: *User) CommandError!u32 { }, } }; + + return std.math.clamp(num, 0, 500); } From fcfaaf88f8a04658edeb9c13fbe59bb6677f0562 Mon Sep 17 00:00:00 2001 From: RanPix Date: Sun, 1 Jun 2025 19:10:56 +0300 Subject: [PATCH 09/10] Revert "add spawn count limit" This reverts commit 7ea6b74d5792b85276cdfc09fc8fbd793ac0b0ee. --- src/server/command/particle.zig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/server/command/particle.zig b/src/server/command/particle.zig index 86acf6fc..5bc6249b 100644 --- a/src/server/command/particle.zig +++ b/src/server/command/particle.zig @@ -78,7 +78,7 @@ fn parseBool(arg: []const u8) CommandError!bool { } fn parseNumber(arg: []const u8, source: *User) CommandError!u32 { - const num = std.fmt.parseUnsigned(u32, arg, 0) catch |err| { + return std.fmt.parseUnsigned(u32, arg, 0) catch |err| { switch(err) { error.Overflow => return std.math.maxInt(u32), error.InvalidCharacter => { @@ -87,6 +87,4 @@ fn parseNumber(arg: []const u8, source: *User) CommandError!u32 { }, } }; - - return std.math.clamp(num, 0, 500); } From d5093c88bba72bfa46dbefa8b85997632b4a1878 Mon Sep 17 00:00:00 2001 From: RanPix Date: Mon, 2 Jun 2025 20:48:55 +0300 Subject: [PATCH 10/10] fix formatting --- src/particles.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/particles.zig b/src/particles.zig index 5e0ce076..15fbff67 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -35,7 +35,7 @@ pub const ParticleManager = struct { const ParticleIndex = u16; var particleTypeHashmap: std.StringHashMapUnmanaged(ParticleIndex) = .{}; - var typeIds: main.List([]const u8) = undefined; + var typeIds: main.List([]const u8) = undefined; pub fn init() void { types = .init(arenaAllocator);