diff --git a/assets/cubyz/blocks/branch/leafy/oak.zig.zon b/assets/cubyz/blocks/branch/leafy/oak.zig.zon index 3df0f05e81..0a00b46849 100644 --- a/assets/cubyz/blocks/branch/leafy/oak.zig.zon +++ b/assets/cubyz/blocks/branch/leafy/oak.zig.zon @@ -1,9 +1,6 @@ .{ .onUpdate = .{ .type = .decay, - .drops = .{ - .{.items = .{"cubyz:branch/oak"}}, - }, }, .drops = .{ .{.items = .{"cubyz:branch/oak"}}, diff --git a/src/callbacks/block/server/check_support_blocks.zig b/src/callbacks/block/server/check_support_blocks.zig index 30296ababf..a6de4e4b1e 100644 --- a/src/callbacks/block/server/check_support_blocks.zig +++ b/src/callbacks/block/server/check_support_blocks.zig @@ -10,6 +10,7 @@ const Vec3d = vec.Vec3d; const Vec3f = vec.Vec3f; const ZonElement = main.ZonElement; const server = main.server; +const BlockDrop = main.server.BlockDrop; pub fn init(_: ZonElement, _: main.callbacks.Creator) ?*@This() { return @as(*@This(), undefined); @@ -43,27 +44,11 @@ pub fn run(_: *@This(), params: main.callbacks.ServerBlockCallback.Params) main. if (newBlock == params.block) return .ignored; if (main.server.world.?.cmpxchgBlock(wx, wy, wz, params.block, newBlock) == null) { - const dropAmount = params.block.mode().itemDropsOnChange(params.block, newBlock); - const drops = params.block.blockDrops(); - for (0..dropAmount) |_| { - for (drops) |drop| { - if (!drop.isDroppedWhenBrokenWithItem(.null)) continue; - if (drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) { - for (drop.itemStacks) |stack| { - var dir = main.vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed)); - // Bias upwards - dir[2] += main.random.nextFloat(&main.seed)*4.0; - const model = params.block.mode().model(params.block).model(); - const pos = Vec3f{ - @as(f32, @floatFromInt(wx)) + model.min[0] + main.random.nextFloat(&main.seed)*(model.max[0] - model.min[0]), - @as(f32, @floatFromInt(wy)) + model.min[1] + main.random.nextFloat(&main.seed)*(model.max[1] - model.min[1]), - @as(f32, @floatFromInt(wz)) + model.min[2] + main.random.nextFloat(&main.seed)*(model.max[2] - model.min[2]), - }; - main.server.world.?.drop(stack.clone(), pos, dir, 1); - } - } - } - } + const dropCtx = BlockDrop.Context{ + .oldBlock = params.block, + .newBlock = newBlock, + }; + dropCtx.dropNaturally(.{wx, wy, wz}); return .handled; } return .ignored; diff --git a/src/callbacks/block/server/decay.zig b/src/callbacks/block/server/decay.zig index eb6e2bb28e..8315b987c4 100644 --- a/src/callbacks/block/server/decay.zig +++ b/src/callbacks/block/server/decay.zig @@ -135,22 +135,17 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma // no, there is no log in proximity if (world.cmpxchgBlock(wx, wy, wz, leaf, self.decayReplacement) == null) { - for (self.blockDrops) |drop| { - if (drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) { - for (drop.itemStacks) |stack| { - var dir = main.vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed)); - // Bias upwards - dir[2] += main.random.nextFloat(&main.seed)*4.0; - const model = leaf.mode().model(leaf).model(); - const pos = Vec3f{ - @as(f32, @floatFromInt(wx)) + model.min[0] + main.random.nextFloat(&main.seed)*(model.max[0] - model.min[0]), - @as(f32, @floatFromInt(wy)) + model.min[1] + main.random.nextFloat(&main.seed)*(model.max[1] - model.min[1]), - @as(f32, @floatFromInt(wz)) + model.min[2] + main.random.nextFloat(&main.seed)*(model.max[2] - model.min[2]), - }; - main.server.world.?.drop(stack.clone(), pos, dir, 1); - } - } - } + const model = params.block.mode().model(params.block).model(); + const location = BlockDrop.Location{ + .normalDir = main.vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed)), + .min = model.min, + .max = model.max, + }; + const dropCtx = BlockDrop.Context{ + .oldBlock = params.block, + .newBlock = self.decayReplacement, + }; + dropCtx.drop(location, .{wx, wy, wz}); return .handled; } } diff --git a/src/server/BlockDrop.zig b/src/server/BlockDrop.zig index 3725bcf29e..a58697e504 100644 --- a/src/server/BlockDrop.zig +++ b/src/server/BlockDrop.zig @@ -8,6 +8,7 @@ const Vec3f = vec.Vec3f; const Vec3i = vec.Vec3i; const blocks = main.blocks; const Block = blocks.Block; +const ModelIndex = main.models.ModelIndex; itemStacks: []const items.ItemStack, chance: f32, @@ -28,13 +29,34 @@ pub fn isDroppedWhenBrokenWithItem(self: @This(), item: Item) bool { } pub fn drop(self: @This(), pos: Vec3d, dir: Vec3f, velocity: f32) void { - if (self.chance == 1 or main.random.nextFloat(&main.seed) < self.chance) { + if (self.shouldDrop()) { for (self.itemStacks) |itemStack| { main.server.world.?.drop(itemStack.clone(), pos, dir, velocity); } } } +pub fn dropNaturally(self: @This(), modelIndex: ModelIndex, pos: Vec3i) void { + if (self.shouldDrop()) { + const model = modelIndex.model(); + for (self.itemStacks) |itemStack| { + var randomDir = main.vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed)); + // Bias upwards + randomDir[2] += main.random.nextFloat(&main.seed)*4.0; + const randomPos = Vec3f{ + @as(f32, @floatFromInt(pos[0])) + model.min[0] + main.random.nextFloat(&main.seed)*(model.max[0] - model.min[0]), + @as(f32, @floatFromInt(pos[1])) + model.min[1] + main.random.nextFloat(&main.seed)*(model.max[1] - model.min[1]), + @as(f32, @floatFromInt(pos[2])) + model.min[2] + main.random.nextFloat(&main.seed)*(model.max[2] - model.min[2]), + }; + main.server.world.?.drop(itemStack.clone(), randomPos, randomDir, 1); + } + } +} + +inline fn shouldDrop(self: @This()) bool { + return self.chance == 1 or main.random.nextFloat(&main.seed) < self.chance; +} + pub const Location = struct { normalDir: Vec3f, min: Vec3f, @@ -100,14 +122,14 @@ pub const Context = struct { item: Item = .null, pub fn drop(self: Context, location: Location, pos: Vec3i) void { - const dropAmount = self.oldBlock.mode().itemDropsOnChange(self.oldBlock, self.newBlock); - if (dropAmount == 0) return; + const amount = self.dropAmount(); + if (amount == 0) return; const dropPos = if (self.newBlock.collide()) location.outsidePos(pos) else location.insidePos(pos); const dropDir = location.dropDir(); const dropVelocity = location.dropVelocity(); - for (0..dropAmount) |_| { + for (0..amount) |_| { for (self.oldBlock.blockDrops()) |blockDrop| { if (blockDrop.isDroppedWhenBrokenWithItem(self.item)) { blockDrop.drop(dropPos, dropDir, dropVelocity); @@ -115,4 +137,22 @@ pub const Context = struct { } } } + + pub fn dropNaturally(self: Context, pos: Vec3i) void { + const amount = self.dropAmount(); + if (amount == 0) return; + + const modelIndex = self.oldBlock.mode().model(self.oldBlock); + for (0..amount) |_| { + for (self.oldBlock.blockDrops()) |blockDrop| { + if (blockDrop.isDroppedWhenBrokenWithItem(.null)) { + blockDrop.dropNaturally(modelIndex, pos); + } + } + } + } + + inline fn dropAmount(self: Context) u16 { + return self.oldBlock.mode().itemDropsOnChange(self.oldBlock, self.newBlock); + } };