From 994d2c93eae660345c1d74d329303a55e58e270e Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Mon, 25 Nov 2024 17:52:49 +0100 Subject: [PATCH] Allow breaking single torches and carpets from a given block, instead of breaking all at once. fixes #798 --- src/rotation.zig | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/rotation.zig b/src/rotation.zig index 739193333..afab3fa2a 100644 --- a/src/rotation.zig +++ b/src/rotation.zig @@ -680,20 +680,33 @@ pub const RotationModes = struct { return true; } - pub fn rayIntersection(block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { + fn closestRay(comptime typ: enum{bit, intersection}, block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) if(typ == .intersection) ?RayIntersectionResult else u16 { var result: ?RayIntersectionResult = null; + var resultBit: u16 = 0; for([_]u16{1, 2, 4, 8, 16}) |bit| { if(block.data & bit != 0) { const modelIndex = blocks.meshes.modelIndexStart(block) + bit - 1; if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { if(result == null or result.?.distance > intersection.distance) { result = intersection; + resultBit = bit; } } } } + if(typ == .bit) return resultBit; return result; } + + pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { + return closestRay(.intersection, block, item, relativePlayerPos, playerDir); + } + + pub fn onBlockBreaking(item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f, currentData: *Block) void { + const bit = closestRay(.bit, currentData.*, item, relativePlayerPos, playerDir); + currentData.data &= ~bit; + if(currentData.data == 0) currentData.typ = 0; + } }; pub const Carpet = struct { // MARK: Carpet pub const id: []const u8 = "carpet"; @@ -823,20 +836,33 @@ pub const RotationModes = struct { return true; } - pub fn rayIntersection(block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { + fn closestRay(comptime typ: enum{bit, intersection}, block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) if(typ == .intersection) ?RayIntersectionResult else u16 { var result: ?RayIntersectionResult = null; + var resultBit: u16 = 0; for([_]u16{1, 2, 4, 8, 16, 32}) |bit| { if(block.data & bit != 0) { const modelIndex = blocks.meshes.modelIndexStart(block) + bit - 1; if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { if(result == null or result.?.distance > intersection.distance) { result = intersection; + resultBit = bit; } } } } + if(typ == .bit) return resultBit; return result; } + + pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { + return closestRay(.intersection, block, item, relativePlayerPos, playerDir); + } + + pub fn onBlockBreaking(item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f, currentData: *Block) void { + const bit = closestRay(.bit, currentData.*, item, relativePlayerPos, playerDir); + currentData.data &= ~bit; + if(currentData.data == 0) currentData.typ = 0; + } }; };