Cubyz/src/server/terrain/terrain.zig
IntegratedQuantum 09fc516828 Move all the allocators to a separate file. They can now be imported with main.heap (analogous to std.heap)
I also removed the unused BufferFallbackAllocator which was from a time where I was still experimenting with different allocators.
2025-03-09 16:26:41 +01:00

174 lines
6.2 KiB
Zig

const std = @import("std");
const main = @import("root");
const ZonElement = main.ZonElement;
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
pub const biomes = @import("biomes.zig");
pub const noise = @import("noise/noise.zig");
const Biome = biomes.Biome;
pub const ClimateMap = @import("ClimateMap.zig");
pub const SurfaceMap = @import("SurfaceMap.zig");
pub const LightMap = @import("LightMap.zig");
pub const CaveBiomeMap = @import("CaveBiomeMap.zig");
pub const CaveMap = @import("CaveMap.zig");
pub const StructureMap = @import("StructureMap.zig");
/// A generator for setting the actual Blocks in each Chunk.
pub const BlockGenerator = struct {
init: *const fn(parameters: ZonElement) void,
deinit: *const fn() void,
generate: *const fn(seed: u64, chunk: *main.chunk.ServerChunk, caveMap: CaveMap.CaveMapView, biomeMap: CaveBiomeMap.CaveBiomeMapView) void,
/// Used to prioritize certain generators over others.
priority: i32,
/// To avoid duplicate seeds in similar generation algorithms, the SurfaceGenerator xors the world-seed with the generator specific seed.
generatorSeed: u64,
var generatorRegistry: std.StringHashMapUnmanaged(BlockGenerator) = .{};
pub fn registerGenerator(comptime GeneratorType: type) void {
const self = BlockGenerator{
.init = &GeneratorType.init,
.deinit = &GeneratorType.deinit,
.generate = &GeneratorType.generate,
.priority = GeneratorType.priority,
.generatorSeed = GeneratorType.generatorSeed,
};
generatorRegistry.put(main.globalAllocator.allocator, GeneratorType.id, self) catch unreachable;
}
fn getAndInitGenerators(allocator: NeverFailingAllocator, settings: ZonElement) []BlockGenerator {
const list = allocator.alloc(BlockGenerator, generatorRegistry.size);
var iterator = generatorRegistry.iterator();
var i: usize = 0;
while(iterator.next()) |generator| {
list[i] = generator.value_ptr.*;
list[i].init(settings.getChild(generator.key_ptr.*));
i += 1;
}
const lessThan = struct {
fn lessThan(_: void, lhs: BlockGenerator, rhs: BlockGenerator) bool {
return lhs.priority < rhs.priority;
}
}.lessThan;
std.sort.insertion(BlockGenerator, list, {}, lessThan);
return list;
}
};
/// Lists all the Generators and Biomes that should be used for a given world.
/// TODO: Generator/Biome blackslisting (from the world creation menu).
/// TODO: Generator settings (from the world creation menu).
pub const TerrainGenerationProfile = struct {
mapFragmentGenerator: SurfaceMap.MapGenerator = undefined,
climateGenerator: ClimateMap.ClimateMapGenerator = undefined,
caveBiomeGenerators: []CaveBiomeMap.CaveBiomeGenerator = undefined,
caveGenerators: []CaveMap.CaveGenerator = undefined,
structureMapGenerators: []StructureMap.StructureMapGenerator = undefined,
generators: []BlockGenerator = undefined,
climateWavelengths: [5]f32 = undefined,
seed: u64,
pub fn init(settings: ZonElement, seed: u64) !TerrainGenerationProfile {
var self = TerrainGenerationProfile{
.seed = seed,
};
var generator = settings.getChild("mapGenerator");
self.mapFragmentGenerator = try SurfaceMap.MapGenerator.getGeneratorById(generator.get([]const u8, "id", "cubyz:mapgen_v1"));
self.mapFragmentGenerator.init(generator);
generator = settings.getChild("climateGenerator");
self.climateGenerator = try ClimateMap.ClimateMapGenerator.getGeneratorById(generator.get([]const u8, "id", "cubyz:polar_circles"));
self.climateGenerator.init(generator);
generator = settings.getChild("caveBiomeGenerators");
self.caveBiomeGenerators = CaveBiomeMap.CaveBiomeGenerator.getAndInitGenerators(main.globalAllocator, generator);
generator = settings.getChild("caveGenerators");
self.caveGenerators = CaveMap.CaveGenerator.getAndInitGenerators(main.globalAllocator, generator);
generator = settings.getChild("structureMapGenerators");
self.structureMapGenerators = StructureMap.StructureMapGenerator.getAndInitGenerators(main.globalAllocator, generator);
generator = settings.getChild("generators");
self.generators = BlockGenerator.getAndInitGenerators(main.globalAllocator, generator);
const climateWavelengths = settings.getChild("climateWavelengths");
self.climateWavelengths[0] = climateWavelengths.get(f32, "hot_cold", 2400);
self.climateWavelengths[1] = climateWavelengths.get(f32, "land_ocean", 3200);
self.climateWavelengths[2] = climateWavelengths.get(f32, "wet_dry", 2400);
self.climateWavelengths[3] = climateWavelengths.get(f32, "vegetation", 2400);
self.climateWavelengths[4] = climateWavelengths.get(f32, "mountain", 500);
return self;
}
pub fn deinit(self: TerrainGenerationProfile) void {
self.mapFragmentGenerator.deinit();
self.climateGenerator.deinit();
for(self.caveBiomeGenerators) |generator| {
generator.deinit();
}
main.globalAllocator.free(self.caveBiomeGenerators);
for(self.caveGenerators) |generator| {
generator.deinit();
}
main.globalAllocator.free(self.caveGenerators);
for(self.structureMapGenerators) |generator| {
generator.deinit();
}
main.globalAllocator.free(self.structureMapGenerators);
for(self.generators) |generator| {
generator.deinit();
}
main.globalAllocator.free(self.generators);
}
};
pub fn initGenerators() void {
SurfaceMap.initGenerators();
ClimateMap.initGenerators();
CaveBiomeMap.initGenerators();
CaveMap.initGenerators();
StructureMap.initGenerators();
const list = @import("chunkgen/_list.zig");
inline for(@typeInfo(list).@"struct".decls) |decl| {
BlockGenerator.registerGenerator(@field(list, decl.name));
}
const t1 = std.time.milliTimestamp();
noise.BlueNoise.load();
std.log.info("Blue noise took {} ms to load", .{std.time.milliTimestamp() -% t1});
}
pub fn deinitGenerators() void {
SurfaceMap.deinitGenerators();
ClimateMap.deinitGenerators();
CaveBiomeMap.deinitGenerators();
CaveMap.deinitGenerators();
StructureMap.deinitGenerators();
BlockGenerator.generatorRegistry.clearAndFree(main.globalAllocator.allocator);
}
pub fn init(profile: TerrainGenerationProfile) void {
CaveBiomeMap.init(profile);
CaveMap.init(profile);
StructureMap.init(profile);
ClimateMap.init(profile);
SurfaceMap.init(profile);
}
pub fn deinit() void {
CaveBiomeMap.deinit();
CaveMap.deinit();
StructureMap.deinit();
ClimateMap.deinit();
SurfaceMap.deinit();
LightMap.deinit();
}