From f86bb9454aa1b78af067a3c6946c0c4a3e19d010 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 25 Nov 2025 09:09:16 +0100 Subject: [PATCH 01/22] saplings --- src/callbacks/block/server/_list.zig | 1 + src/callbacks/block/server/sapling.zig | 91 +++++++++++++++++++ src/server/terrain/StructureMap.zig | 4 +- src/server/terrain/biomes.zig | 6 +- .../terrain/simple_structures/Boulder.zig | 2 +- .../terrain/simple_structures/FallenTree.zig | 2 +- .../terrain/simple_structures/FlowerPatch.zig | 2 +- .../terrain/simple_structures/GroundPatch.zig | 2 +- .../terrain/simple_structures/SbbGen.zig | 18 +++- .../simple_structures/SimpleTreeModel.zig | 2 +- .../simple_structures/SimpleVegetation.zig | 2 +- .../terrain/simple_structures/Stalagmite.zig | 2 +- .../structuremapgen/SimpleStructureGen.zig | 4 +- 13 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 src/callbacks/block/server/sapling.zig diff --git a/src/callbacks/block/server/_list.zig b/src/callbacks/block/server/_list.zig index 2a2a6f314a..c09607e64f 100644 --- a/src/callbacks/block/server/_list.zig +++ b/src/callbacks/block/server/_list.zig @@ -1,2 +1,3 @@ pub const leafDecay = @import("leafDecay.zig"); pub const replaceBlock = @import("replaceBlock.zig"); +pub const sapling = @import("sapling.zig"); diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig new file mode 100644 index 0000000000..fb1fae61bf --- /dev/null +++ b/src/callbacks/block/server/sapling.zig @@ -0,0 +1,91 @@ +const std = @import("std"); + +const main = @import("main"); +const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; + + +structures:main.ZonElement, +vegetationModels: ?[]SimpleStructureModel, + +pub fn init(zon: main.ZonElement) ?*@This() { + const result = main.worldArena.create(@This()); + result.structures = zon.getChild("structures").clone(main.globalAllocator); + result.vegetationModels = null; + return result; +} + +//TODO: no deinits yet + +fn initAfterBiomesHaveBeenInited(self: *@This())void{ + var vegetation = main.ListUnmanaged(SimpleStructureModel){}; + var totalChance: f32 = 0; + defer vegetation.deinit(main.stackAllocator); + for(self.structures.toSlice()) |elem| { + if(SimpleStructureModel.initModel(elem)) |model| { + vegetation.append(main.stackAllocator, model); + totalChance += model.chance; + } + } + if(totalChance > 1) { + for(vegetation.items) |*model| { + model.chance /= totalChance; + } + } + self.vegetationModels = main.worldArena.dupe(SimpleStructureModel, vegetation.items); +} + +pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result { + if(self.vegetationModels == null) + self.initAfterBiomesHaveBeenInited(); + const vegetationModels = self.vegetationModels.?; + + const wx = params.chunk.super.pos.wx + params.x; + const wy = params.chunk.super.pos.wy + params.y; + const wz = params.chunk.super.pos.wz + params.z; + const ch = params.chunk; + + // the originals have already deinited long time ago at this point :( + const caveMap = main.server.terrain.CaveMap.CaveMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); + defer caveMap.deinit(main.stackAllocator); + const biomeMap = main.server.terrain.CaveBiomeMap.CaveBiomeMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); + defer biomeMap.deinit(); + + //copied from SimpleStructureGen.generate. + var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); + var randomValue = main.random.nextFloat(&seed); + for(vegetationModels) |*model| { // TODO: Could probably use an alias table here. + if(randomValue < model.chance or true) { + + //const heightFinalized = adjustToCaveMap(biomeMap, caveMap, wpx, wpy, map.pos.wz +% relZ, model, &seed) orelse break; + model.generate(params.x, params.y, params.z, params.chunk, caveMap, biomeMap, &main.seed, false,false); + //ch.setChanged(); + //const data = map.allocator.create(SimpleStructure); + // data.* = .{ + // .wx = wpx, + // .wy = wpy, + // .wz = map.pos.wz +% heightFinalized.relZ, + // .seed = seed, + // .model = model, + // .isCeiling = heightFinalized.isCeiling, + // }; + // if(model.generationMode == .water_surface) { + // if(wpz != 0) break; + // data.wz = 0; + // } + // map.addStructure(.{ + // .internal = .{ + // .data = @ptrCast(data), + // .generateFn = &SimpleStructure.generate, + // }, + // .priority = model.priority, + // }, .{px -% margin, py -% margin, data.wz -% map.pos.wz -% marginZ}, .{px +% margin, py +% margin, data.wz -% map.pos.wz +% marginZ}); + + break; + } else { + randomValue -= model.chance; + } + } + + + return .handled; +} diff --git a/src/server/terrain/StructureMap.zig b/src/server/terrain/StructureMap.zig index a417e954ee..e4b6850e5e 100644 --- a/src/server/terrain/StructureMap.zig +++ b/src/server/terrain/StructureMap.zig @@ -14,11 +14,11 @@ const terrain = @import("terrain.zig"); const TerrainGenerationProfile = terrain.TerrainGenerationProfile; const StructureInternal = struct { - generateFn: *const fn(self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void, + generateFn: *const fn(self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void, data: *const anyopaque, pub fn generate(self: StructureInternal, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { - self.generateFn(self.data, chunk, caveMap, biomeMap); + self.generateFn(self.data, chunk, caveMap, biomeMap,true); } }; diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index cd96172474..b68c6cb42b 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -21,7 +21,7 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; const VTable = struct { loadModel: *const fn(parameters: ZonElement) ?*anyopaque, - generate: *const fn(self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void, + generate: *const fn(self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration:bool) void, hashFunction: *const fn(self: *anyopaque) u64, generationMode: GenerationMode, }; @@ -51,8 +51,8 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; } - pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void { - self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling); + pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool,inGeneration:bool) void { + self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling, inGeneration); } var modelRegistry: std.StringHashMapUnmanaged(VTable) = .{}; diff --git a/src/server/terrain/simple_structures/Boulder.zig b/src/server/terrain/simple_structures/Boulder.zig index 0c745c800b..29fa7da703 100644 --- a/src/server/terrain/simple_structures/Boulder.zig +++ b/src/server/terrain/simple_structures/Boulder.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*Boulder { return self; } -pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { _ = caveMap; const radius = self.size + self.sizeVariation*(random.nextFloat(seed)*2 - 1); // My basic idea is to use a point cloud and a potential function to achieve somewhat smooth boulders without being a sphere. diff --git a/src/server/terrain/simple_structures/FallenTree.zig b/src/server/terrain/simple_structures/FallenTree.zig index 680539d98b..e797423485 100644 --- a/src/server/terrain/simple_structures/FallenTree.zig +++ b/src/server/terrain/simple_structures/FallenTree.zig @@ -101,7 +101,7 @@ pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, ch } } -pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight); generateStump(self, x, y, z, chunk); diff --git a/src/server/terrain/simple_structures/FlowerPatch.zig b/src/server/terrain/simple_structures/FlowerPatch.zig index b51bba9ebd..83d097640a 100644 --- a/src/server/terrain/simple_structures/FlowerPatch.zig +++ b/src/server/terrain/simple_structures/FlowerPatch.zig @@ -35,7 +35,7 @@ pub fn loadModel(parameters: ZonElement) ?*FlowerPatch { return self; } -pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/GroundPatch.zig b/src/server/terrain/simple_structures/GroundPatch.zig index 73471d9fee..791e83ba3b 100644 --- a/src/server/terrain/simple_structures/GroundPatch.zig +++ b/src/server/terrain/simple_structures/GroundPatch.zig @@ -37,7 +37,7 @@ pub fn loadModel(parameters: ZonElement) ?*GroundPatch { return self; } -pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _:bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index c34a8d6043..65968579f0 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -52,11 +52,11 @@ pub fn loadModel(parameters: ZonElement) ?*SbbGen { return self; } -pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { - placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed); +pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration:bool) void { + placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed,inGeneration); } -fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64) void { +fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; @@ -68,12 +68,20 @@ fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placeme const rotatedOrigin = rotated.originBlock.pos(); const pastePosition = placementPosition - rotatedOrigin - placementDirection.relPos(); - rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); + if(inGeneration){ + rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); + }else{ + var pos = Vec3i{0,0,0}; + pos[0] = chunk.super.pos.wx + pastePosition[0]; + pos[1] = chunk.super.pos.wy + pastePosition[1]; + pos[2] = chunk.super.pos.wz + pastePosition[2]; + rotated.blueprint.paste( pos,.{}); + } for(rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; const childRotation = rotation.getChildRotation(seed, child.rotation, childBlock.direction()); - placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed); + placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed,inGeneration); } } diff --git a/src/server/terrain/simple_structures/SimpleTreeModel.zig b/src/server/terrain/simple_structures/SimpleTreeModel.zig index 30c7a85730..96c36a7f3b 100644 --- a/src/server/terrain/simple_structures/SimpleTreeModel.zig +++ b/src/server/terrain/simple_structures/SimpleTreeModel.zig @@ -90,7 +90,7 @@ pub fn generateBranch(self: *SimpleTreeModel, x: i32, y: i32, z: i32, d: u32, ch } } -pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const factor = random.nextFloat(seed); var height = self.height0 + @as(i32, @intFromFloat(factor*@as(f32, @floatFromInt(self.deltaHeight)))); const leafRadius = self.leafRadius + factor*self.deltaLeafRadius; diff --git a/src/server/terrain/simple_structures/SimpleVegetation.zig b/src/server/terrain/simple_structures/SimpleVegetation.zig index ea5d96156e..82259213cc 100644 --- a/src/server/terrain/simple_structures/SimpleVegetation.zig +++ b/src/server/terrain/simple_structures/SimpleVegetation.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*SimpleVegetation { return self; } -pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool) void { +pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool,_:bool) void { if(chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight + 1); if(z + height >= caveMap.findTerrainChangeAbove(x, y, z)) return; // Space is too small. diff --git a/src/server/terrain/simple_structures/Stalagmite.zig b/src/server/terrain/simple_structures/Stalagmite.zig index a2fa5d6914..d5673c1a94 100644 --- a/src/server/terrain/simple_structures/Stalagmite.zig +++ b/src/server/terrain/simple_structures/Stalagmite.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*Stalagmite { return self; } -pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool) void { +pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool,_:bool) void { const relX: f32 = @as(f32, @floatFromInt(x)) + main.random.nextFloat(seed); const relY: f32 = @as(f32, @floatFromInt(y)) + main.random.nextFloat(seed); var relZ: f32 = @as(f32, @floatFromInt(z)) + main.random.nextFloat(seed); diff --git a/src/server/terrain/structuremapgen/SimpleStructureGen.zig b/src/server/terrain/structuremapgen/SimpleStructureGen.zig index f250066fe9..d642b99b4a 100644 --- a/src/server/terrain/structuremapgen/SimpleStructureGen.zig +++ b/src/server/terrain/structuremapgen/SimpleStructureGen.zig @@ -194,12 +194,12 @@ const SimpleStructure = struct { wz: i32, isCeiling: bool, - pub fn generate(_self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { + pub fn generate(_self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void { const self: *const SimpleStructure = @ptrCast(@alignCast(_self)); var seed = self.seed; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; const relZ = self.wz - chunk.super.pos.wz; - self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling); + self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling, inGeneration); } }; From 4f5bebb39650ac136aba04177d9cfdac22959090 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 25 Nov 2025 09:09:50 +0100 Subject: [PATCH 02/22] tmp: cactus_flower as sapling --- assets/cubyz/blocks/cactus_flower.zig.zon | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/assets/cubyz/blocks/cactus_flower.zig.zon b/assets/cubyz/blocks/cactus_flower.zig.zon index c96512a869..bc2361f49d 100644 --- a/assets/cubyz/blocks/cactus_flower.zig.zon +++ b/assets/cubyz/blocks/cactus_flower.zig.zon @@ -4,6 +4,23 @@ .drops = .{ .{.items = .{.auto}}, }, + .onTick = .{ + .type = .sapling, + .structures = .{ + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/saguaro", + .placeMode = .degradable, + .chance = 0.01, + }, + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/young", + .placeMode = .degradable, + .chance = 0.006, + }, + } + }, .degradable = true, .collide = false, .alwaysViewThrough = true, From 14d97e8f563a17a4c29a38bc45ae8db38415d36a Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 25 Nov 2025 09:09:16 +0100 Subject: [PATCH 03/22] saplings --- src/callbacks/block/server/_list.zig | 1 + src/callbacks/block/server/sapling.zig | 91 +++++++++++++++++++ src/server/terrain/StructureMap.zig | 4 +- src/server/terrain/biomes.zig | 6 +- .../terrain/simple_structures/Boulder.zig | 2 +- .../terrain/simple_structures/FallenTree.zig | 2 +- .../terrain/simple_structures/FlowerPatch.zig | 2 +- .../terrain/simple_structures/GroundPatch.zig | 2 +- .../terrain/simple_structures/SbbGen.zig | 18 +++- .../simple_structures/SimpleTreeModel.zig | 2 +- .../simple_structures/SimpleVegetation.zig | 4 +- .../structuremapgen/SimpleStructureGen.zig | 4 +- 12 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 src/callbacks/block/server/sapling.zig diff --git a/src/callbacks/block/server/_list.zig b/src/callbacks/block/server/_list.zig index 53f9eb7744..b6c4fd424e 100644 --- a/src/callbacks/block/server/_list.zig +++ b/src/callbacks/block/server/_list.zig @@ -1,3 +1,4 @@ pub const checkSupportBlocks = @import("checkSupportBlocks.zig"); pub const decay = @import("decay.zig"); pub const replaceBlock = @import("replaceBlock.zig"); +pub const sapling = @import("sapling.zig"); diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig new file mode 100644 index 0000000000..fb1fae61bf --- /dev/null +++ b/src/callbacks/block/server/sapling.zig @@ -0,0 +1,91 @@ +const std = @import("std"); + +const main = @import("main"); +const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; + + +structures:main.ZonElement, +vegetationModels: ?[]SimpleStructureModel, + +pub fn init(zon: main.ZonElement) ?*@This() { + const result = main.worldArena.create(@This()); + result.structures = zon.getChild("structures").clone(main.globalAllocator); + result.vegetationModels = null; + return result; +} + +//TODO: no deinits yet + +fn initAfterBiomesHaveBeenInited(self: *@This())void{ + var vegetation = main.ListUnmanaged(SimpleStructureModel){}; + var totalChance: f32 = 0; + defer vegetation.deinit(main.stackAllocator); + for(self.structures.toSlice()) |elem| { + if(SimpleStructureModel.initModel(elem)) |model| { + vegetation.append(main.stackAllocator, model); + totalChance += model.chance; + } + } + if(totalChance > 1) { + for(vegetation.items) |*model| { + model.chance /= totalChance; + } + } + self.vegetationModels = main.worldArena.dupe(SimpleStructureModel, vegetation.items); +} + +pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result { + if(self.vegetationModels == null) + self.initAfterBiomesHaveBeenInited(); + const vegetationModels = self.vegetationModels.?; + + const wx = params.chunk.super.pos.wx + params.x; + const wy = params.chunk.super.pos.wy + params.y; + const wz = params.chunk.super.pos.wz + params.z; + const ch = params.chunk; + + // the originals have already deinited long time ago at this point :( + const caveMap = main.server.terrain.CaveMap.CaveMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); + defer caveMap.deinit(main.stackAllocator); + const biomeMap = main.server.terrain.CaveBiomeMap.CaveBiomeMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); + defer biomeMap.deinit(); + + //copied from SimpleStructureGen.generate. + var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); + var randomValue = main.random.nextFloat(&seed); + for(vegetationModels) |*model| { // TODO: Could probably use an alias table here. + if(randomValue < model.chance or true) { + + //const heightFinalized = adjustToCaveMap(biomeMap, caveMap, wpx, wpy, map.pos.wz +% relZ, model, &seed) orelse break; + model.generate(params.x, params.y, params.z, params.chunk, caveMap, biomeMap, &main.seed, false,false); + //ch.setChanged(); + //const data = map.allocator.create(SimpleStructure); + // data.* = .{ + // .wx = wpx, + // .wy = wpy, + // .wz = map.pos.wz +% heightFinalized.relZ, + // .seed = seed, + // .model = model, + // .isCeiling = heightFinalized.isCeiling, + // }; + // if(model.generationMode == .water_surface) { + // if(wpz != 0) break; + // data.wz = 0; + // } + // map.addStructure(.{ + // .internal = .{ + // .data = @ptrCast(data), + // .generateFn = &SimpleStructure.generate, + // }, + // .priority = model.priority, + // }, .{px -% margin, py -% margin, data.wz -% map.pos.wz -% marginZ}, .{px +% margin, py +% margin, data.wz -% map.pos.wz +% marginZ}); + + break; + } else { + randomValue -= model.chance; + } + } + + + return .handled; +} diff --git a/src/server/terrain/StructureMap.zig b/src/server/terrain/StructureMap.zig index 1a1592a55a..338e02b885 100644 --- a/src/server/terrain/StructureMap.zig +++ b/src/server/terrain/StructureMap.zig @@ -15,11 +15,11 @@ const GeneratorState = terrain.GeneratorState; const TerrainGenerationProfile = terrain.TerrainGenerationProfile; const StructureInternal = struct { - generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void, + generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void, data: *const anyopaque, pub fn generate(self: StructureInternal, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { - self.generateFn(self.data, chunk, caveMap, biomeMap); + self.generateFn(self.data, chunk, caveMap, biomeMap,true); } }; diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index c0fbe78b85..543a072f55 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -21,7 +21,7 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; const VTable = struct { loadModel: *const fn (parameters: ZonElement) ?*anyopaque, - generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void, + generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration:bool) void, hashFunction: *const fn (self: *anyopaque) u64, generationMode: GenerationMode, }; @@ -51,8 +51,8 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; } - pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void { - self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling); + pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool,inGeneration:bool) void { + self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling, inGeneration); } var modelRegistry: std.StringHashMapUnmanaged(VTable) = .{}; diff --git a/src/server/terrain/simple_structures/Boulder.zig b/src/server/terrain/simple_structures/Boulder.zig index 6a489ba9a9..9034713fad 100644 --- a/src/server/terrain/simple_structures/Boulder.zig +++ b/src/server/terrain/simple_structures/Boulder.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*Boulder { return self; } -pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { _ = caveMap; const radius = self.size + self.sizeVariation*(random.nextFloat(seed)*2 - 1); // My basic idea is to use a point cloud and a potential function to achieve somewhat smooth boulders without being a sphere. diff --git a/src/server/terrain/simple_structures/FallenTree.zig b/src/server/terrain/simple_structures/FallenTree.zig index 401f1d8961..3f3b4f611a 100644 --- a/src/server/terrain/simple_structures/FallenTree.zig +++ b/src/server/terrain/simple_structures/FallenTree.zig @@ -101,7 +101,7 @@ pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, ch } } -pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight); generateStump(self, x, y, z, chunk); diff --git a/src/server/terrain/simple_structures/FlowerPatch.zig b/src/server/terrain/simple_structures/FlowerPatch.zig index a5189708dc..b1399bc72d 100644 --- a/src/server/terrain/simple_structures/FlowerPatch.zig +++ b/src/server/terrain/simple_structures/FlowerPatch.zig @@ -35,7 +35,7 @@ pub fn loadModel(parameters: ZonElement) ?*FlowerPatch { return self; } -pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/GroundPatch.zig b/src/server/terrain/simple_structures/GroundPatch.zig index 1236bb3917..5fdc250610 100644 --- a/src/server/terrain/simple_structures/GroundPatch.zig +++ b/src/server/terrain/simple_structures/GroundPatch.zig @@ -37,7 +37,7 @@ pub fn loadModel(parameters: ZonElement) ?*GroundPatch { return self; } -pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _:bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 43f034b50c..40dd93b7b9 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -52,11 +52,11 @@ pub fn loadModel(parameters: ZonElement) ?*SbbGen { return self; } -pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { - placeSbb(self, self.structureRef, Vec3i{x, y, z}, null, self.rotation.getInitialRotation(seed), chunk, seed); +pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration:bool) void { + placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed,inGeneration); } -fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64) void { +fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; @@ -68,12 +68,20 @@ fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placeme const rotatedOrigin = rotated.originBlock.pos(); const pastePosition = placementPosition - rotatedOrigin - (placementDirection orelse origin.direction()).relPos(); - rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); + if(inGeneration){ + rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); + }else{ + var pos = Vec3i{0,0,0}; + pos[0] = chunk.super.pos.wx + pastePosition[0]; + pos[1] = chunk.super.pos.wy + pastePosition[1]; + pos[2] = chunk.super.pos.wz + pastePosition[2]; + rotated.blueprint.paste( pos,.{}); + } for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; const childRotation = rotation.getChildRotation(seed, child.rotation, childBlock.direction()); - placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed); + placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed,inGeneration); } } diff --git a/src/server/terrain/simple_structures/SimpleTreeModel.zig b/src/server/terrain/simple_structures/SimpleTreeModel.zig index 99484c8af0..bd9f06476f 100644 --- a/src/server/terrain/simple_structures/SimpleTreeModel.zig +++ b/src/server/terrain/simple_structures/SimpleTreeModel.zig @@ -90,7 +90,7 @@ pub fn generateBranch(self: *SimpleTreeModel, x: i32, y: i32, z: i32, d: u32, ch } } -pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const factor = random.nextFloat(seed); var height = self.height0 + @as(i32, @intFromFloat(factor*@as(f32, @floatFromInt(self.deltaHeight)))); const leafRadius = self.leafRadius + factor*self.deltaLeafRadius; diff --git a/src/server/terrain/simple_structures/SimpleVegetation.zig b/src/server/terrain/simple_structures/SimpleVegetation.zig index 975d324bea..68965afbe3 100644 --- a/src/server/terrain/simple_structures/SimpleVegetation.zig +++ b/src/server/terrain/simple_structures/SimpleVegetation.zig @@ -33,8 +33,8 @@ pub fn loadModel(parameters: ZonElement) ?*SimpleVegetation { return self; } -pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool) void { - if (chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; +pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool,_:bool) void { + if(chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight + 1); if (z + height >= caveMap.findTerrainChangeAbove(x, y, z)) return; // Space is too small. var pz: i32 = chunk.startIndex(z); diff --git a/src/server/terrain/structuremapgen/SimpleStructureGen.zig b/src/server/terrain/structuremapgen/SimpleStructureGen.zig index 3ecff6a414..07dbc96338 100644 --- a/src/server/terrain/structuremapgen/SimpleStructureGen.zig +++ b/src/server/terrain/structuremapgen/SimpleStructureGen.zig @@ -196,11 +196,11 @@ pub const SimpleStructure = struct { wz: i32, isCeiling: bool, - pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { + pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void { var seed = self.seed; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; const relZ = self.wz - chunk.super.pos.wz; - self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling); + self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling, inGeneration); } }; From e216b6203d2098a2c2b8e9d458bbc318dcd1dcbc Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 25 Nov 2025 09:09:50 +0100 Subject: [PATCH 04/22] tmp: cactus_flower as sapling --- assets/cubyz/blocks/cactus_flower.zig.zon | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/assets/cubyz/blocks/cactus_flower.zig.zon b/assets/cubyz/blocks/cactus_flower.zig.zon index f98419d1a6..ce21588650 100644 --- a/assets/cubyz/blocks/cactus_flower.zig.zon +++ b/assets/cubyz/blocks/cactus_flower.zig.zon @@ -4,6 +4,23 @@ .drops = .{ .{.items = .{.auto}}, }, + .onTick = .{ + .type = .sapling, + .structures = .{ + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/saguaro", + .placeMode = .degradable, + .chance = 0.01, + }, + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/young", + .placeMode = .degradable, + .chance = 0.006, + }, + } + }, .degradable = true, .collide = false, .alwaysViewThrough = true, From 10c38362351f2489248c30716dad60778bda8f7f Mon Sep 17 00:00:00 2001 From: till++ Date: Sun, 22 Feb 2026 22:49:06 +0100 Subject: [PATCH 05/22] fixed memory leak and added oak sapling --- assets/cubyz/blocks/sapling/oak.zon | 39 +++++++++++++++++++ src/callbacks/block/server/sapling.zig | 12 +++--- .../terrain/simple_structures/SbbGen.zig | 2 +- .../terrain/simple_structures/Stalagmite.zig | 2 +- .../SbbEnumerationGenerator.zig | 2 +- 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 assets/cubyz/blocks/sapling/oak.zon diff --git a/assets/cubyz/blocks/sapling/oak.zon b/assets/cubyz/blocks/sapling/oak.zon new file mode 100644 index 0000000000..6cd9705fe1 --- /dev/null +++ b/assets/cubyz/blocks/sapling/oak.zon @@ -0,0 +1,39 @@ +.{ + .tags = .{.cuttable}, + .blockHealth = 0.2, + .drops = .{ + .{.items = .{.auto}}, + }, + .onTick = .{ + .type = .sapling, + .structures = .{ + .{ + .id = "cubyz:sbb", + .structure = "cubyz:tree/oak/white", + .placeMode = .degradable, + .chance = 0.03, + } + } + }, + .degradable = true, + .collide = false, + .alwaysViewThrough = true, + .absorbedLight = 0x121012, + .model = "cubyz:cactus_flower", + .rotation = "cubyz:direction", + .texture = "cubyz:cactus_flower", + .texture_top = "cubyz:cactus_flower_top", + .texture_bottom = "cubyz:cactus_flower_top", + .item = .{ + .texture = "cactus_flower.png", + }, + .lodReplacement = "cubyz:air", + .onTouch = .{ + .type = .hurt, + .dps = 0.2, + .damageType = .spiky, + }, + .onUpdate = .{ + .type = .checkSupportBlocks, + }, +} diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index fb1fae61bf..f1ac15345e 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -9,7 +9,7 @@ vegetationModels: ?[]SimpleStructureModel, pub fn init(zon: main.ZonElement) ?*@This() { const result = main.worldArena.create(@This()); - result.structures = zon.getChild("structures").clone(main.globalAllocator); + result.structures = zon.getChild("structures").clone(main.worldArena); result.vegetationModels = null; return result; } @@ -39,9 +39,9 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma self.initAfterBiomesHaveBeenInited(); const vegetationModels = self.vegetationModels.?; - const wx = params.chunk.super.pos.wx + params.x; - const wy = params.chunk.super.pos.wy + params.y; - const wz = params.chunk.super.pos.wz + params.z; + const wx = params.chunk.super.pos.wx + params.blockPos.x; + const wy = params.chunk.super.pos.wy + params.blockPos.y; + const wz = params.chunk.super.pos.wz + params.blockPos.z; const ch = params.chunk; // the originals have already deinited long time ago at this point :( @@ -54,10 +54,10 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); var randomValue = main.random.nextFloat(&seed); for(vegetationModels) |*model| { // TODO: Could probably use an alias table here. - if(randomValue < model.chance or true) { + if(randomValue < model.chance) { //const heightFinalized = adjustToCaveMap(biomeMap, caveMap, wpx, wpy, map.pos.wz +% relZ, model, &seed) orelse break; - model.generate(params.x, params.y, params.z, params.chunk, caveMap, biomeMap, &main.seed, false,false); + model.generate(params.blockPos.x, params.blockPos.y, params.blockPos.z, params.chunk, caveMap, biomeMap, &main.seed, false,false); //ch.setChanged(); //const data = map.allocator.create(SimpleStructure); // data.* = .{ diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 40dd93b7b9..67174104d3 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -56,7 +56,7 @@ pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed,inGeneration); } -fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { +fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; diff --git a/src/server/terrain/simple_structures/Stalagmite.zig b/src/server/terrain/simple_structures/Stalagmite.zig index 4a8ad5fc92..c20340f1e6 100644 --- a/src/server/terrain/simple_structures/Stalagmite.zig +++ b/src/server/terrain/simple_structures/Stalagmite.zig @@ -39,7 +39,7 @@ pub fn loadModel(parameters: ZonElement) ?*Stalagmite { return self; } -pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { +pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { const relX: f32 = @as(f32, @floatFromInt(x)) + main.random.nextFloat(seed)*0.6 - 0.3; const relY: f32 = @as(f32, @floatFromInt(y)) + main.random.nextFloat(seed)*0.6 - 0.3; const relZ: f32 = @as(f32, @floatFromInt(z)) + main.random.nextFloat(seed)*0.6 - 0.3; diff --git a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig index 955998f8c1..1f6ad76acb 100644 --- a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig +++ b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig @@ -193,7 +193,7 @@ const SignGenerator = struct { wz: i32, id: []const u8, - pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView) void { + pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView,_:bool) void { if (chunk.super.pos.voxelSize != 1) return; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; From 08ecb24c5cde96f2f9a5bc7f873214041b1d13a3 Mon Sep 17 00:00:00 2001 From: till++ Date: Sun, 22 Feb 2026 23:35:18 +0100 Subject: [PATCH 06/22] format --- assets/cubyz/blocks/cactus_flower.zig.zon | 31 +++++++++---------- assets/cubyz/blocks/sapling/oak.zon | 19 +++++------- src/callbacks/block/server/sapling.zig | 28 ++++++++--------- src/server/terrain/StructureMap.zig | 4 +-- src/server/terrain/biomes.zig | 4 +-- .../terrain/simple_structures/Boulder.zig | 2 +- .../terrain/simple_structures/FallenTree.zig | 2 +- .../terrain/simple_structures/FlowerPatch.zig | 2 +- .../terrain/simple_structures/GroundPatch.zig | 2 +- .../terrain/simple_structures/SbbGen.zig | 14 ++++----- .../simple_structures/SimpleTreeModel.zig | 2 +- .../simple_structures/SimpleVegetation.zig | 4 +-- .../terrain/simple_structures/Stalagmite.zig | 2 +- .../SbbEnumerationGenerator.zig | 2 +- .../structuremapgen/SimpleStructureGen.zig | 2 +- 15 files changed, 56 insertions(+), 64 deletions(-) diff --git a/assets/cubyz/blocks/cactus_flower.zig.zon b/assets/cubyz/blocks/cactus_flower.zig.zon index ce21588650..b1b5ae0551 100644 --- a/assets/cubyz/blocks/cactus_flower.zig.zon +++ b/assets/cubyz/blocks/cactus_flower.zig.zon @@ -4,23 +4,20 @@ .drops = .{ .{.items = .{.auto}}, }, - .onTick = .{ - .type = .sapling, - .structures = .{ - .{ - .id = "cubyz:sbb", - .structure = "cubyz:cactus/saguaro", - .placeMode = .degradable, - .chance = 0.01, - }, - .{ - .id = "cubyz:sbb", - .structure = "cubyz:cactus/young", - .placeMode = .degradable, - .chance = 0.006, - }, - } - }, + .onTick = .{.type = .sapling, .structures = .{ + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/saguaro", + .placeMode = .degradable, + .chance = 0.01, + }, + .{ + .id = "cubyz:sbb", + .structure = "cubyz:cactus/young", + .placeMode = .degradable, + .chance = 0.006, + }, + }}, .degradable = true, .collide = false, .alwaysViewThrough = true, diff --git a/assets/cubyz/blocks/sapling/oak.zon b/assets/cubyz/blocks/sapling/oak.zon index 6cd9705fe1..f831768e7a 100644 --- a/assets/cubyz/blocks/sapling/oak.zon +++ b/assets/cubyz/blocks/sapling/oak.zon @@ -4,17 +4,14 @@ .drops = .{ .{.items = .{.auto}}, }, - .onTick = .{ - .type = .sapling, - .structures = .{ - .{ - .id = "cubyz:sbb", - .structure = "cubyz:tree/oak/white", - .placeMode = .degradable, - .chance = 0.03, - } - } - }, + .onTick = .{.type = .sapling, .structures = .{ + .{ + .id = "cubyz:sbb", + .structure = "cubyz:tree/oak/white", + .placeMode = .degradable, + .chance = 0.03, + }, + }}, .degradable = true, .collide = false, .alwaysViewThrough = true, diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index f1ac15345e..0d5ca32e06 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -3,39 +3,38 @@ const std = @import("std"); const main = @import("main"); const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; - -structures:main.ZonElement, +structures: main.ZonElement, vegetationModels: ?[]SimpleStructureModel, pub fn init(zon: main.ZonElement) ?*@This() { const result = main.worldArena.create(@This()); - result.structures = zon.getChild("structures").clone(main.worldArena); + result.structures = zon.getChild("structures").clone(main.worldArena); result.vegetationModels = null; return result; } //TODO: no deinits yet -fn initAfterBiomesHaveBeenInited(self: *@This())void{ +fn initAfterBiomesHaveBeenInited(self: *@This()) void { var vegetation = main.ListUnmanaged(SimpleStructureModel){}; var totalChance: f32 = 0; defer vegetation.deinit(main.stackAllocator); - for(self.structures.toSlice()) |elem| { - if(SimpleStructureModel.initModel(elem)) |model| { + for (self.structures.toSlice()) |elem| { + if (SimpleStructureModel.initModel(elem)) |model| { vegetation.append(main.stackAllocator, model); totalChance += model.chance; } } - if(totalChance > 1) { - for(vegetation.items) |*model| { + if (totalChance > 1) { + for (vegetation.items) |*model| { model.chance /= totalChance; } } self.vegetationModels = main.worldArena.dupe(SimpleStructureModel, vegetation.items); } - + pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result { - if(self.vegetationModels == null) + if (self.vegetationModels == null) self.initAfterBiomesHaveBeenInited(); const vegetationModels = self.vegetationModels.?; @@ -53,11 +52,11 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma //copied from SimpleStructureGen.generate. var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); var randomValue = main.random.nextFloat(&seed); - for(vegetationModels) |*model| { // TODO: Could probably use an alias table here. - if(randomValue < model.chance) { + for (vegetationModels) |*model| { // TODO: Could probably use an alias table here. + if (randomValue < model.chance) { //const heightFinalized = adjustToCaveMap(biomeMap, caveMap, wpx, wpy, map.pos.wz +% relZ, model, &seed) orelse break; - model.generate(params.blockPos.x, params.blockPos.y, params.blockPos.z, params.chunk, caveMap, biomeMap, &main.seed, false,false); + model.generate(params.blockPos.x, params.blockPos.y, params.blockPos.z, params.chunk, caveMap, biomeMap, &main.seed, false, false); //ch.setChanged(); //const data = map.allocator.create(SimpleStructure); // data.* = .{ @@ -79,13 +78,12 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma // }, // .priority = model.priority, // }, .{px -% margin, py -% margin, data.wz -% map.pos.wz -% marginZ}, .{px +% margin, py +% margin, data.wz -% map.pos.wz +% marginZ}); - + break; } else { randomValue -= model.chance; } } - return .handled; } diff --git a/src/server/terrain/StructureMap.zig b/src/server/terrain/StructureMap.zig index 338e02b885..8764846e30 100644 --- a/src/server/terrain/StructureMap.zig +++ b/src/server/terrain/StructureMap.zig @@ -15,11 +15,11 @@ const GeneratorState = terrain.GeneratorState; const TerrainGenerationProfile = terrain.TerrainGenerationProfile; const StructureInternal = struct { - generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void, + generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, inGeneration: bool) void, data: *const anyopaque, pub fn generate(self: StructureInternal, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { - self.generateFn(self.data, chunk, caveMap, biomeMap,true); + self.generateFn(self.data, chunk, caveMap, biomeMap, true); } }; diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index 543a072f55..c3b6fe5132 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -21,7 +21,7 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; const VTable = struct { loadModel: *const fn (parameters: ZonElement) ?*anyopaque, - generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration:bool) void, + generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration: bool) void, hashFunction: *const fn (self: *anyopaque) u64, generationMode: GenerationMode, }; @@ -51,7 +51,7 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; } - pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool,inGeneration:bool) void { + pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration: bool) void { self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling, inGeneration); } diff --git a/src/server/terrain/simple_structures/Boulder.zig b/src/server/terrain/simple_structures/Boulder.zig index 9034713fad..20c03f50f6 100644 --- a/src/server/terrain/simple_structures/Boulder.zig +++ b/src/server/terrain/simple_structures/Boulder.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*Boulder { return self; } -pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { +pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { _ = caveMap; const radius = self.size + self.sizeVariation*(random.nextFloat(seed)*2 - 1); // My basic idea is to use a point cloud and a potential function to achieve somewhat smooth boulders without being a sphere. diff --git a/src/server/terrain/simple_structures/FallenTree.zig b/src/server/terrain/simple_structures/FallenTree.zig index 3f3b4f611a..e41eca2694 100644 --- a/src/server/terrain/simple_structures/FallenTree.zig +++ b/src/server/terrain/simple_structures/FallenTree.zig @@ -101,7 +101,7 @@ pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, ch } } -pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { +pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight); generateStump(self, x, y, z, chunk); diff --git a/src/server/terrain/simple_structures/FlowerPatch.zig b/src/server/terrain/simple_structures/FlowerPatch.zig index b1399bc72d..f3eb1c2c60 100644 --- a/src/server/terrain/simple_structures/FlowerPatch.zig +++ b/src/server/terrain/simple_structures/FlowerPatch.zig @@ -35,7 +35,7 @@ pub fn loadModel(parameters: ZonElement) ?*FlowerPatch { return self; } -pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { +pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/GroundPatch.zig b/src/server/terrain/simple_structures/GroundPatch.zig index 5fdc250610..afe34febca 100644 --- a/src/server/terrain/simple_structures/GroundPatch.zig +++ b/src/server/terrain/simple_structures/GroundPatch.zig @@ -37,7 +37,7 @@ pub fn loadModel(parameters: ZonElement) ?*GroundPatch { return self; } -pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _:bool) void { +pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 67174104d3..faf88d9f63 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -52,8 +52,8 @@ pub fn loadModel(parameters: ZonElement) ?*SbbGen { return self; } -pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration:bool) void { - placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed,inGeneration); +pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration: bool) void { + placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed, inGeneration); } fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { @@ -68,20 +68,20 @@ fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placeme const rotatedOrigin = rotated.originBlock.pos(); const pastePosition = placementPosition - rotatedOrigin - (placementDirection orelse origin.direction()).relPos(); - if(inGeneration){ + if (inGeneration) { rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); - }else{ - var pos = Vec3i{0,0,0}; + } else { + var pos = Vec3i{0, 0, 0}; pos[0] = chunk.super.pos.wx + pastePosition[0]; pos[1] = chunk.super.pos.wy + pastePosition[1]; pos[2] = chunk.super.pos.wz + pastePosition[2]; - rotated.blueprint.paste( pos,.{}); + rotated.blueprint.paste(pos, .{}); } for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; const childRotation = rotation.getChildRotation(seed, child.rotation, childBlock.direction()); - placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed,inGeneration); + placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed, inGeneration); } } diff --git a/src/server/terrain/simple_structures/SimpleTreeModel.zig b/src/server/terrain/simple_structures/SimpleTreeModel.zig index bd9f06476f..961e33fd91 100644 --- a/src/server/terrain/simple_structures/SimpleTreeModel.zig +++ b/src/server/terrain/simple_structures/SimpleTreeModel.zig @@ -90,7 +90,7 @@ pub fn generateBranch(self: *SimpleTreeModel, x: i32, y: i32, z: i32, d: u32, ch } } -pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { +pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { const factor = random.nextFloat(seed); var height = self.height0 + @as(i32, @intFromFloat(factor*@as(f32, @floatFromInt(self.deltaHeight)))); const leafRadius = self.leafRadius + factor*self.deltaLeafRadius; diff --git a/src/server/terrain/simple_structures/SimpleVegetation.zig b/src/server/terrain/simple_structures/SimpleVegetation.zig index 68965afbe3..aee033f8fe 100644 --- a/src/server/terrain/simple_structures/SimpleVegetation.zig +++ b/src/server/terrain/simple_structures/SimpleVegetation.zig @@ -33,8 +33,8 @@ pub fn loadModel(parameters: ZonElement) ?*SimpleVegetation { return self; } -pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool,_:bool) void { - if(chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; +pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool, _: bool) void { + if (chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight + 1); if (z + height >= caveMap.findTerrainChangeAbove(x, y, z)) return; // Space is too small. var pz: i32 = chunk.startIndex(z); diff --git a/src/server/terrain/simple_structures/Stalagmite.zig b/src/server/terrain/simple_structures/Stalagmite.zig index c20340f1e6..ede82d6546 100644 --- a/src/server/terrain/simple_structures/Stalagmite.zig +++ b/src/server/terrain/simple_structures/Stalagmite.zig @@ -39,7 +39,7 @@ pub fn loadModel(parameters: ZonElement) ?*Stalagmite { return self; } -pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool,_:bool) void { +pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { const relX: f32 = @as(f32, @floatFromInt(x)) + main.random.nextFloat(seed)*0.6 - 0.3; const relY: f32 = @as(f32, @floatFromInt(y)) + main.random.nextFloat(seed)*0.6 - 0.3; const relZ: f32 = @as(f32, @floatFromInt(z)) + main.random.nextFloat(seed)*0.6 - 0.3; diff --git a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig index 1f6ad76acb..c461115802 100644 --- a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig +++ b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig @@ -193,7 +193,7 @@ const SignGenerator = struct { wz: i32, id: []const u8, - pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView,_:bool) void { + pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView, _: bool) void { if (chunk.super.pos.voxelSize != 1) return; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; diff --git a/src/server/terrain/structuremapgen/SimpleStructureGen.zig b/src/server/terrain/structuremapgen/SimpleStructureGen.zig index 07dbc96338..c94266ef49 100644 --- a/src/server/terrain/structuremapgen/SimpleStructureGen.zig +++ b/src/server/terrain/structuremapgen/SimpleStructureGen.zig @@ -196,7 +196,7 @@ pub const SimpleStructure = struct { wz: i32, isCeiling: bool, - pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView,inGeneration:bool) void { + pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, inGeneration: bool) void { var seed = self.seed; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; From 5b68a8d169ed5372454df3e8c49662aeb870041a Mon Sep 17 00:00:00 2001 From: till++ Date: Mon, 23 Feb 2026 00:00:08 +0100 Subject: [PATCH 07/22] fmt --- src/callbacks/block/server/sapling.zig | 27 +------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index 0d5ca32e06..83abce450b 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -13,8 +13,6 @@ pub fn init(zon: main.ZonElement) ?*@This() { return result; } -//TODO: no deinits yet - fn initAfterBiomesHaveBeenInited(self: *@This()) void { var vegetation = main.ListUnmanaged(SimpleStructureModel){}; var totalChance: f32 = 0; @@ -49,35 +47,12 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma const biomeMap = main.server.terrain.CaveBiomeMap.CaveBiomeMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); defer biomeMap.deinit(); - //copied from SimpleStructureGen.generate. + // copied from SimpleStructureGen.generate. var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); var randomValue = main.random.nextFloat(&seed); for (vegetationModels) |*model| { // TODO: Could probably use an alias table here. if (randomValue < model.chance) { - - //const heightFinalized = adjustToCaveMap(biomeMap, caveMap, wpx, wpy, map.pos.wz +% relZ, model, &seed) orelse break; model.generate(params.blockPos.x, params.blockPos.y, params.blockPos.z, params.chunk, caveMap, biomeMap, &main.seed, false, false); - //ch.setChanged(); - //const data = map.allocator.create(SimpleStructure); - // data.* = .{ - // .wx = wpx, - // .wy = wpy, - // .wz = map.pos.wz +% heightFinalized.relZ, - // .seed = seed, - // .model = model, - // .isCeiling = heightFinalized.isCeiling, - // }; - // if(model.generationMode == .water_surface) { - // if(wpz != 0) break; - // data.wz = 0; - // } - // map.addStructure(.{ - // .internal = .{ - // .data = @ptrCast(data), - // .generateFn = &SimpleStructure.generate, - // }, - // .priority = model.priority, - // }, .{px -% margin, py -% margin, data.wz -% map.pos.wz -% marginZ}, .{px +% margin, py +% margin, data.wz -% map.pos.wz +% marginZ}); break; } else { From c74e085b28460aa46cef3c86041b57d877cccca0 Mon Sep 17 00:00:00 2001 From: till++ Date: Mon, 23 Feb 2026 00:06:54 +0100 Subject: [PATCH 08/22] format --- assets/cubyz/blocks/sapling/{oak.zon => oak.zig.zon} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename assets/cubyz/blocks/sapling/{oak.zon => oak.zig.zon} (100%) diff --git a/assets/cubyz/blocks/sapling/oak.zon b/assets/cubyz/blocks/sapling/oak.zig.zon similarity index 100% rename from assets/cubyz/blocks/sapling/oak.zon rename to assets/cubyz/blocks/sapling/oak.zig.zon From 88962189ac0dcf9c36620f7b6023a0a75fa697ed Mon Sep 17 00:00:00 2001 From: till++ Date: Wed, 25 Feb 2026 07:53:03 +0100 Subject: [PATCH 09/22] Only allow SBBs --- assets/cubyz/blocks/cactus_flower.zig.zon | 14 ---- assets/cubyz/blocks/sapling/cactus.zig.zon | 33 ++++++++++ assets/cubyz/blocks/sapling/oak.zig.zon | 8 +-- src/callbacks/block/server/sapling.zig | 65 ++++++------------- src/server/terrain/biomes.zig | 1 + .../terrain/simple_structures/SbbGen.zig | 6 +- 6 files changed, 62 insertions(+), 65 deletions(-) create mode 100644 assets/cubyz/blocks/sapling/cactus.zig.zon diff --git a/assets/cubyz/blocks/cactus_flower.zig.zon b/assets/cubyz/blocks/cactus_flower.zig.zon index b1b5ae0551..f98419d1a6 100644 --- a/assets/cubyz/blocks/cactus_flower.zig.zon +++ b/assets/cubyz/blocks/cactus_flower.zig.zon @@ -4,20 +4,6 @@ .drops = .{ .{.items = .{.auto}}, }, - .onTick = .{.type = .sapling, .structures = .{ - .{ - .id = "cubyz:sbb", - .structure = "cubyz:cactus/saguaro", - .placeMode = .degradable, - .chance = 0.01, - }, - .{ - .id = "cubyz:sbb", - .structure = "cubyz:cactus/young", - .placeMode = .degradable, - .chance = 0.006, - }, - }}, .degradable = true, .collide = false, .alwaysViewThrough = true, diff --git a/assets/cubyz/blocks/sapling/cactus.zig.zon b/assets/cubyz/blocks/sapling/cactus.zig.zon new file mode 100644 index 0000000000..7336afd0bc --- /dev/null +++ b/assets/cubyz/blocks/sapling/cactus.zig.zon @@ -0,0 +1,33 @@ +.{ + .tags = .{.cuttable}, + .blockHealth = 0.2, + .drops = .{ + .{.items = .{.auto}}, + }, + .onTick = .{.type = .sapling, .sbb = .{ + .structure = "cubyz:cactus/saguaro", + .placeMode = .degradable, + .chance = 0.01, + }}, + .degradable = true, + .collide = false, + .alwaysViewThrough = true, + .absorbedLight = 0x121012, + .model = "cubyz:cactus_flower", + .rotation = "cubyz:direction", + .texture = "cubyz:cactus_flower", + .texture_top = "cubyz:cactus_flower_top", + .texture_bottom = "cubyz:cactus_flower_top", + .item = .{ + .texture = "cactus_flower.png", + }, + .lodReplacement = "cubyz:air", + .onTouch = .{ + .type = .hurt, + .dps = 0.2, + .damageType = .spiky, + }, + .onUpdate = .{ + .type = .checkSupportBlocks, + }, +} diff --git a/assets/cubyz/blocks/sapling/oak.zig.zon b/assets/cubyz/blocks/sapling/oak.zig.zon index f831768e7a..6a2bd9debc 100644 --- a/assets/cubyz/blocks/sapling/oak.zig.zon +++ b/assets/cubyz/blocks/sapling/oak.zig.zon @@ -4,14 +4,14 @@ .drops = .{ .{.items = .{.auto}}, }, - .onTick = .{.type = .sapling, .structures = .{ - .{ - .id = "cubyz:sbb", + .onTick = .{ + .type = .sapling, + .sbb = .{ .structure = "cubyz:tree/oak/white", .placeMode = .degradable, .chance = 0.03, }, - }}, + }, .degradable = true, .collide = false, .alwaysViewThrough = true, diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index 83abce450b..02b7872a84 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -1,63 +1,40 @@ const std = @import("std"); const main = @import("main"); +const Vec3i = main.vec.Vec3i; +const sbbGen = main.server.terrain.biomes.SimpleStructures.SbbGen; const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; structures: main.ZonElement, -vegetationModels: ?[]SimpleStructureModel, +sbb: ?*sbbGen.SbbGen, +generationMode: SimpleStructureModel.GenerationMode, +chance: f32, pub fn init(zon: main.ZonElement) ?*@This() { const result = main.worldArena.create(@This()); - result.structures = zon.getChild("structures").clone(main.worldArena); - result.vegetationModels = null; + result.structures = zon.getChild("sbb").clone(main.worldArena); + result.sbb = null; return result; } - -fn initAfterBiomesHaveBeenInited(self: *@This()) void { - var vegetation = main.ListUnmanaged(SimpleStructureModel){}; - var totalChance: f32 = 0; - defer vegetation.deinit(main.stackAllocator); - for (self.structures.toSlice()) |elem| { - if (SimpleStructureModel.initModel(elem)) |model| { - vegetation.append(main.stackAllocator, model); - totalChance += model.chance; - } - } - if (totalChance > 1) { - for (vegetation.items) |*model| { - model.chance /= totalChance; - } - } - self.vegetationModels = main.worldArena.dupe(SimpleStructureModel, vegetation.items); +fn initOfSBB(self: *@This()) void { + const vtableModel = sbbGen.loadModel(self.structures) orelse { + std.log.err("Error occurred while loading structure for saplings", .{}); + return; + }; + self.sbb = vtableModel; + self.generationMode = std.meta.stringToEnum(SimpleStructureModel.GenerationMode, self.structures.get([]const u8, "generationMode", "")) orelse sbbGen.generationMode; + self.chance = self.structures.get(f32, "chance", 0.1); } pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result { - if (self.vegetationModels == null) - self.initAfterBiomesHaveBeenInited(); - const vegetationModels = self.vegetationModels.?; - - const wx = params.chunk.super.pos.wx + params.blockPos.x; - const wy = params.chunk.super.pos.wy + params.blockPos.y; - const wz = params.chunk.super.pos.wz + params.blockPos.z; - const ch = params.chunk; - - // the originals have already deinited long time ago at this point :( - const caveMap = main.server.terrain.CaveMap.CaveMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); - defer caveMap.deinit(main.stackAllocator); - const biomeMap = main.server.terrain.CaveBiomeMap.CaveBiomeMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); - defer biomeMap.deinit(); + if (self.sbb == null) + self.initOfSBB(); // copied from SimpleStructureGen.generate. - var seed = main.random.initSeed3D(main.seed, .{wx, wy, wz}); - var randomValue = main.random.nextFloat(&seed); - for (vegetationModels) |*model| { // TODO: Could probably use an alias table here. - if (randomValue < model.chance) { - model.generate(params.blockPos.x, params.blockPos.y, params.blockPos.z, params.chunk, caveMap, biomeMap, &main.seed, false, false); - - break; - } else { - randomValue -= model.chance; - } + if (self.sbb) |sbb| { + const randomValue = main.random.nextFloat(&main.seed); + if (randomValue < self.chance) + sbb.placeSbb(sbb.structureRef, Vec3i{params.blockPos.x, params.blockPos.y, params.blockPos.z}, null, sbb.rotation.getInitialRotation(&main.seed), params.chunk, &main.seed, false); } return .handled; diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index c3b6fe5132..e29fb3cee9 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -9,6 +9,7 @@ const NeverFailingAllocator = main.heap.NeverFailingAllocator; const vec = @import("main.vec"); const Vec3f = main.vec.Vec3f; const Vec3d = main.vec.Vec3d; +pub const SimpleStructures = @import("simple_structures/_list.zig"); pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel pub const GenerationMode = enum { diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index faf88d9f63..e00271f510 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -16,7 +16,7 @@ const NeverFailingAllocator = main.heap.NeverFailingAllocator; pub const id = "cubyz:sbb"; pub const generationMode = .floor; -const SbbGen = @This(); +pub const SbbGen = @This(); structureRef: *const sbb.StructureBuildingBlock, placeMode: Blueprint.PasteMode, @@ -53,10 +53,10 @@ pub fn loadModel(parameters: ZonElement) ?*SbbGen { } pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration: bool) void { - placeSbb(self, self.structureRef, Vec3i{x, y, z}, Neighbor.dirUp, self.rotation.getInitialRotation(seed), chunk, seed, inGeneration); + placeSbb(self, self.structureRef, Vec3i{x, y, z}, null, self.rotation.getInitialRotation(seed), chunk, seed, inGeneration); } -fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { +pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; From cffc575f9cdd11d72ec7a799b5eade9eb733577f Mon Sep 17 00:00:00 2001 From: till++ Date: Wed, 25 Feb 2026 08:01:35 +0100 Subject: [PATCH 10/22] removed unused parameter --- src/server/terrain/StructureMap.zig | 4 ++-- src/server/terrain/biomes.zig | 6 +++--- src/server/terrain/simple_structures/Boulder.zig | 2 +- src/server/terrain/simple_structures/FallenTree.zig | 2 +- src/server/terrain/simple_structures/FlowerPatch.zig | 2 +- src/server/terrain/simple_structures/GroundPatch.zig | 2 +- src/server/terrain/simple_structures/SbbGen.zig | 10 +++++----- .../terrain/simple_structures/SimpleTreeModel.zig | 2 +- .../terrain/simple_structures/SimpleVegetation.zig | 2 +- src/server/terrain/simple_structures/Stalagmite.zig | 2 +- .../structuremapgen/SbbEnumerationGenerator.zig | 2 +- .../terrain/structuremapgen/SimpleStructureGen.zig | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/server/terrain/StructureMap.zig b/src/server/terrain/StructureMap.zig index 8764846e30..1a1592a55a 100644 --- a/src/server/terrain/StructureMap.zig +++ b/src/server/terrain/StructureMap.zig @@ -15,11 +15,11 @@ const GeneratorState = terrain.GeneratorState; const TerrainGenerationProfile = terrain.TerrainGenerationProfile; const StructureInternal = struct { - generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, inGeneration: bool) void, + generateFn: *const fn (self: *const anyopaque, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void, data: *const anyopaque, pub fn generate(self: StructureInternal, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { - self.generateFn(self.data, chunk, caveMap, biomeMap, true); + self.generateFn(self.data, chunk, caveMap, biomeMap); } }; diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index e29fb3cee9..3beae522ed 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -22,7 +22,7 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; const VTable = struct { loadModel: *const fn (parameters: ZonElement) ?*anyopaque, - generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration: bool) void, + generate: *const fn (self: *anyopaque, generationMode: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void, hashFunction: *const fn (self: *anyopaque) u64, generationMode: GenerationMode, }; @@ -52,8 +52,8 @@ pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel }; } - pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool, inGeneration: bool) void { - self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling, inGeneration); + pub fn generate(self: SimpleStructureModel, x: i32, y: i32, z: i32, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, seed: *u64, isCeiling: bool) void { + self.vtable.generate(self.data, self.generationMode, x, y, z, chunk, caveMap, biomeMap, seed, isCeiling); } var modelRegistry: std.StringHashMapUnmanaged(VTable) = .{}; diff --git a/src/server/terrain/simple_structures/Boulder.zig b/src/server/terrain/simple_structures/Boulder.zig index 20c03f50f6..6a489ba9a9 100644 --- a/src/server/terrain/simple_structures/Boulder.zig +++ b/src/server/terrain/simple_structures/Boulder.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*Boulder { return self; } -pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { _ = caveMap; const radius = self.size + self.sizeVariation*(random.nextFloat(seed)*2 - 1); // My basic idea is to use a point cloud and a potential function to achieve somewhat smooth boulders without being a sphere. diff --git a/src/server/terrain/simple_structures/FallenTree.zig b/src/server/terrain/simple_structures/FallenTree.zig index e41eca2694..401f1d8961 100644 --- a/src/server/terrain/simple_structures/FallenTree.zig +++ b/src/server/terrain/simple_structures/FallenTree.zig @@ -101,7 +101,7 @@ pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, ch } } -pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *FallenTree, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight); generateStump(self, x, y, z, chunk); diff --git a/src/server/terrain/simple_structures/FlowerPatch.zig b/src/server/terrain/simple_structures/FlowerPatch.zig index f3eb1c2c60..a5189708dc 100644 --- a/src/server/terrain/simple_structures/FlowerPatch.zig +++ b/src/server/terrain/simple_structures/FlowerPatch.zig @@ -35,7 +35,7 @@ pub fn loadModel(parameters: ZonElement) ?*FlowerPatch { return self; } -pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/GroundPatch.zig b/src/server/terrain/simple_structures/GroundPatch.zig index afe34febca..1236bb3917 100644 --- a/src/server/terrain/simple_structures/GroundPatch.zig +++ b/src/server/terrain/simple_structures/GroundPatch.zig @@ -37,7 +37,7 @@ pub fn loadModel(parameters: ZonElement) ?*GroundPatch { return self; } -pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void { const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation; const orientation = 2*std.math.pi*random.nextFloat(seed); const ellipseParam = 1 + random.nextFloat(seed); diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index e00271f510..b0a5afc82b 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -52,11 +52,11 @@ pub fn loadModel(parameters: ZonElement) ?*SbbGen { return self; } -pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, inGeneration: bool) void { - placeSbb(self, self.structureRef, Vec3i{x, y, z}, null, self.rotation.getInitialRotation(seed), chunk, seed, inGeneration); +pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { + placeSbb(self, self.structureRef, Vec3i{x, y, z}, null, self.rotation.getInitialRotation(seed), chunk, seed, true); } -pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, inGeneration: bool) void { +pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, duringWorldGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; @@ -68,7 +68,7 @@ pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, pla const rotatedOrigin = rotated.originBlock.pos(); const pastePosition = placementPosition - rotatedOrigin - (placementDirection orelse origin.direction()).relPos(); - if (inGeneration) { + if (duringWorldGeneration) { rotated.blueprint.pasteInGeneration(pastePosition, chunk, self.placeMode); } else { var pos = Vec3i{0, 0, 0}; @@ -81,7 +81,7 @@ pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, pla for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; const childRotation = rotation.getChildRotation(seed, child.rotation, childBlock.direction()); - placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed, inGeneration); + placeSbb(self, child, pastePosition + childBlock.pos(), childBlock.direction(), childRotation, chunk, seed, duringWorldGeneration); } } diff --git a/src/server/terrain/simple_structures/SimpleTreeModel.zig b/src/server/terrain/simple_structures/SimpleTreeModel.zig index 961e33fd91..99484c8af0 100644 --- a/src/server/terrain/simple_structures/SimpleTreeModel.zig +++ b/src/server/terrain/simple_structures/SimpleTreeModel.zig @@ -90,7 +90,7 @@ pub fn generateBranch(self: *SimpleTreeModel, x: i32, y: i32, z: i32, d: u32, ch } } -pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { const factor = random.nextFloat(seed); var height = self.height0 + @as(i32, @intFromFloat(factor*@as(f32, @floatFromInt(self.deltaHeight)))); const leafRadius = self.leafRadius + factor*self.deltaLeafRadius; diff --git a/src/server/terrain/simple_structures/SimpleVegetation.zig b/src/server/terrain/simple_structures/SimpleVegetation.zig index aee033f8fe..975d324bea 100644 --- a/src/server/terrain/simple_structures/SimpleVegetation.zig +++ b/src/server/terrain/simple_structures/SimpleVegetation.zig @@ -33,7 +33,7 @@ pub fn loadModel(parameters: ZonElement) ?*SimpleVegetation { return self; } -pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool, _: bool) void { +pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, _: CaveBiomeMapView, seed: *u64, isCeiling: bool) void { if (chunk.super.pos.voxelSize > 2 and (x & chunk.super.pos.voxelSize - 1 != 0 or y & chunk.super.pos.voxelSize - 1 != 0)) return; const height = self.height0 + random.nextIntBounded(u31, seed, self.deltaHeight + 1); if (z + height >= caveMap.findTerrainChangeAbove(x, y, z)) return; // Space is too small. diff --git a/src/server/terrain/simple_structures/Stalagmite.zig b/src/server/terrain/simple_structures/Stalagmite.zig index ede82d6546..4a8ad5fc92 100644 --- a/src/server/terrain/simple_structures/Stalagmite.zig +++ b/src/server/terrain/simple_structures/Stalagmite.zig @@ -39,7 +39,7 @@ pub fn loadModel(parameters: ZonElement) ?*Stalagmite { return self; } -pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool, _: bool) void { +pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, _: CaveMapView, _: CaveBiomeMapView, seed: *u64, _: bool) void { const relX: f32 = @as(f32, @floatFromInt(x)) + main.random.nextFloat(seed)*0.6 - 0.3; const relY: f32 = @as(f32, @floatFromInt(y)) + main.random.nextFloat(seed)*0.6 - 0.3; const relZ: f32 = @as(f32, @floatFromInt(z)) + main.random.nextFloat(seed)*0.6 - 0.3; diff --git a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig index c461115802..955998f8c1 100644 --- a/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig +++ b/src/server/terrain/structuremapgen/SbbEnumerationGenerator.zig @@ -193,7 +193,7 @@ const SignGenerator = struct { wz: i32, id: []const u8, - pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView, _: bool) void { + pub fn generate(self: *const SignGenerator, chunk: *ServerChunk, _: terrain.CaveMap.CaveMapView, _: terrain.CaveBiomeMap.CaveBiomeMapView) void { if (chunk.super.pos.voxelSize != 1) return; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; diff --git a/src/server/terrain/structuremapgen/SimpleStructureGen.zig b/src/server/terrain/structuremapgen/SimpleStructureGen.zig index c94266ef49..3ecff6a414 100644 --- a/src/server/terrain/structuremapgen/SimpleStructureGen.zig +++ b/src/server/terrain/structuremapgen/SimpleStructureGen.zig @@ -196,11 +196,11 @@ pub const SimpleStructure = struct { wz: i32, isCeiling: bool, - pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView, inGeneration: bool) void { + pub fn generate(self: *const SimpleStructure, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { var seed = self.seed; const relX = self.wx - chunk.super.pos.wx; const relY = self.wy - chunk.super.pos.wy; const relZ = self.wz - chunk.super.pos.wz; - self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling, inGeneration); + self.model.generate(relX, relY, relZ, chunk, caveMap, biomeMap, &seed, self.isCeiling); } }; From f33d3a82871118c2120efacc27a43343702739e8 Mon Sep 17 00:00:00 2001 From: till++ Date: Wed, 25 Feb 2026 08:27:16 +0100 Subject: [PATCH 11/22] Don't trigger blockUpdates when using saplings, to safe performance --- assets/cubyz/blocks/leaves/_defaults.zig.zon | 2 ++ src/blueprint.zig | 3 ++- src/callbacks/block/server/checkSupportBlocks.zig | 2 +- src/callbacks/block/server/decay.zig | 2 +- src/callbacks/block/server/replaceBlock.zig | 2 +- src/server/terrain/simple_structures/SbbGen.zig | 2 +- src/server/world.zig | 10 +++++++--- src/sync.zig | 2 +- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/assets/cubyz/blocks/leaves/_defaults.zig.zon b/assets/cubyz/blocks/leaves/_defaults.zig.zon index df75ffccfe..4fc677c213 100644 --- a/assets/cubyz/blocks/leaves/_defaults.zig.zon +++ b/assets/cubyz/blocks/leaves/_defaults.zig.zon @@ -4,11 +4,13 @@ .prevention = .{.log, .branch}, .drops = .{ .{.chance = 0.01, .items = .{"cubyz:apple"}}, + .{.chance = 0.001, .items = .{"cubyz:sapling/oak"}}, }, }, .drops = .{ .{.items = .{.auto}}, .{.chance = 0.01, .items = .{"cubyz:apple"}}, + .{.chance = 0.001, .items = .{"cubyz:sapling/oak"}}, }, .rotation = "cubyz:decayable", .tags = .{.cuttable, .leaf}, diff --git a/src/blueprint.zig b/src/blueprint.zig index 5504c05462..6fd52d94da 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -147,6 +147,7 @@ pub const Blueprint = struct { pub const PasteFlags = struct { preserveVoid: bool = false, + noUpdate: bool = false, }; pub fn paste(self: Blueprint, pos: Vec3i, flags: PasteFlags) void { @@ -165,7 +166,7 @@ pub const Blueprint = struct { const block = self.blocks.get(x, y, z); if (block.typ != voidType or flags.preserveVoid) - _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block); + _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, flags.noUpdate); } } } diff --git a/src/callbacks/block/server/checkSupportBlocks.zig b/src/callbacks/block/server/checkSupportBlocks.zig index e9fd36add1..454eadc704 100644 --- a/src/callbacks/block/server/checkSupportBlocks.zig +++ b/src/callbacks/block/server/checkSupportBlocks.zig @@ -42,7 +42,7 @@ 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) { + if (main.server.world.?.cmpxchgBlock(wx, wy, wz, params.block, newBlock, false) == null) { const dropAmount = params.block.mode().itemDropsOnChange(params.block, newBlock); const drops = params.block.blockDrops(); for (0..dropAmount) |_| { diff --git a/src/callbacks/block/server/decay.zig b/src/callbacks/block/server/decay.zig index 5def14b968..731cbfe2ba 100644 --- a/src/callbacks/block/server/decay.zig +++ b/src/callbacks/block/server/decay.zig @@ -132,7 +132,7 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma return .ignored; // no, there is no log in proximity - if (world.cmpxchgBlock(wx, wy, wz, leaf, self.decayReplacement) == null) { + if (world.cmpxchgBlock(wx, wy, wz, leaf, self.decayReplacement, false) == null) { const drops = if (self.blockDrops) |blockDrops| blockDrops else params.block.blockDrops(); for (drops) |drop| { if (drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) { diff --git a/src/callbacks/block/server/replaceBlock.zig b/src/callbacks/block/server/replaceBlock.zig index 9c5e1d9d1c..1dc4db76ea 100644 --- a/src/callbacks/block/server/replaceBlock.zig +++ b/src/callbacks/block/server/replaceBlock.zig @@ -20,6 +20,6 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma const wy = params.chunk.super.pos.wy + params.blockPos.y; const wz = params.chunk.super.pos.wz + params.blockPos.z; - _ = main.server.world.?.cmpxchgBlock(wx, wy, wz, params.block, self.block); + _ = main.server.world.?.cmpxchgBlock(wx, wy, wz, params.block, self.block, false); return .handled; } diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index b0a5afc82b..4677af5ddf 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -76,7 +76,7 @@ pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, pla pos[1] = chunk.super.pos.wy + pastePosition[1]; pos[2] = chunk.super.pos.wz + pastePosition[2]; - rotated.blueprint.paste(pos, .{}); + rotated.blueprint.paste(pos, .{.noUpdate = true}); } for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; diff --git a/src/server/world.zig b/src/server/world.zig index 4f9d2d88eb..570f831641 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -1190,7 +1190,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld } /// Returns the actual block on failure - pub fn cmpxchgBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, oldBlock: ?Block, _newBlock: Block) ?Block { + pub fn cmpxchgBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, oldBlock: ?Block, _newBlock: Block, noUpdate: bool) ?Block { main.sync.threadContext.assertCorrectContext(.server); const baseChunk = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(.{.wx = wx & ~@as(i32, chunk.chunkMask), .wy = wy & ~@as(i32, chunk.chunkMask), .wz = wz & ~@as(i32, chunk.chunkMask), .voxelSize = 1}); defer baseChunk.decreaseRefCount(); @@ -1248,6 +1248,9 @@ pub const ServerWorld = struct { // MARK: ServerWorld for (userList) |user| { main.network.protocols.blockUpdate.send(user.conn, &.{.{.x = wx, .y = wy, .z = wz, .newBlock = newBlock, .blockEntityData = &.{}}}); } + if (noUpdate) + return null; + // onBreak event if (oldBlock) |block| { if (block.typ != newBlock.typ) { @@ -1258,6 +1261,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld }); } } + self.triggerNeighborBlockUpdates(wx, wy, wz); return null; @@ -1281,8 +1285,8 @@ pub const ServerWorld = struct { // MARK: ServerWorld } } - pub fn updateBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, newBlock: Block) void { - _ = self.cmpxchgBlock(wx, wy, wz, null, newBlock); + pub fn updateBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, newBlock: Block, noUpdate: bool) void { + _ = self.cmpxchgBlock(wx, wy, wz, null, newBlock, noUpdate); } pub fn queueChunkUpdateAndDecreaseRefCount(self: *ServerWorld, ch: *ServerChunk) void { diff --git a/src/sync.zig b/src/sync.zig index c745a53b29..33d51a0f00 100644 --- a/src/sync.zig +++ b/src/sync.zig @@ -1422,7 +1422,7 @@ pub const Command = struct { // MARK: Command } if (ctx.side == .server) { - if (main.server.world.?.cmpxchgBlock(self.pos[0], self.pos[1], self.pos[2], self.oldBlock, self.newBlock) != null) { + if (main.server.world.?.cmpxchgBlock(self.pos[0], self.pos[1], self.pos[2], self.oldBlock, self.newBlock, false) != null) { // Inform the client of the actual block: var writer = BinaryWriter.init(main.stackAllocator); defer writer.deinit(); From dbb214751dc3e158306953fc1ae0b81e6934f015 Mon Sep 17 00:00:00 2001 From: till++ Date: Thu, 26 Feb 2026 06:05:06 +0100 Subject: [PATCH 12/22] removed recursive import --- src/callbacks/block/server/sapling.zig | 2 +- src/server/terrain/biomes.zig | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index 02b7872a84..8c5f806cb4 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -2,7 +2,7 @@ const std = @import("std"); const main = @import("main"); const Vec3i = main.vec.Vec3i; -const sbbGen = main.server.terrain.biomes.SimpleStructures.SbbGen; +const sbbGen = @import("../../../server/terrain/simple_structures/SbbGen.zig"); const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; structures: main.ZonElement, diff --git a/src/server/terrain/biomes.zig b/src/server/terrain/biomes.zig index 3beae522ed..c0fbe78b85 100644 --- a/src/server/terrain/biomes.zig +++ b/src/server/terrain/biomes.zig @@ -9,7 +9,6 @@ const NeverFailingAllocator = main.heap.NeverFailingAllocator; const vec = @import("main.vec"); const Vec3f = main.vec.Vec3f; const Vec3d = main.vec.Vec3d; -pub const SimpleStructures = @import("simple_structures/_list.zig"); pub const SimpleStructureModel = struct { // MARK: SimpleStructureModel pub const GenerationMode = enum { From bcf99ebe7d978193fa3017edfdbcebfb7764ad3f Mon Sep 17 00:00:00 2001 From: till++ Date: Mon, 2 Mar 2026 19:32:49 +0100 Subject: [PATCH 13/22] use comptime --- src/blueprint.zig | 2 +- src/server/terrain/simple_structures/SbbGen.zig | 2 +- src/server/world.zig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blueprint.zig b/src/blueprint.zig index 6fd52d94da..a4323cb486 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -166,7 +166,7 @@ pub const Blueprint = struct { const block = self.blocks.get(x, y, z); if (block.typ != voidType or flags.preserveVoid) - _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, flags.noUpdate); + _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, false); } } } diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 4677af5ddf..87f023a8fa 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -56,7 +56,7 @@ pub fn generate(self: *SbbGen, _: GenerationMode, x: i32, y: i32, z: i32, chunk: placeSbb(self, self.structureRef, Vec3i{x, y, z}, null, self.rotation.getInitialRotation(seed), chunk, seed, true); } -pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, duringWorldGeneration: bool) void { +pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, placementPosition: Vec3i, placementDirection: ?Neighbor, rotation: sbb.Rotation, chunk: *ServerChunk, seed: *u64, comptime duringWorldGeneration: bool) void { const blueprints = &(structure.getBlueprints(seed).* orelse return); const origin = blueprints[0].originBlock; diff --git a/src/server/world.zig b/src/server/world.zig index 570f831641..360c0d9fea 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -1190,7 +1190,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld } /// Returns the actual block on failure - pub fn cmpxchgBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, oldBlock: ?Block, _newBlock: Block, noUpdate: bool) ?Block { + pub fn cmpxchgBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, oldBlock: ?Block, _newBlock: Block, comptime noUpdate: bool) ?Block { main.sync.threadContext.assertCorrectContext(.server); const baseChunk = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(.{.wx = wx & ~@as(i32, chunk.chunkMask), .wy = wy & ~@as(i32, chunk.chunkMask), .wz = wz & ~@as(i32, chunk.chunkMask), .voxelSize = 1}); defer baseChunk.decreaseRefCount(); @@ -1285,7 +1285,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld } } - pub fn updateBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, newBlock: Block, noUpdate: bool) void { + pub fn updateBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, newBlock: Block, comptime noUpdate: bool) void { _ = self.cmpxchgBlock(wx, wy, wz, null, newBlock, noUpdate); } From 1b61a67673a4c536c13439cb2482807b290a2382 Mon Sep 17 00:00:00 2001 From: till++ Date: Mon, 4 May 2026 23:17:04 +0200 Subject: [PATCH 14/22] fixed merge --- src/callbacks/block/server/vine_decay.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks/block/server/vine_decay.zig b/src/callbacks/block/server/vine_decay.zig index 5023e60d57..6273251b80 100644 --- a/src/callbacks/block/server/vine_decay.zig +++ b/src/callbacks/block/server/vine_decay.zig @@ -35,6 +35,6 @@ pub fn run(_: *@This(), params: main.callbacks.ServerBlockCallback.Params) main. } fn decay(x: i32, y: i32, z: i32, current: Block) main.callbacks.Result { - if (server.world.?.cmpxchgBlock(x, y, z, current, blocks.Block.air) == null) return .handled; + if (server.world.?.cmpxchgBlock(x, y, z, current, blocks.Block.air, false) == null) return .handled; return .ignored; } From 70bda9ca6c207afa7881e6bf00139badbc86c72b Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 16 Jun 2026 03:32:17 +0200 Subject: [PATCH 15/22] fix merge --- src/callbacks/block/server/sapling.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index 8c5f806cb4..b13eaf0771 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -10,7 +10,7 @@ sbb: ?*sbbGen.SbbGen, generationMode: SimpleStructureModel.GenerationMode, chance: f32, -pub fn init(zon: main.ZonElement) ?*@This() { +pub fn init(zon: main.ZonElement, _: main.callbacks.Creator) ?*@This() { const result = main.worldArena.create(@This()); result.structures = zon.getChild("sbb").clone(main.worldArena); result.sbb = null; From bac9af68f2040f2c56d26f149622fe2531c0f74a Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 16 Jun 2026 03:36:02 +0200 Subject: [PATCH 16/22] changed import style --- src/callbacks/block/server/sapling.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index b13eaf0771..2e5526f569 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -2,7 +2,7 @@ const std = @import("std"); const main = @import("main"); const Vec3i = main.vec.Vec3i; -const sbbGen = @import("../../../server/terrain/simple_structures/SbbGen.zig"); +const sbbGen = main.server.terrain.structures.simple_structures.SbbGen; const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; structures: main.ZonElement, From 75a997279485cc059e134e5e904cfc66c420b479 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 16 Jun 2026 03:42:55 +0200 Subject: [PATCH 17/22] removed noUpdate parameter, use "false" instead --- src/blueprint.zig | 5 +---- src/server/terrain/simple_structures/SbbGen.zig | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/blueprint.zig b/src/blueprint.zig index b4ec89a654..6c884a0dc9 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -164,10 +164,7 @@ pub const Blueprint = struct { } } - pub const PasteFlags = struct { - preserveVoid: bool = false, - noUpdate: bool = false, - }; + pub const PasteFlags = struct { preserveVoid: bool = false }; pub fn paste(self: Blueprint, pos: Vec3i, flags: PasteFlags) void { const startX = pos[0]; diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 6d4300bd52..7f7b2857d7 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -76,7 +76,7 @@ pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, pla pos[1] = chunk.super.pos.wy + pastePosition[1]; pos[2] = chunk.super.pos.wz + pastePosition[2]; - rotated.blueprint.paste(pos, .{.noUpdate = true}); + rotated.blueprint.paste(pos, .{}); } for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; From 190cd6a8f04eb8944119a0a4e9754fb74cfc54c2 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 16 Jun 2026 04:00:07 +0200 Subject: [PATCH 18/22] remove the zon --- src/assets.zig | 2 ++ src/blocks.zig | 7 ++++++- src/callbacks/block/server/sapling.zig | 29 +++++++++----------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/assets.zig b/src/assets.zig index c2147751fa..2ebcac878a 100644 --- a/src/assets.zig +++ b/src/assets.zig @@ -767,6 +767,8 @@ pub fn loadWorldAssets(assetFolder: []const u8, blockPalette: *Palette, itemPale } } + blocks.finishBlockCallbacks(worldAssets.blocks); + worldAssets.log(.world); } diff --git a/src/blocks.zig b/src/blocks.zig index 304ad6edb3..be6d62e970 100644 --- a/src/blocks.zig +++ b/src/blocks.zig @@ -337,11 +337,16 @@ pub fn finishBlocks(zonElements: Assets.ZonHashMap) void { registerBlockDrop(i, zonElements.get(_id[i]) orelse continue); registerLodReplacement(i, zonElements.get(_id[i]) orelse continue); registerOpaqueVariant(i, zonElements.get(_id[i]) orelse continue); - registerCallbacks(i, zonElements.get(_id[i]) orelse continue); } blueprint.registerVoidBlock(parseBlock("cubyz:void")); meshes.finishTextureLoading(); } +pub fn finishBlockCallbacks(zonElements: Assets.ZonHashMap) void { + var i: u16 = 0; + while (i < size) : (i += 1) { + registerCallbacks(i, zonElements.get(_id[i]) orelse continue); + } +} pub fn reset() void { size = 0; diff --git a/src/callbacks/block/server/sapling.zig b/src/callbacks/block/server/sapling.zig index 2e5526f569..b573157cec 100644 --- a/src/callbacks/block/server/sapling.zig +++ b/src/callbacks/block/server/sapling.zig @@ -5,36 +5,27 @@ const Vec3i = main.vec.Vec3i; const sbbGen = main.server.terrain.structures.simple_structures.SbbGen; const SimpleStructureModel = main.server.terrain.biomes.SimpleStructureModel; -structures: main.ZonElement, -sbb: ?*sbbGen.SbbGen, -generationMode: SimpleStructureModel.GenerationMode, +sbb: *sbbGen.SbbGen, chance: f32, pub fn init(zon: main.ZonElement, _: main.callbacks.Creator) ?*@This() { const result = main.worldArena.create(@This()); - result.structures = zon.getChild("sbb").clone(main.worldArena); - result.sbb = null; - return result; -} -fn initOfSBB(self: *@This()) void { - const vtableModel = sbbGen.loadModel(self.structures) orelse { + + const vtableModel = sbbGen.loadModel(zon.getChild("sbb")) orelse { std.log.err("Error occurred while loading structure for saplings", .{}); - return; + return null; }; - self.sbb = vtableModel; - self.generationMode = std.meta.stringToEnum(SimpleStructureModel.GenerationMode, self.structures.get([]const u8, "generationMode", "")) orelse sbbGen.generationMode; - self.chance = self.structures.get(f32, "chance", 0.1); + result.sbb = vtableModel; + result.chance = zon.get(f32, "chance", 0.1); + return result; } pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result { - if (self.sbb == null) - self.initOfSBB(); // copied from SimpleStructureGen.generate. - if (self.sbb) |sbb| { - const randomValue = main.random.nextFloat(&main.seed); - if (randomValue < self.chance) - sbb.placeSbb(sbb.structureRef, Vec3i{params.blockPos.x, params.blockPos.y, params.blockPos.z}, null, sbb.rotation.getInitialRotation(&main.seed), params.chunk, &main.seed, false); + const randomValue = main.random.nextFloat(&main.seed); + if (randomValue < self.chance) { + self.sbb.placeSbb(self.sbb.structureRef, Vec3i{params.blockPos.x, params.blockPos.y, params.blockPos.z}, null, self.sbb.rotation.getInitialRotation(&main.seed), params.chunk, &main.seed, false); } return .handled; From b82be539fc20ae874ddf8717970a130a559910c4 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 16 Jun 2026 04:18:02 +0200 Subject: [PATCH 19/22] make noUpdate doable --- src/blueprint.zig | 2 +- src/server/world.zig | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/blueprint.zig b/src/blueprint.zig index 6c884a0dc9..86cdee788c 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -182,7 +182,7 @@ pub const Blueprint = struct { const block = self.blocks.get(x, y, z); if (block.typ != voidType or flags.preserveVoid) { - _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, false); + _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, true); } } } diff --git a/src/server/world.zig b/src/server/world.zig index 1f41b5bcb9..6935587bfe 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -1281,8 +1281,6 @@ pub const ServerWorld = struct { // MARK: ServerWorld for (userList) |user| { main.network.protocols.blockUpdate.send(user.conn, &.{.{.pos = .{wx, wy, wz}, .newBlock = newBlock, .blockEntityData = &.{}}}); } - if (noUpdate) - return null; // onBreak event if (oldBlock) |block| { @@ -1294,8 +1292,9 @@ pub const ServerWorld = struct { // MARK: ServerWorld }); } } - - self.triggerNeighborBlockUpdates(wx, wy, wz); + if (!noUpdate){ + self.triggerNeighborBlockUpdates(wx, wy, wz); + } return null; } From a3dd604942bb2e60ff48b93f5367d30335086aa8 Mon Sep 17 00:00:00 2001 From: till++ Date: Thu, 18 Jun 2026 22:47:28 +0200 Subject: [PATCH 20/22] fmt --- src/server/world.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/world.zig b/src/server/world.zig index 678983ec76..cf9a514ced 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -1297,7 +1297,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld }); } } - if (!noUpdate){ + if (!noUpdate) { self.triggerNeighborBlockUpdates(wx, wy, wz); } From 0f426e45e234d8fad3b9520d771708ebc353be55 Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 23 Jun 2026 17:04:31 +0200 Subject: [PATCH 21/22] dont replace undegradable --- src/blueprint.zig | 17 ++++++++++++++--- src/server/terrain/simple_structures/SbbGen.zig | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/blueprint.zig b/src/blueprint.zig index 86cdee788c..f33366851a 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -164,7 +164,10 @@ pub const Blueprint = struct { } } - pub const PasteFlags = struct { preserveVoid: bool = false }; + pub const PasteFlags = struct { + preserveVoid: bool = false, + replaceUndegradable: bool = true, + }; pub fn paste(self: Blueprint, pos: Vec3i, flags: PasteFlags) void { const startX = pos[0]; @@ -181,9 +184,17 @@ pub const Blueprint = struct { const worldZ = startZ +% @as(i32, @intCast(z)); const block = self.blocks.get(x, y, z); - if (block.typ != voidType or flags.preserveVoid) { - _ = main.server.world.?.updateBlock(worldX, worldY, worldZ, block, true); + if (block.typ == voidType and !flags.preserveVoid) continue; + + while(true){ + const oldBlock = main.server.world.?.getBlock(@intCast(worldX),@intCast(worldY),@intCast(worldZ)); + if(oldBlock)|_oldBlock|{ + if (!_oldBlock.degradable() and !flags.replaceUndegradable) break; + } + if(main.server.world.?.cmpxchgBlock(worldX, worldY, worldZ, oldBlock, block, true) == null) + break; } + } } } diff --git a/src/server/terrain/simple_structures/SbbGen.zig b/src/server/terrain/simple_structures/SbbGen.zig index 7f7b2857d7..dcc7179105 100644 --- a/src/server/terrain/simple_structures/SbbGen.zig +++ b/src/server/terrain/simple_structures/SbbGen.zig @@ -76,7 +76,7 @@ pub fn placeSbb(self: *SbbGen, structure: *const sbb.StructureBuildingBlock, pla pos[1] = chunk.super.pos.wy + pastePosition[1]; pos[2] = chunk.super.pos.wz + pastePosition[2]; - rotated.blueprint.paste(pos, .{}); + rotated.blueprint.paste(pos, .{.replaceUndegradable = false}); } for (rotated.childBlocks) |childBlock| { const child = structure.getChildStructure(childBlock) orelse continue; From e944aa3057fbaaabe04eec433137d386441ab8ca Mon Sep 17 00:00:00 2001 From: till++ Date: Tue, 23 Jun 2026 17:09:28 +0200 Subject: [PATCH 22/22] fmt --- src/blueprint.zig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/blueprint.zig b/src/blueprint.zig index f33366851a..34197d80ad 100644 --- a/src/blueprint.zig +++ b/src/blueprint.zig @@ -164,7 +164,7 @@ pub const Blueprint = struct { } } - pub const PasteFlags = struct { + pub const PasteFlags = struct { preserveVoid: bool = false, replaceUndegradable: bool = true, }; @@ -186,15 +186,14 @@ pub const Blueprint = struct { const block = self.blocks.get(x, y, z); if (block.typ == voidType and !flags.preserveVoid) continue; - while(true){ - const oldBlock = main.server.world.?.getBlock(@intCast(worldX),@intCast(worldY),@intCast(worldZ)); - if(oldBlock)|_oldBlock|{ + while (true) { + const oldBlock = main.server.world.?.getBlock(@intCast(worldX), @intCast(worldY), @intCast(worldZ)); + if (oldBlock) |_oldBlock| { if (!_oldBlock.degradable() and !flags.replaceUndegradable) break; } - if(main.server.world.?.cmpxchgBlock(worldX, worldY, worldZ, oldBlock, block, true) == null) + if (main.server.world.?.cmpxchgBlock(worldX, worldY, worldZ, oldBlock, block, true) == null) break; } - } } }