From 4e9a1b20393455f2e5a8770e5a0456bc1d596a2a Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:07:24 +0200 Subject: [PATCH 01/15] add swing_arm component --- src/entityComponent/_list.zig | 1 + src/entityComponent/swing_arm.zig | 99 +++++++++++++++++++++++++++++++ src/renderer.zig | 16 ++--- src/server/server.zig | 1 + 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/entityComponent/swing_arm.zig diff --git a/src/entityComponent/_list.zig b/src/entityComponent/_list.zig index d162bf66e0..289cebbb74 100644 --- a/src/entityComponent/_list.zig +++ b/src/entityComponent/_list.zig @@ -3,3 +3,4 @@ pub const @"cubyz:bag" = @import("bag.zig"); pub const @"cubyz:model" = @import("model.zig"); pub const @"cubyz:permissions" = @import("permissions.zig"); pub const @"cubyz:player" = @import("player.zig"); +pub const @"cubyz:swing_arm" = @import("swing_arm.zig"); diff --git a/src/entityComponent/swing_arm.zig b/src/entityComponent/swing_arm.zig new file mode 100644 index 0000000000..31c9b7ca0b --- /dev/null +++ b/src/entityComponent/swing_arm.zig @@ -0,0 +1,99 @@ +const std = @import("std"); + +const main = @import("main"); +const chunk = main.chunk; +const Entity = main.entity.Entity; +const ServerChunk = chunk.ServerChunk; +const game = main.game; +const graphics = main.graphics; +const ZonElement = main.ZonElement; +const renderer = main.renderer; +const settings = main.settings; +const utils = main.utils; +const BinaryReader = utils.BinaryReader; +const BinaryWriter = utils.BinaryWriter; +const vec = main.vec; +const Mat4f = vec.Mat4f; +const Vec3d = vec.Vec3d; +const Vec3f = vec.Vec3f; +const Vec4f = vec.Vec4f; +const Vec3i = vec.Vec3i; +const NeverFailingAllocator = main.heap.NeverFailingAllocator; +const blocks = main.blocks; +const World = game.World; +const ServerWorld = main.server.ServerWorld; +const items = main.items; +const ItemStack = items.ItemStack; +const random = main.random; + +const c = @import("c"); + +pub var entityComponentID: main.entity.EntityComponentId = undefined; +pub const entityComponentVersion = 0; + +// ############################# Client only stuff ################################ +pub const client = struct { + const Component = struct { + currentSwingProgress: f32, + }; + pub var components: main.utils.SparseSet(Component, Entity) = .{}; + + pub fn init() void {} + pub fn deinit() void { + components.deinit(main.globalAllocator); + } + pub fn clear() void { + components.clear(); + } + pub fn load(entity: Entity, reader: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { + if (version != 0) return error.InvalidComponentVersion; + const currentSwingProgress = reader.readFloat(f32) catch return error.UnreadableComponentData; + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = Component{ + .currentSwingProgress = currentSwingProgress, + }; + } + pub fn unload(entity: Entity) void { + components.remove(entity) catch {}; + } + pub fn get(entity: Entity) ?*Component { + return components.get(entity); + } +}; +// ############################# Server only stuff ################################ +pub const server = struct { + pub const Component = struct { + currentSwingProgress: f32, + pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { + writer.writeFloat(f32, self.currentSwingProgress); + if (audience == .disk) return .discard; + return .save; + } + }; + var components: main.utils.SparseSet(Component, Entity) = undefined; + pub fn init() void { + components = .{}; + } + pub fn deinit() void { + components.deinit(main.globalAllocator); + } + pub fn loadFromData(entity: Entity, _: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { + if (version != 0) return error.InvalidComponentVersion; + load(entity); + } + pub fn load(entity: Entity) void { + put(entity, Component{ + .currentSwingProgress = 0, + }); + } + pub fn unload(entity: Entity) void { + components.remove(entity) catch {}; + } + pub fn put(entity: Entity, renderComponent: Component) void { + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = renderComponent; + } + pub fn get(entity: Entity) ?*Component { + return components.get(entity); + } +}; diff --git a/src/renderer.zig b/src/renderer.zig index b250021882..66b6d63b36 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -924,7 +924,6 @@ pub const MeshSelection = struct { // MARK: MeshSelection pub var selectedBlockPos: ?Vec3i = null; var lastSelectedBlockPos: Vec3i = undefined; var currentBlockProgress: f32 = 0; - var currentSwingProgress: f32 = 0; var currentSwingTime: f32 = 0; var selectionMin: Vec3f = undefined; var selectionMax: Vec3f = undefined; @@ -1067,6 +1066,8 @@ pub const MeshSelection = struct { // MARK: MeshSelection } pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { + const swing_arm = main.entity.components.@"cubyz:swing_arm".client.get(main.game.Player.id) orelse return; // player can't swing... + if (selectedBlockPos) |selectedPos| { const stack = inventory.getStack(slot); const isSelectionWand = stack.item == .baseItem and std.mem.eql(u8, stack.item.baseItem.id(), "cubyz:selection_wand"); @@ -1078,8 +1079,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (@reduce(.Or, lastSelectedBlockPos != selectedPos)) { mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); - currentSwingProgress = 0; - currentSwingTime = 0; + swing_arm.currentSwingProgress = 0; lastSelectedBlockPos = selectedPos; currentBlockProgress = 0; } @@ -1100,7 +1100,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (damage > 0) { const swingTime = if (isProceduralItem and stack.item.proceduralItem.isEffectiveOn(block)) 1.0/stack.item.proceduralItem.getProperty(.swingSpeed) else 0.5; if (currentSwingTime > swingTime) { - currentSwingProgress = 0; + swing_arm.currentSwingProgress = 0; currentSwingTime = 0; } if (currentSwingTime == 0) { @@ -1108,9 +1108,9 @@ pub const MeshSelection = struct { // MARK: MeshSelection const damagePerSwing = block.blockHealth()/swings; currentSwingTime = damagePerSwing/damage*swingTime; } - currentSwingProgress += @floatCast(deltaTime); - while (currentSwingProgress > currentSwingTime) { - currentSwingProgress -= currentSwingTime; + swing_arm.currentSwingProgress += @floatCast(deltaTime); + while (swing_arm.currentSwingProgress > currentSwingTime) { + swing_arm.currentSwingProgress -= currentSwingTime; currentBlockProgress += damage*currentSwingTime/swingTime/block.blockHealth(); if (currentBlockProgress > 0.9999) break; const swings = @ceil(block.blockHealth()/damage); @@ -1126,7 +1126,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection return; } else { - currentSwingProgress = 0; + swing_arm.currentSwingProgress = 0; mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); currentBlockProgress = 0; currentSwingTime = 0; diff --git a/src/server/server.zig b/src/server/server.zig index 03830290d8..6684813aa9 100644 --- a/src/server/server.zig +++ b/src/server/server.zig @@ -324,6 +324,7 @@ pub const User = struct { // MARK: User self.loadUnloadChunks(); main.entity.components.@"cubyz:player".server.load(self.id, @truncate(self.playerIndex)); + main.entity.components.@"cubyz:swing_arm".server.load(self.id); } fn simArrIndex(x: i32) usize { From fef53322ebc9b2e2296f2a37599ac16094c63def Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:13:38 +0200 Subject: [PATCH 02/15] move currentSwingTime over --- src/entityComponent/swing_arm.zig | 6 ++++++ src/renderer.zig | 29 ++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/entityComponent/swing_arm.zig b/src/entityComponent/swing_arm.zig index 31c9b7ca0b..e1975663be 100644 --- a/src/entityComponent/swing_arm.zig +++ b/src/entityComponent/swing_arm.zig @@ -35,6 +35,7 @@ pub const entityComponentVersion = 0; pub const client = struct { const Component = struct { currentSwingProgress: f32, + currentSwingTime: f32, }; pub var components: main.utils.SparseSet(Component, Entity) = .{}; @@ -48,9 +49,11 @@ pub const client = struct { pub fn load(entity: Entity, reader: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { if (version != 0) return error.InvalidComponentVersion; const currentSwingProgress = reader.readFloat(f32) catch return error.UnreadableComponentData; + const currentSwingTime = reader.readFloat(f32) catch return error.UnreadableComponentData; const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); ptr.* = Component{ .currentSwingProgress = currentSwingProgress, + .currentSwingTime = currentSwingTime, }; } pub fn unload(entity: Entity) void { @@ -64,8 +67,10 @@ pub const client = struct { pub const server = struct { pub const Component = struct { currentSwingProgress: f32, + currentSwingTime: f32, pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { writer.writeFloat(f32, self.currentSwingProgress); + writer.writeFloat(f32, self.currentSwingTime); if (audience == .disk) return .discard; return .save; } @@ -84,6 +89,7 @@ pub const server = struct { pub fn load(entity: Entity) void { put(entity, Component{ .currentSwingProgress = 0, + .currentSwingTime = 0, }); } pub fn unload(entity: Entity) void { diff --git a/src/renderer.zig b/src/renderer.zig index 66b6d63b36..770bf4f521 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -924,7 +924,6 @@ pub const MeshSelection = struct { // MARK: MeshSelection pub var selectedBlockPos: ?Vec3i = null; var lastSelectedBlockPos: Vec3i = undefined; var currentBlockProgress: f32 = 0; - var currentSwingTime: f32 = 0; var selectionMin: Vec3f = undefined; var selectionMax: Vec3f = undefined; var selectionNormal: Vec3f = undefined; @@ -1066,7 +1065,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection } pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { - const swing_arm = main.entity.components.@"cubyz:swing_arm".client.get(main.game.Player.id) orelse return; // player can't swing... + const swingArm = main.entity.components.@"cubyz:swing_arm".client.get(main.game.Player.id) orelse return; // player can't swing... if (selectedBlockPos) |selectedPos| { const stack = inventory.getStack(slot); @@ -1079,7 +1078,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (@reduce(.Or, lastSelectedBlockPos != selectedPos)) { mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); - swing_arm.currentSwingProgress = 0; + swingArm.currentSwingProgress = 0; lastSelectedBlockPos = selectedPos; currentBlockProgress = 0; } @@ -1099,23 +1098,23 @@ pub const MeshSelection = struct { // MARK: MeshSelection damage -= block.blockResistance(); if (damage > 0) { const swingTime = if (isProceduralItem and stack.item.proceduralItem.isEffectiveOn(block)) 1.0/stack.item.proceduralItem.getProperty(.swingSpeed) else 0.5; - if (currentSwingTime > swingTime) { - swing_arm.currentSwingProgress = 0; - currentSwingTime = 0; + if (swingArm.currentSwingTime > swingTime) { + swingArm.currentSwingProgress = 0; + swingArm.currentSwingTime = 0; } - if (currentSwingTime == 0) { + if (swingArm.currentSwingTime == 0) { const swings = @ceil(block.blockHealth()/damage); const damagePerSwing = block.blockHealth()/swings; - currentSwingTime = damagePerSwing/damage*swingTime; + swingArm.currentSwingTime = damagePerSwing/damage*swingTime; } - swing_arm.currentSwingProgress += @floatCast(deltaTime); - while (swing_arm.currentSwingProgress > currentSwingTime) { - swing_arm.currentSwingProgress -= currentSwingTime; - currentBlockProgress += damage*currentSwingTime/swingTime/block.blockHealth(); + swingArm.currentSwingProgress += @floatCast(deltaTime); + while (swingArm.currentSwingProgress > swingArm.currentSwingTime) { + swingArm.currentSwingProgress -= swingArm.currentSwingTime; + currentBlockProgress += damage*swingArm.currentSwingTime/swingTime/block.blockHealth(); if (currentBlockProgress > 0.9999) break; const swings = @ceil(block.blockHealth()/damage); const damagePerSwing = block.blockHealth()/swings; - currentSwingTime = damagePerSwing/damage*swingTime; + swingArm.currentSwingTime = damagePerSwing/damage*swingTime; } if (currentBlockProgress < 0.9999) { mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); @@ -1126,10 +1125,10 @@ pub const MeshSelection = struct { // MARK: MeshSelection return; } else { - swing_arm.currentSwingProgress = 0; + swingArm.currentSwingProgress = 0; mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); currentBlockProgress = 0; - currentSwingTime = 0; + swingArm.currentSwingTime = 0; } } else { main.sync.client.mutex.unlock(); From 617627e91b7499e8a6ee1eb9173ce422599e5a8d Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:35:04 +0200 Subject: [PATCH 03/15] add broken component --- src/entityComponent/_list.zig | 1 + src/entityComponent/broken.zig | 99 ++++++++++++++++++++++++++++++++++ src/renderer.zig | 16 +++--- src/server/server.zig | 1 + 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/entityComponent/broken.zig diff --git a/src/entityComponent/_list.zig b/src/entityComponent/_list.zig index 289cebbb74..f223f9c70e 100644 --- a/src/entityComponent/_list.zig +++ b/src/entityComponent/_list.zig @@ -1,5 +1,6 @@ pub const @"cubyz:_template" = @import("_template.zig"); pub const @"cubyz:bag" = @import("bag.zig"); +pub const @"cubyz:broken" = @import("broken.zig"); pub const @"cubyz:model" = @import("model.zig"); pub const @"cubyz:permissions" = @import("permissions.zig"); pub const @"cubyz:player" = @import("player.zig"); diff --git a/src/entityComponent/broken.zig b/src/entityComponent/broken.zig new file mode 100644 index 0000000000..6bc1b8bf00 --- /dev/null +++ b/src/entityComponent/broken.zig @@ -0,0 +1,99 @@ +const std = @import("std"); + +const main = @import("main"); +const chunk = main.chunk; +const Entity = main.entity.Entity; +const ServerChunk = chunk.ServerChunk; +const game = main.game; +const graphics = main.graphics; +const ZonElement = main.ZonElement; +const renderer = main.renderer; +const settings = main.settings; +const utils = main.utils; +const BinaryReader = utils.BinaryReader; +const BinaryWriter = utils.BinaryWriter; +const vec = main.vec; +const Mat4f = vec.Mat4f; +const Vec3d = vec.Vec3d; +const Vec3f = vec.Vec3f; +const Vec4f = vec.Vec4f; +const Vec3i = vec.Vec3i; +const NeverFailingAllocator = main.heap.NeverFailingAllocator; +const blocks = main.blocks; +const World = game.World; +const ServerWorld = main.server.ServerWorld; +const items = main.items; +const ItemStack = items.ItemStack; +const random = main.random; + +const c = @import("c"); + +pub var entityComponentID: main.entity.EntityComponentId = undefined; +pub const entityComponentVersion = 0; + +// ############################# Client only stuff ################################ +pub const client = struct { + const Component = struct { + progress: f32, + }; + pub var components: main.utils.SparseSet(Component, Entity) = .{}; + + pub fn init() void {} + pub fn deinit() void { + components.deinit(main.globalAllocator); + } + pub fn clear() void { + components.clear(); + } + pub fn load(entity: Entity, reader: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { + if (version != 0) return error.InvalidComponentVersion; + const progress = reader.readFloat(f32) catch return error.UnreadableComponentData; + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = Component{ + .progress = progress, + }; + } + pub fn unload(entity: Entity) void { + components.remove(entity) catch {}; + } + pub fn get(entity: Entity) ?*Component { + return components.get(entity); + } +}; +// ############################# Server only stuff ################################ +pub const server = struct { + pub const Component = struct { + progress: f32, + pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { + writer.writeFloat(f32, self.progress); + if (audience == .disk) return .discard; + return .save; + } + }; + var components: main.utils.SparseSet(Component, Entity) = undefined; + pub fn init() void { + components = .{}; + } + pub fn deinit() void { + components.deinit(main.globalAllocator); + } + pub fn loadFromData(entity: Entity, _: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { + if (version != 0) return error.InvalidComponentVersion; + load(entity); + } + pub fn load(entity: Entity) void { + put(entity, Component{ + .progress = 0, + }); + } + pub fn unload(entity: Entity) void { + components.remove(entity) catch {}; + } + pub fn put(entity: Entity, renderComponent: Component) void { + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = renderComponent; + } + pub fn get(entity: Entity) ?*Component { + return components.get(entity); + } +}; diff --git a/src/renderer.zig b/src/renderer.zig index 770bf4f521..2a6361ae4c 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -923,7 +923,6 @@ pub const MeshSelection = struct { // MARK: MeshSelection var neighborOfSelection: chunk.Neighbor = undefined; pub var selectedBlockPos: ?Vec3i = null; var lastSelectedBlockPos: Vec3i = undefined; - var currentBlockProgress: f32 = 0; var selectionMin: Vec3f = undefined; var selectionMax: Vec3f = undefined; var selectionNormal: Vec3f = undefined; @@ -1066,6 +1065,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { const swingArm = main.entity.components.@"cubyz:swing_arm".client.get(main.game.Player.id) orelse return; // player can't swing... + const brokenBlock = main.entity.components.@"cubyz:broken".client.get(main.game.Player.id) orelse return; // player can't break blocks... if (selectedBlockPos) |selectedPos| { const stack = inventory.getStack(slot); @@ -1080,7 +1080,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); swingArm.currentSwingProgress = 0; lastSelectedBlockPos = selectedPos; - currentBlockProgress = 0; + brokenBlock.progress = 0; } const block = mesh_storage.getBlockFromRenderThread(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return; const holdingTargetedBlock = stack.item == .baseItem and stack.item.baseItem.block() == block.typ; @@ -1110,16 +1110,16 @@ pub const MeshSelection = struct { // MARK: MeshSelection swingArm.currentSwingProgress += @floatCast(deltaTime); while (swingArm.currentSwingProgress > swingArm.currentSwingTime) { swingArm.currentSwingProgress -= swingArm.currentSwingTime; - currentBlockProgress += damage*swingArm.currentSwingTime/swingTime/block.blockHealth(); - if (currentBlockProgress > 0.9999) break; + brokenBlock.progress += damage*swingArm.currentSwingTime/swingTime/block.blockHealth(); + if (brokenBlock.progress > 0.9999) break; const swings = @ceil(block.blockHealth()/damage); const damagePerSwing = block.blockHealth()/swings; swingArm.currentSwingTime = damagePerSwing/damage*swingTime; } - if (currentBlockProgress < 0.9999) { + if (brokenBlock.progress < 0.9999) { mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); - if (currentBlockProgress != 0) { - mesh_storage.addBreakingAnimation(lastSelectedBlockPos, currentBlockProgress); + if (brokenBlock.progress != 0) { + mesh_storage.addBreakingAnimation(lastSelectedBlockPos, brokenBlock.progress); } main.sync.client.mutex.unlock(); @@ -1127,7 +1127,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection } else { swingArm.currentSwingProgress = 0; mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); - currentBlockProgress = 0; + brokenBlock.progress = 0; swingArm.currentSwingTime = 0; } } else { diff --git a/src/server/server.zig b/src/server/server.zig index 6684813aa9..db48dd5d1f 100644 --- a/src/server/server.zig +++ b/src/server/server.zig @@ -325,6 +325,7 @@ pub const User = struct { // MARK: User main.entity.components.@"cubyz:player".server.load(self.id, @truncate(self.playerIndex)); main.entity.components.@"cubyz:swing_arm".server.load(self.id); + main.entity.components.@"cubyz:broken".server.load(self.id); } fn simArrIndex(x: i32) usize { From 9bce733ecc028338dc5f468e510f83d2c064a9af Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Thu, 1 Oct 2026 17:42:19 +0200 Subject: [PATCH 04/15] lastSelectedBlockPos -> broken --- src/entityComponent/broken.zig | 6 ++++++ src/renderer.zig | 15 +++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/entityComponent/broken.zig b/src/entityComponent/broken.zig index 6bc1b8bf00..bde9e5792c 100644 --- a/src/entityComponent/broken.zig +++ b/src/entityComponent/broken.zig @@ -35,6 +35,7 @@ pub const entityComponentVersion = 0; pub const client = struct { const Component = struct { progress: f32, + blockPos: Vec3i, }; pub var components: main.utils.SparseSet(Component, Entity) = .{}; @@ -48,9 +49,11 @@ pub const client = struct { pub fn load(entity: Entity, reader: *utils.BinaryReader, version: u32) main.entity.EntityComponentLoadError!void { if (version != 0) return error.InvalidComponentVersion; const progress = reader.readFloat(f32) catch return error.UnreadableComponentData; + const blockPos = reader.readVec(Vec3i) catch return error.UnreadableComponentData; const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); ptr.* = Component{ .progress = progress, + .blockPos = blockPos, }; } pub fn unload(entity: Entity) void { @@ -64,8 +67,10 @@ pub const client = struct { pub const server = struct { pub const Component = struct { progress: f32, + blockPos: Vec3i, pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { writer.writeFloat(f32, self.progress); + writer.writeVec(Vec3i, self.blockPos); if (audience == .disk) return .discard; return .save; } @@ -84,6 +89,7 @@ pub const server = struct { pub fn load(entity: Entity) void { put(entity, Component{ .progress = 0, + .blockPos = .{0, 0, 0}, }); } pub fn unload(entity: Entity) void { diff --git a/src/renderer.zig b/src/renderer.zig index 2a6361ae4c..088a170fac 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -922,7 +922,6 @@ pub const MeshSelection = struct { // MARK: MeshSelection var posBeforeBlock: Vec3i = undefined; var neighborOfSelection: chunk.Neighbor = undefined; pub var selectedBlockPos: ?Vec3i = null; - var lastSelectedBlockPos: Vec3i = undefined; var selectionMin: Vec3f = undefined; var selectionMax: Vec3f = undefined; var selectionNormal: Vec3f = undefined; @@ -1076,10 +1075,10 @@ pub const MeshSelection = struct { // MARK: MeshSelection return; } - if (@reduce(.Or, lastSelectedBlockPos != selectedPos)) { - mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); + if (@reduce(.Or, brokenBlock.blockPos != selectedPos)) { + mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); swingArm.currentSwingProgress = 0; - lastSelectedBlockPos = selectedPos; + brokenBlock.blockPos = selectedPos; brokenBlock.progress = 0; } const block = mesh_storage.getBlockFromRenderThread(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return; @@ -1117,16 +1116,16 @@ pub const MeshSelection = struct { // MARK: MeshSelection swingArm.currentSwingTime = damagePerSwing/damage*swingTime; } if (brokenBlock.progress < 0.9999) { - mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); + mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); if (brokenBlock.progress != 0) { - mesh_storage.addBreakingAnimation(lastSelectedBlockPos, brokenBlock.progress); + mesh_storage.addBreakingAnimation(brokenBlock.blockPos, brokenBlock.progress); } main.sync.client.mutex.unlock(); return; } else { swingArm.currentSwingProgress = 0; - mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); + mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); brokenBlock.progress = 0; swingArm.currentSwingTime = 0; } @@ -1135,7 +1134,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection return; } } else { - mesh_storage.removeBreakingAnimation(lastSelectedBlockPos); + mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); } var newBlock = block; From d406604c74ca462e8e688f8fc256f32611608c4d Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Thu, 1 Oct 2026 18:51:26 +0200 Subject: [PATCH 05/15] discard earlier --- src/entityComponent/broken.zig | 2 +- src/entityComponent/player.zig | 2 +- src/entityComponent/swing_arm.zig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entityComponent/broken.zig b/src/entityComponent/broken.zig index bde9e5792c..5caeac1424 100644 --- a/src/entityComponent/broken.zig +++ b/src/entityComponent/broken.zig @@ -69,9 +69,9 @@ pub const server = struct { progress: f32, blockPos: Vec3i, pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { + if (audience == .disk) return .discard; writer.writeFloat(f32, self.progress); writer.writeVec(Vec3i, self.blockPos); - if (audience == .disk) return .discard; return .save; } }; diff --git a/src/entityComponent/player.zig b/src/entityComponent/player.zig index d20a73a5f7..796edf0451 100644 --- a/src/entityComponent/player.zig +++ b/src/entityComponent/player.zig @@ -59,8 +59,8 @@ pub const server = struct { pub const Component = struct { playerIndex: u32, // model pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { - writer.writeVarInt(u32, self.playerIndex); if (audience == .disk) return .discard; + writer.writeVarInt(u32, self.playerIndex); return .save; } }; diff --git a/src/entityComponent/swing_arm.zig b/src/entityComponent/swing_arm.zig index e1975663be..f7b9932120 100644 --- a/src/entityComponent/swing_arm.zig +++ b/src/entityComponent/swing_arm.zig @@ -69,9 +69,9 @@ pub const server = struct { currentSwingProgress: f32, currentSwingTime: f32, pub fn save(self: Component, writer: *utils.BinaryWriter, audience: main.entity.AudienceInfo) main.entity.ComponentSaveBehaviour { + if (audience == .disk) return .discard; writer.writeFloat(f32, self.currentSwingProgress); writer.writeFloat(f32, self.currentSwingTime); - if (audience == .disk) return .discard; return .save; } }; From ffb275da0c15045c4a992c51b3b3db352c821b11 Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Thu, 1 Oct 2026 18:58:17 +0200 Subject: [PATCH 06/15] load on client --- src/server/Entity.zig | 3 +++ src/server/server.zig | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server/Entity.zig b/src/server/Entity.zig index 169412a84f..ec9e32f7ca 100644 --- a/src/server/Entity.zig +++ b/src/server/Entity.zig @@ -29,6 +29,9 @@ pub fn loadFrom(self: *@This(), id: main.entity.Entity, zon: ZonElement, comptim try main.entity.loadComponentsFromBase64(components.as([]const u8) orelse "", self.id, side); } + main.entity.components.@"cubyz:swing_arm".server.load(self.id); + main.entity.components.@"cubyz:broken".server.load(self.id); + if (zon.getChildOrNull("name")) |name| { if (self.name) |oldname| { main.globalAllocator.free(oldname); diff --git a/src/server/server.zig b/src/server/server.zig index db48dd5d1f..03830290d8 100644 --- a/src/server/server.zig +++ b/src/server/server.zig @@ -324,8 +324,6 @@ pub const User = struct { // MARK: User self.loadUnloadChunks(); main.entity.components.@"cubyz:player".server.load(self.id, @truncate(self.playerIndex)); - main.entity.components.@"cubyz:swing_arm".server.load(self.id); - main.entity.components.@"cubyz:broken".server.load(self.id); } fn simArrIndex(x: i32) usize { From d88cd81e60a4de779fdbd71b2b63e591d1e967e5 Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Thu, 1 Oct 2026 19:04:41 +0200 Subject: [PATCH 07/15] load actually on client --- src/entityComponent/broken.zig | 9 +++++++++ src/entityComponent/swing_arm.zig | 9 +++++++++ src/game.zig | 3 +++ src/server/Entity.zig | 3 --- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/entityComponent/broken.zig b/src/entityComponent/broken.zig index 5caeac1424..2954610d83 100644 --- a/src/entityComponent/broken.zig +++ b/src/entityComponent/broken.zig @@ -56,6 +56,15 @@ pub const client = struct { .blockPos = blockPos, }; } + + pub fn put(entity: Entity) void { + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = .{ + .progress = 0, + .blockPos = .{0, 0, 0}, + }; + } + pub fn unload(entity: Entity) void { components.remove(entity) catch {}; } diff --git a/src/entityComponent/swing_arm.zig b/src/entityComponent/swing_arm.zig index f7b9932120..7a0cba2ca7 100644 --- a/src/entityComponent/swing_arm.zig +++ b/src/entityComponent/swing_arm.zig @@ -56,6 +56,15 @@ pub const client = struct { .currentSwingTime = currentSwingTime, }; } + + pub fn put(entity: Entity) void { + const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); + ptr.* = .{ + .currentSwingProgress = 0, + .currentSwingTime = 0, + }; + } + pub fn unload(entity: Entity) void { components.remove(entity) catch {}; } diff --git a/src/game.zig b/src/game.zig index cf679ee869..f095a42901 100644 --- a/src/game.zig +++ b/src/game.zig @@ -117,6 +117,9 @@ pub const Player = struct { // MARK: Player fn loadFrom(zon: ZonElement) !void { try super.loadFrom(id, zon, .client, undefined); + + main.entity.components.@"cubyz:swing_arm".client.put(super.id); + main.entity.components.@"cubyz:broken".client.put(super.id); } pub fn setPosBlocking(newPos: Vec3d) void { diff --git a/src/server/Entity.zig b/src/server/Entity.zig index ec9e32f7ca..169412a84f 100644 --- a/src/server/Entity.zig +++ b/src/server/Entity.zig @@ -29,9 +29,6 @@ pub fn loadFrom(self: *@This(), id: main.entity.Entity, zon: ZonElement, comptim try main.entity.loadComponentsFromBase64(components.as([]const u8) orelse "", self.id, side); } - main.entity.components.@"cubyz:swing_arm".server.load(self.id); - main.entity.components.@"cubyz:broken".server.load(self.id); - if (zon.getChildOrNull("name")) |name| { if (self.name) |oldname| { main.globalAllocator.free(oldname); From 707d5b89ba3678b1e5141ef3f9ec8ed5e4348989 Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Thu, 1 Oct 2026 19:07:42 +0200 Subject: [PATCH 08/15] renaming --- src/entityComponent/_list.zig | 4 ++-- src/entityComponent/{broken.zig => breaking.zig} | 0 src/entityComponent/{swing_arm.zig => swinging.zig} | 0 src/game.zig | 4 ++-- src/renderer.zig | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) rename src/entityComponent/{broken.zig => breaking.zig} (100%) rename src/entityComponent/{swing_arm.zig => swinging.zig} (100%) diff --git a/src/entityComponent/_list.zig b/src/entityComponent/_list.zig index f223f9c70e..280bde371a 100644 --- a/src/entityComponent/_list.zig +++ b/src/entityComponent/_list.zig @@ -1,7 +1,7 @@ pub const @"cubyz:_template" = @import("_template.zig"); pub const @"cubyz:bag" = @import("bag.zig"); -pub const @"cubyz:broken" = @import("broken.zig"); +pub const @"cubyz:breaking" = @import("breaking.zig"); pub const @"cubyz:model" = @import("model.zig"); pub const @"cubyz:permissions" = @import("permissions.zig"); pub const @"cubyz:player" = @import("player.zig"); -pub const @"cubyz:swing_arm" = @import("swing_arm.zig"); +pub const @"cubyz:swinging" = @import("swinging.zig"); diff --git a/src/entityComponent/broken.zig b/src/entityComponent/breaking.zig similarity index 100% rename from src/entityComponent/broken.zig rename to src/entityComponent/breaking.zig diff --git a/src/entityComponent/swing_arm.zig b/src/entityComponent/swinging.zig similarity index 100% rename from src/entityComponent/swing_arm.zig rename to src/entityComponent/swinging.zig diff --git a/src/game.zig b/src/game.zig index f095a42901..e06dce6e65 100644 --- a/src/game.zig +++ b/src/game.zig @@ -118,8 +118,8 @@ pub const Player = struct { // MARK: Player fn loadFrom(zon: ZonElement) !void { try super.loadFrom(id, zon, .client, undefined); - main.entity.components.@"cubyz:swing_arm".client.put(super.id); - main.entity.components.@"cubyz:broken".client.put(super.id); + main.entity.components.@"cubyz:swinging".client.put(super.id); + main.entity.components.@"cubyz:breaking".client.put(super.id); } pub fn setPosBlocking(newPos: Vec3d) void { diff --git a/src/renderer.zig b/src/renderer.zig index 088a170fac..d2c817b33b 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1063,8 +1063,8 @@ pub const MeshSelection = struct { // MARK: MeshSelection } pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { - const swingArm = main.entity.components.@"cubyz:swing_arm".client.get(main.game.Player.id) orelse return; // player can't swing... - const brokenBlock = main.entity.components.@"cubyz:broken".client.get(main.game.Player.id) orelse return; // player can't break blocks... + const swingArm = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... + const brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse return; // player can't break blocks... if (selectedBlockPos) |selectedPos| { const stack = inventory.getStack(slot); From 0d6911ed144a8f0a91e655373cdedd9ac8681dbf Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Fri, 2 Oct 2026 19:56:06 +0200 Subject: [PATCH 09/15] change it a bit --- src/entityComponent/breaking.zig | 5 +++-- src/game.zig | 1 - src/renderer.zig | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/entityComponent/breaking.zig b/src/entityComponent/breaking.zig index 2954610d83..633e3c1f62 100644 --- a/src/entityComponent/breaking.zig +++ b/src/entityComponent/breaking.zig @@ -57,12 +57,13 @@ pub const client = struct { }; } - pub fn put(entity: Entity) void { + pub fn getAndPut(entity: Entity, blockPos: Vec3i) *Component { const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); ptr.* = .{ .progress = 0, - .blockPos = .{0, 0, 0}, + .blockPos = blockPos, }; + return ptr; } pub fn unload(entity: Entity) void { diff --git a/src/game.zig b/src/game.zig index e06dce6e65..c152bf583b 100644 --- a/src/game.zig +++ b/src/game.zig @@ -119,7 +119,6 @@ pub const Player = struct { // MARK: Player try super.loadFrom(id, zon, .client, undefined); main.entity.components.@"cubyz:swinging".client.put(super.id); - main.entity.components.@"cubyz:breaking".client.put(super.id); } pub fn setPosBlocking(newPos: Vec3d) void { diff --git a/src/renderer.zig b/src/renderer.zig index d2c817b33b..4db832d7ed 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1064,9 +1064,13 @@ pub const MeshSelection = struct { // MARK: MeshSelection pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { const swingArm = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... - const brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse return; // player can't break blocks... if (selectedBlockPos) |selectedPos| { + var brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { + swingArm.currentSwingProgress = 0; + swingArm.currentSwingTime = 0; + break :blk main.entity.components.@"cubyz:breaking".client.getAndPut(main.game.Player.id, selectedPos); + }; const stack = inventory.getStack(slot); const isSelectionWand = stack.item == .baseItem and std.mem.eql(u8, stack.item.baseItem.id(), "cubyz:selection_wand"); if (isSelectionWand) { @@ -1077,9 +1081,9 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (@reduce(.Or, brokenBlock.blockPos != selectedPos)) { mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); + brokenBlock = main.entity.components.@"cubyz:breaking".client.getAndPut(main.game.Player.id, selectedPos); swingArm.currentSwingProgress = 0; - brokenBlock.blockPos = selectedPos; - brokenBlock.progress = 0; + swingArm.currentSwingTime = 0; } const block = mesh_storage.getBlockFromRenderThread(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return; const holdingTargetedBlock = stack.item == .baseItem and stack.item.baseItem.block() == block.typ; From 382c1e89855e58fce9f1672c933085572ca0a5af Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 14:28:20 +0200 Subject: [PATCH 10/15] getAndPut -> getOrPut --- src/entityComponent/breaking.zig | 2 +- src/renderer.zig | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entityComponent/breaking.zig b/src/entityComponent/breaking.zig index 633e3c1f62..cb5012ae44 100644 --- a/src/entityComponent/breaking.zig +++ b/src/entityComponent/breaking.zig @@ -57,7 +57,7 @@ pub const client = struct { }; } - pub fn getAndPut(entity: Entity, blockPos: Vec3i) *Component { + pub fn getOrPut(entity: Entity, blockPos: Vec3i) *Component { const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); ptr.* = .{ .progress = 0, diff --git a/src/renderer.zig b/src/renderer.zig index 4db832d7ed..e02b65197a 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1069,7 +1069,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection var brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { swingArm.currentSwingProgress = 0; swingArm.currentSwingTime = 0; - break :blk main.entity.components.@"cubyz:breaking".client.getAndPut(main.game.Player.id, selectedPos); + break :blk main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); }; const stack = inventory.getStack(slot); const isSelectionWand = stack.item == .baseItem and std.mem.eql(u8, stack.item.baseItem.id(), "cubyz:selection_wand"); @@ -1081,7 +1081,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (@reduce(.Or, brokenBlock.blockPos != selectedPos)) { mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); - brokenBlock = main.entity.components.@"cubyz:breaking".client.getAndPut(main.game.Player.id, selectedPos); + brokenBlock = main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); swingArm.currentSwingProgress = 0; swingArm.currentSwingTime = 0; } From 6a2cbc6a906155044af94df70f7620d9c85b0b37 Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 14:31:36 +0200 Subject: [PATCH 11/15] remove = --- src/renderer.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer.zig b/src/renderer.zig index e02b65197a..256a1407d3 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1067,8 +1067,6 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (selectedBlockPos) |selectedPos| { var brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { - swingArm.currentSwingProgress = 0; - swingArm.currentSwingTime = 0; break :blk main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); }; const stack = inventory.getStack(slot); From 7d9ccd205b7e08e1e9980c97cf80a51a9f0a60fb Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 15:59:20 +0000 Subject: [PATCH 12/15] Update src/renderer.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> --- src/renderer.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.zig b/src/renderer.zig index 256a1407d3..ecbf4235b8 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1063,7 +1063,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection } pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { - const swingArm = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... + const swinging = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... if (selectedBlockPos) |selectedPos| { var brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { From b03ce0135fd723933a5a52db53703b15e7cfc4a6 Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 15:59:28 +0000 Subject: [PATCH 13/15] Update src/renderer.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> --- src/renderer.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.zig b/src/renderer.zig index ecbf4235b8..f4ef2bc0e1 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1066,7 +1066,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection const swinging = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... if (selectedBlockPos) |selectedPos| { - var brokenBlock = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { + var breaking = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { break :blk main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); }; const stack = inventory.getStack(slot); From b953fc8e73729f93b390c28a4566a1a2b493194b Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 18:05:28 +0200 Subject: [PATCH 14/15] rename and move swinging loading --- src/game.zig | 2 -- src/renderer.zig | 55 +++++++++++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/game.zig b/src/game.zig index c152bf583b..cf679ee869 100644 --- a/src/game.zig +++ b/src/game.zig @@ -117,8 +117,6 @@ pub const Player = struct { // MARK: Player fn loadFrom(zon: ZonElement) !void { try super.loadFrom(id, zon, .client, undefined); - - main.entity.components.@"cubyz:swinging".client.put(super.id); } pub fn setPosBlocking(newPos: Vec3d) void { diff --git a/src/renderer.zig b/src/renderer.zig index f4ef2bc0e1..0695acc319 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1063,7 +1063,10 @@ pub const MeshSelection = struct { // MARK: MeshSelection } pub fn breakBlock(inventory: main.items.Inventory.ClientInventory, slot: u32, deltaTime: f64) void { - const swinging = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse return; // player can't swing... + const swinging = main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id) orelse blk: { + main.entity.components.@"cubyz:swinging".client.put(main.game.Player.id); + break :blk main.entity.components.@"cubyz:swinging".client.get(main.game.Player.id).?; + }; if (selectedBlockPos) |selectedPos| { var breaking = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { @@ -1077,11 +1080,11 @@ pub const MeshSelection = struct { // MARK: MeshSelection return; } - if (@reduce(.Or, brokenBlock.blockPos != selectedPos)) { - mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); - brokenBlock = main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); - swingArm.currentSwingProgress = 0; - swingArm.currentSwingTime = 0; + if (@reduce(.Or, breaking.blockPos != selectedPos)) { + mesh_storage.removeBreakingAnimation(breaking.blockPos); + breaking = main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); + swinging.currentSwingProgress = 0; + swinging.currentSwingTime = 0; } const block = mesh_storage.getBlockFromRenderThread(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return; const holdingTargetedBlock = stack.item == .baseItem and stack.item.baseItem.block() == block.typ; @@ -1099,44 +1102,44 @@ pub const MeshSelection = struct { // MARK: MeshSelection damage -= block.blockResistance(); if (damage > 0) { const swingTime = if (isProceduralItem and stack.item.proceduralItem.isEffectiveOn(block)) 1.0/stack.item.proceduralItem.getProperty(.swingSpeed) else 0.5; - if (swingArm.currentSwingTime > swingTime) { - swingArm.currentSwingProgress = 0; - swingArm.currentSwingTime = 0; + if (swinging.currentSwingTime > swingTime) { + swinging.currentSwingProgress = 0; + swinging.currentSwingTime = 0; } - if (swingArm.currentSwingTime == 0) { + if (swinging.currentSwingTime == 0) { const swings = @ceil(block.blockHealth()/damage); const damagePerSwing = block.blockHealth()/swings; - swingArm.currentSwingTime = damagePerSwing/damage*swingTime; + swinging.currentSwingTime = damagePerSwing/damage*swingTime; } - swingArm.currentSwingProgress += @floatCast(deltaTime); - while (swingArm.currentSwingProgress > swingArm.currentSwingTime) { - swingArm.currentSwingProgress -= swingArm.currentSwingTime; - brokenBlock.progress += damage*swingArm.currentSwingTime/swingTime/block.blockHealth(); - if (brokenBlock.progress > 0.9999) break; + swinging.currentSwingProgress += @floatCast(deltaTime); + while (swinging.currentSwingProgress > swinging.currentSwingTime) { + swinging.currentSwingProgress -= swinging.currentSwingTime; + breaking.progress += damage*swinging.currentSwingTime/swingTime/block.blockHealth(); + if (breaking.progress > 0.9999) break; const swings = @ceil(block.blockHealth()/damage); const damagePerSwing = block.blockHealth()/swings; - swingArm.currentSwingTime = damagePerSwing/damage*swingTime; + swinging.currentSwingTime = damagePerSwing/damage*swingTime; } - if (brokenBlock.progress < 0.9999) { - mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); - if (brokenBlock.progress != 0) { - mesh_storage.addBreakingAnimation(brokenBlock.blockPos, brokenBlock.progress); + if (breaking.progress < 0.9999) { + mesh_storage.removeBreakingAnimation(breaking.blockPos); + if (breaking.progress != 0) { + mesh_storage.addBreakingAnimation(breaking.blockPos, breaking.progress); } main.sync.client.mutex.unlock(); return; } else { - swingArm.currentSwingProgress = 0; - mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); - brokenBlock.progress = 0; - swingArm.currentSwingTime = 0; + swinging.currentSwingProgress = 0; + mesh_storage.removeBreakingAnimation(breaking.blockPos); + breaking.progress = 0; + swinging.currentSwingTime = 0; } } else { main.sync.client.mutex.unlock(); return; } } else { - mesh_storage.removeBreakingAnimation(brokenBlock.blockPos); + mesh_storage.removeBreakingAnimation(breaking.blockPos); } var newBlock = block; From ffcbe4ac73a1d35a10f3e474e01262047ed8545a Mon Sep 17 00:00:00 2001 From: Wunka <56411012+Wunka@users.noreply.github.com> Date: Sun, 4 Oct 2026 18:12:36 +0200 Subject: [PATCH 15/15] no reasign --- src/entityComponent/breaking.zig | 3 +-- src/renderer.zig | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/entityComponent/breaking.zig b/src/entityComponent/breaking.zig index cb5012ae44..ae2982009e 100644 --- a/src/entityComponent/breaking.zig +++ b/src/entityComponent/breaking.zig @@ -57,13 +57,12 @@ pub const client = struct { }; } - pub fn getOrPut(entity: Entity, blockPos: Vec3i) *Component { + pub fn put(entity: Entity, blockPos: Vec3i) void { const ptr = components.get(entity) orelse components.add(main.globalAllocator, entity); ptr.* = .{ .progress = 0, .blockPos = blockPos, }; - return ptr; } pub fn unload(entity: Entity) void { diff --git a/src/renderer.zig b/src/renderer.zig index 0695acc319..8ba03fe715 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -1069,8 +1069,9 @@ pub const MeshSelection = struct { // MARK: MeshSelection }; if (selectedBlockPos) |selectedPos| { - var breaking = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { - break :blk main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); + const breaking = main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id) orelse blk: { + main.entity.components.@"cubyz:breaking".client.put(main.game.Player.id, selectedPos); + break :blk main.entity.components.@"cubyz:breaking".client.get(main.game.Player.id).?; }; const stack = inventory.getStack(slot); const isSelectionWand = stack.item == .baseItem and std.mem.eql(u8, stack.item.baseItem.id(), "cubyz:selection_wand"); @@ -1082,7 +1083,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection if (@reduce(.Or, breaking.blockPos != selectedPos)) { mesh_storage.removeBreakingAnimation(breaking.blockPos); - breaking = main.entity.components.@"cubyz:breaking".client.getOrPut(main.game.Player.id, selectedPos); + main.entity.components.@"cubyz:breaking".client.put(main.game.Player.id, selectedPos); swinging.currentSwingProgress = 0; swinging.currentSwingTime = 0; }