mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00
Merge d5093c88bba72bfa46dbefa8b85997632b4a1878 into 2dc2a6e79018221d5aab44e09be242d9dab3ddf2
This commit is contained in:
commit
46ced50441
@ -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;
|
||||
@ -1018,6 +1019,7 @@ pub const Protocols = struct {
|
||||
worldEditPos = 2,
|
||||
time = 3,
|
||||
biome = 4,
|
||||
particle = 5,
|
||||
};
|
||||
|
||||
const WorldEditPosition = enum(u2) {
|
||||
@ -1090,6 +1092,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,
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1130,6 +1146,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();
|
||||
|
@ -35,6 +35,7 @@ pub const ParticleManager = struct {
|
||||
|
||||
const ParticleIndex = u16;
|
||||
var particleTypeHashmap: std.StringHashMapUnmanaged(ParticleIndex) = .{};
|
||||
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});
|
||||
@ -147,6 +151,16 @@ pub const ParticleManager = struct {
|
||||
particleTypesSSBO.bufferData(ParticleType, ParticleManager.types.items);
|
||||
particleTypesSSBO.bind(14);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
};
|
||||
|
||||
pub const ParticleSystem = struct {
|
||||
|
@ -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");
|
||||
|
||||
|
90
src/server/command/particle.zig
Normal file
90
src/server/command/particle.zig
Normal file
@ -0,0 +1,90 @@
|
||||
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 <id> <x> <y> <z>
|
||||
\\/particle <id> <x> <y> <z> <collides>
|
||||
\\/particle <id> <x> <y> <z> <collides> <count>
|
||||
;
|
||||
|
||||
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| {
|
||||
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 => return,
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
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{
|
||||
TooManyArguments,
|
||||
TooFewArguments,
|
||||
InvalidBoolean,
|
||||
InvalidNumber,
|
||||
InvalidParticleId,
|
||||
};
|
||||
|
||||
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;
|
||||
const indexId = particles.ParticleManager.getTypeIndexById(particleId) orelse return error.InvalidParticleId;
|
||||
|
||||
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", source);
|
||||
if(split.next() != null) return error.TooManyArguments;
|
||||
|
||||
return .{indexId, x, y, z, collides, particleCount};
|
||||
}
|
||||
|
||||
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) {
|
||||
source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg});
|
||||
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, source: *User) CommandError!u32 {
|
||||
return std.fmt.parseUnsigned(u32, arg, 0) catch |err| {
|
||||
switch(err) {
|
||||
error.Overflow => return std.math.maxInt(u32),
|
||||
error.InvalidCharacter => {
|
||||
source.sendMessage("#ff0000Expected number, found \"{s}\"", .{arg});
|
||||
return error.InvalidNumber;
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user