Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/blueprint.zig
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,18 @@ pub const Blueprint = struct {
return .{.success = self};
}

pub const PasteMode = enum {all, degradable};

pub fn pasteInGeneration(self: Blueprint, pos: Vec3i, chunk: *ServerChunk, mode: PasteMode) void {
switch(mode) {
inline else => |comptimeMode| _pasteInGeneration(self, pos, chunk, comptimeMode),
pub const PasteMode = enum {
all,
degradable,
fn asUpdateMode(self: PasteMode) ServerChunk.UpdateMode {
return switch(self) {
.all => .replace,
.degradable => .replaceIfDegradable,
};
}
}
};

fn _pasteInGeneration(self: Blueprint, pos: Vec3i, chunk: *ServerChunk, comptime mode: PasteMode) void {
pub fn pasteInGeneration(self: Blueprint, pos: Vec3i, chunk: *ServerChunk, mode: PasteMode) void {
const indexEndX: i32 = @min(@as(i32, chunk.super.width) - pos[0], @as(i32, @intCast(self.blocks.width)));
const indexEndY: i32 = @min(@as(i32, chunk.super.width) - pos[1], @as(i32, @intCast(self.blocks.depth)));
const indexEndZ: i32 = @min(@as(i32, chunk.super.width) - pos[2], @as(i32, @intCast(self.blocks.height)));
Expand All @@ -136,10 +139,7 @@ pub const Blueprint = struct {
const chunkX = indexX + pos[0];
const chunkY = indexY + pos[1];
const chunkZ = indexZ + pos[2];
switch(mode) {
.all => chunk.updateBlockInGeneration(chunkX, chunkY, chunkZ, block),
.degradable => chunk.updateBlockIfDegradable(chunkX, chunkY, chunkZ, block),
}
chunk.updateBlock(mode.asUpdateMode(), .noSetChanged, chunkX, chunkY, chunkZ, block);
}
}
}
Expand Down
48 changes: 27 additions & 21 deletions src/chunk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -463,35 +463,41 @@ pub const ServerChunk = struct { // MARK: ServerChunk
return self.super.data.getValue(pos.toIndex());
}

/// Updates a block if it is inside this chunk.
/// Does not do any bound checks. They are expected to be done with the `liesInChunk` function.
pub fn updateBlockAndSetChanged(self: *ServerChunk, x: i32, y: i32, z: i32, newBlock: Block) void {
main.utils.assertLocked(&self.mutex);
const pos = BlockPos.fromLodCoords(x, y, z, self.super.voxelSizeShift);
self.super.data.setValue(pos.toIndex(), newBlock);
self.shouldStoreNeighbors = true;
self.setChanged();
}
pub const UpdateMode = enum {
/// Always update the block.
replace,
/// Updates if current value is air or the current block is degradable.
replaceIfDegradable,
};

pub const SetChanged = enum {
/// Mark the chunk as changed.
setChanged,
/// Should be used in generation to prevent accidently storing the update as changes.
noSetChanged,
};

/// Updates a block if current value is air or the current block is degradable.
/// Updates a block if it is inside this chunk.
/// Does not do any bound checks. They are expected to be done with the `liesInChunk` function.
pub fn updateBlockIfDegradable(self: *ServerChunk, x: i32, y: i32, z: i32, newBlock: Block) void {
pub fn updateBlock(self: *ServerChunk, mode: UpdateMode, shouldSetChanged: SetChanged, x: i32, y: i32, z: i32, newBlock: Block) void {
main.utils.assertLocked(&self.mutex);
const pos = BlockPos.fromLodCoords(x, y, z, self.super.voxelSizeShift);
const oldBlock = self.super.data.getValue(pos.toIndex());
if(oldBlock.typ == 0 or oldBlock.degradable()) {
const shouldUpdate = switch(mode) {
.replace => true,
.replaceIfDegradable => blk: {
const oldBlock = self.super.data.getValue(pos.toIndex());
break :blk oldBlock.typ == 0 or oldBlock.degradable();
},
};
if(shouldUpdate) {
self.super.data.setValue(pos.toIndex(), newBlock);
if(shouldSetChanged == .setChanged) {
self.shouldStoreNeighbors = true;
self.setChanged();
}
}
}

/// Updates a block if it is inside this chunk. Should be used in generation to prevent accidently storing these as changes.
/// Does not do any bound checks. They are expected to be done with the `liesInChunk` function.
pub fn updateBlockInGeneration(self: *ServerChunk, x: i32, y: i32, z: i32, newBlock: Block) void {
main.utils.assertLocked(&self.mutex);
const pos = BlockPos.fromLodCoords(x, y, z, self.super.voxelSizeShift);
self.super.data.setValue(pos.toIndex(), newBlock);
}

/// Updates a block if it is inside this chunk. Should be used in generation to prevent accidently storing these as changes.
/// Does not do any bound checks. They are expected to be done with the `liesInChunk` function.
pub fn updateBlockColumnInGeneration(self: *ServerChunk, x: i32, y: i32, zStartInclusive: i32, zEndInclusive: i32, newBlock: Block) void {
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/biomes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ pub const BlockStructure = struct { // MARK: BlockStructure
continue;
}
if(chunk.liesInChunk(x, y, depth)) {
chunk.updateBlockInGeneration(x, y, depth, blockStack.block);
chunk.updateBlock(.replace, .noSetChanged, x, y, depth, blockStack.block);
}
depth -%= chunk.super.pos.voxelSize;
if(depth -% minDepth <= 0)
Expand Down
5 changes: 1 addition & 4 deletions src/server/terrain/chunkgen/CrystalGenerator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,7 @@ fn considerCrystal(x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, seed:
const dist = distSqr(@as(f32, @floatFromInt(x3)) - x2, @as(f32, @floatFromInt(y3)) - y2, @as(f32, @floatFromInt(z3)) - z2);
if(dist < size*size) {
if(x3 >= 0 and x3 < chunk.super.width and y3 >= 0 and y3 < chunk.super.width and z3 >= 0 and z3 < chunk.super.width) {
const block: main.blocks.Block = chunk.getBlock(x3, y3, z3);
if(block.typ == 0 or block.degradable()) {
chunk.updateBlockInGeneration(x3, y3, z3, .{.typ = typ, .data = 0});
}
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x3, y3, z3, .{.typ = typ, .data = 0});
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/chunkgen/OreGenerator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn considerCoordinates(ore: *const main.blocks.Ore, relX: f32, relY: f32, relZ:
if((1 - distSqr)*ore.density >= random.nextFloat(&veinSeed)) {
const stoneBlock = chunk.getBlock(curX, curY, curZ);
if(chunk.getBlock(curX, curY, curZ).allowOres()) {
chunk.updateBlockInGeneration(curX, curY, curZ, .{.typ = ore.blockType, .data = stoneBlock.typ});
chunk.updateBlock(.replace, .noSetChanged, curX, curY, curZ, .{.typ = ore.blockType, .data = stoneBlock.typ});
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/chunkgen/TerrainGenerator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub fn generate(worldSeed: u64, chunk: *main.chunk.ServerChunk, caveMap: CaveMap
break;
}
}
chunk.updateBlockInGeneration(x, y, z, block);
chunk.updateBlock(.replace, .noSetChanged, x, y, z, block);
}
z += chunk.super.pos.voxelSize;
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/simple_structures/Boulder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub fn generate(self: *Boulder, _: GenerationMode, x: i32, y: i32, z: i32, chunk
}
potential *= radius*radius/4/numberOfPoints;
if(potential >= 1) {
chunk.updateBlockInGeneration(px, py, pz, self.block);
chunk.updateBlock(.replace, .noSetChanged, px, py, pz, self.block);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/server/terrain/simple_structures/FallenTree.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn loadModel(parameters: ZonElement) ?*FallenTree {

pub fn generateStump(self: *FallenTree, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk) void {
if(chunk.liesInChunk(x, y, z))
chunk.updateBlockIfDegradable(x, y, z, .{.typ = self.woodBlock, .data = 0});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, z, .{.typ = self.woodBlock, .data = 0});
}

pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, seed: *u64) void {
Expand Down Expand Up @@ -96,7 +96,7 @@ pub fn generateFallen(self: *FallenTree, x: i32, y: i32, z: i32, length: u32, ch
const v: i32 = @intCast(val);
if(chunk.liesInChunk(x + dx*(v + 2), y + dy*(v + 2), z)) {
const typ = if(v == (length - 1)) self.topWoodBlock else self.woodBlock;
chunk.updateBlockIfDegradable(x + dx*(v + 2), y + dy*(v + 2), z, .{.typ = typ, .data = @intCast(d.? + 2)});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x + dx*(v + 2), y + dy*(v + 2), z, .{.typ = typ, .data = @intCast(d.? + 2)});
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/simple_structures/FlowerPatch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32
startHeight = chunk.startIndex(startHeight + chunk.super.pos.voxelSize);
if(@abs(startHeight -% baseHeight) > 5) continue;
if(chunk.liesInChunk(px, py, startHeight)) {
chunk.updateBlockInGeneration(px, py, startHeight, self.block);
chunk.updateBlock(.replace, .noSetChanged, px, py, startHeight, self.block);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/terrain/simple_structures/GroundPatch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub fn generate(self: *GroundPatch, mode: GenerationMode, x: i32, y: i32, z: i32
while(pz <= startHeight) : (pz += chunk.super.pos.voxelSize) {
if(dist <= self.smoothness or (dist - self.smoothness)/(1 - self.smoothness) < random.nextFloat(seed)) {
if(chunk.liesInChunk(px, py, pz)) {
chunk.updateBlockInGeneration(px, py, pz, self.block);
chunk.updateBlock(.replace, .noSetChanged, px, py, pz, self.block);
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/server/terrain/simple_structures/SimpleTreeModel.zig
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn generateStem(self: *SimpleTreeModel, x: i32, y: i32, z: i32, height: i32,
var pz: i32 = chunk.startIndex(z);
while(pz < z + height) : (pz += chunk.super.pos.voxelSize) {
if(chunk.liesInChunk(x, y, pz)) {
chunk.updateBlockIfDegradable(x, y, pz, if(pz == z + height - 1) self.topWoodBlock else self.woodBlock);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, pz, if(pz == z + height - 1) self.topWoodBlock else self.woodBlock);

if(self.branched) {
const chance = @sqrt(@as(f32, @floatFromInt(pz - z))/@as(f32, @floatFromInt(height*2)));
Expand All @@ -80,13 +80,13 @@ pub fn generateBranch(self: *SimpleTreeModel, x: i32, y: i32, z: i32, d: u32, ch
_ = seed;

if(d == 0 and chunk.liesInChunk(x + 1, y, z)) {
chunk.updateBlockIfDegradable(x + 1, y, z, .{.typ = self.topWoodBlock.typ, .data = 2});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x + 1, y, z, .{.typ = self.topWoodBlock.typ, .data = 2});
} else if(d == 1 and chunk.liesInChunk(x - 1, y, z)) {
chunk.updateBlockIfDegradable(x - 1, y, z, .{.typ = self.topWoodBlock.typ, .data = 3});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x - 1, y, z, .{.typ = self.topWoodBlock.typ, .data = 3});
} else if(d == 2 and chunk.liesInChunk(x, y + 1, z)) {
chunk.updateBlockIfDegradable(x, y + 1, z, .{.typ = self.topWoodBlock.typ, .data = 4});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y + 1, z, .{.typ = self.topWoodBlock.typ, .data = 4});
} else if(d == 3 and chunk.liesInChunk(x, y - 1, z)) {
chunk.updateBlockIfDegradable(x, y - 1, z, .{.typ = self.topWoodBlock.typ, .data = 5});
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y - 1, z, .{.typ = self.topWoodBlock.typ, .data = 5});
}
}

Expand All @@ -104,10 +104,10 @@ pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i3
if(chunk.super.pos.voxelSize >= 16) {
// Ensures that even at lowest resolution some leaves are rendered for smaller trees.
if(chunk.liesInChunk(x, y, z)) {
chunk.updateBlockIfDegradable(x, y, z, self.leavesBlock);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, z, self.leavesBlock);
}
if(chunk.liesInChunk(x, y, z + chunk.super.pos.voxelSize)) {
chunk.updateBlockIfDegradable(x, y, z + chunk.super.pos.voxelSize, self.leavesBlock);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, z + chunk.super.pos.voxelSize, self.leavesBlock);
}
}

Expand All @@ -124,7 +124,7 @@ pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i3
var py = chunk.startIndex(y + 1 - j);
while(py < y + j) : (py += chunk.super.pos.voxelSize) {
if(chunk.liesInChunk(px, py, pz))
chunk.updateBlockIfDegradable(px, py, pz, self.leavesBlock);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, px, py, pz, self.leavesBlock);
}
}
}
Expand All @@ -146,7 +146,7 @@ pub fn generate(self: *SimpleTreeModel, _: GenerationMode, x: i32, y: i32, z: i3
while(py < y + ceilRadius) : (py += chunk.super.pos.voxelSize) {
const distSqr = @as(f32, @floatFromInt((pz - center)*(pz - center)))*invLeafElongationSqr + @as(f32, @floatFromInt((px - x)*(px - x) + (py - y)*(py - y)));
if(chunk.liesInChunk(px, py, pz) and distSqr < radiusSqr and (distSqr < randomRadiusSqr or random.nextInt(u1, seed) != 0)) { // TODO: Use another seed to make this more reliable!
chunk.updateBlockIfDegradable(px, py, pz, self.leavesBlock);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, px, py, pz, self.leavesBlock);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/server/terrain/simple_structures/SimpleVegetation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ pub fn generate(self: *SimpleVegetation, _: GenerationMode, x: i32, y: i32, z: i
if(isCeiling) {
while(pz >= z - height) : (pz -= chunk.super.pos.voxelSize) {
if(chunk.liesInChunk(x, y, pz)) {
chunk.updateBlockIfDegradable(x, y, pz, self.block);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, pz, self.block);
}
}
} else {
while(pz < z + height) : (pz += chunk.super.pos.voxelSize) {
if(chunk.liesInChunk(x, y, pz)) {
chunk.updateBlockIfDegradable(x, y, pz, self.block);
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x, y, pz, self.block);
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/server/terrain/simple_structures/Stalagmite.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@ pub fn generate(self: *Stalagmite, _: GenerationMode, x: i32, y: i32, z: i32, ch
const dist = vec.lengthSquare(Vec3f{@as(f32, @floatFromInt(x3)) - relX, @as(f32, @floatFromInt(y3)) - relY, @as(f32, @floatFromInt(z3)) - z2});
if(dist < size*size) {
if(x3 >= 0 and x3 < chunk.super.width and y3 >= 0 and y3 < chunk.super.width and z3 >= 0 and z3 < chunk.super.width) {
const block: main.blocks.Block = chunk.getBlock(x3, y3, z3);
if(block.typ == 0 or block.degradable()) {
chunk.updateBlockInGeneration(x3, y3, z3, self.block);
}
chunk.updateBlock(.replaceIfDegradable, .noSetChanged, x3, y3, z3, self.block);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/server/world.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld

var neighborBlock = ch.getBlock(neighborPos.x, neighborPos.y, neighborPos.z);
if(neighborBlock.mode().dependsOnNeighbors and neighborBlock.mode().updateData(&neighborBlock, neighbor.reverse(), newBlock)) {
ch.updateBlockAndSetChanged(neighborPos.x, neighborPos.y, neighborPos.z, neighborBlock);
ch.updateBlock(.replace, .setChanged, neighborPos.x, neighborPos.y, neighborPos.z, neighborBlock);
}
if(newBlock.mode().dependsOnNeighbors) {
_ = newBlock.mode().updateData(&newBlock, neighbor, neighborBlock);
Expand All @@ -1166,7 +1166,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld
std.log.err("Got error {s} while trying to remove entity data in position {} for block {s}", .{@errorName(err), Vec3i{wx, wy, wz}, currentBlock.id()});
};
}
baseChunk.updateBlockAndSetChanged(pos.x, pos.y, pos.z, newBlock);
baseChunk.updateBlock(.replace, .setChanged, pos.x, pos.y, pos.z, newBlock);

const userList = server.getUserListAndIncreaseRefCount(main.stackAllocator);
defer server.freeUserListAndDecreaseRefCount(main.stackAllocator, userList);
Expand Down