Load music by ID from the assets folder and improve error handling when the file isn't found.

fixes #535
fixes #543
This commit is contained in:
IntegratedQuantum 2024-07-03 17:22:07 +02:00
parent 2e06b9d4af
commit 1f61ea0c37
34 changed files with 58 additions and 42 deletions

View File

@ -9,7 +9,7 @@
"hills" : 10, "hills" : 10,
"rivers" : true, "rivers" : true,
"music" : "sunrise", "music" : "cubyz:sunrise",
"ground_structure" : [ "ground_structure" : [
"cubyz:grass", "cubyz:grass",

View File

@ -2,7 +2,7 @@
"isCave" : true, "isCave" : true,
"maxHeight" : 0, "maxHeight" : 0,
"music" : "heart-of-the-beast", "music" : "cubyz:heart-of-the-beast",
"ground_structure" : [ "ground_structure" : [
"0 to 1 cubyz:gravel", "0 to 1 cubyz:gravel",

View File

@ -7,7 +7,7 @@
"caves" : -0.1, "caves" : -0.1,
"crystals" : 32, "crystals" : 32,
"music" : "la_kubisa_caverna", "music" : "cubyz:la_kubisa_caverna",
"stoneBlock" : "cubyz:stone", "stoneBlock" : "cubyz:stone",
"structures" : [ "structures" : [
{ {

View File

@ -7,7 +7,7 @@
"caves" : -0.1, "caves" : -0.1,
"crystals" : 32, "crystals" : 32,
"music" : "leaves", "music" : "cubyz:leaves",
"stoneBlock" : "cubyz:stone", "stoneBlock" : "cubyz:stone",
"ground_structure" : [ "ground_structure" : [

View File

@ -2,7 +2,7 @@
"isCave" : true, "isCave" : true,
"minHeight" : 0, "minHeight" : 0,
"music" : "GymnopedieNo1", "music" : "cubyz:GymnopedieNo1",
"ground_structure" : [], "ground_structure" : [],
} }

View File

@ -7,7 +7,7 @@
"caves" : -0.1, "caves" : -0.1,
"stalagmites" : 160, "stalagmites" : 160,
"music" : "heart-of-the-beast", "music" : "cubyz:heart-of-the-beast",
"stoneBlock" : "cubyz:stone" "stoneBlock" : "cubyz:stone"
} }

View File

@ -5,7 +5,7 @@
"caves" : -0.2, "caves" : -0.2,
"music" : "heart-of-the-beast", "music" : "cubyz:heart-of-the-beast",
"ground_structure" : [ "ground_structure" : [
"0 to 1 cubyz:gravel", "0 to 1 cubyz:gravel",

View File

@ -6,6 +6,6 @@
"caves" : -0.1, "caves" : -0.1,
"music" : "heart-of-the-beast", "music" : "cubyz:heart-of-the-beast",
"stoneBlock" : "cubyz:void_stone", "stoneBlock" : "cubyz:void_stone",
} }

View File

@ -9,7 +9,7 @@
"roughness" : 1, "roughness" : 1,
"hills" : 5, "hills" : 5,
"music" : "sunrise", "music" : "cubyz:sunrise",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -11,7 +11,7 @@
"roughness" : 20, "roughness" : 20,
"hills" : 10, "hills" : 10,
"music" : "under_the_water_sky", "music" : "cubyz:under_the_water_sky",
"ground_structure" : [ "ground_structure" : [
"1 to 2 cubyz:cobblestone" "1 to 2 cubyz:cobblestone"

View File

@ -8,7 +8,7 @@
"hills" : 20, "hills" : 20,
"music" : "EasternThought", "music" : "cubyz:EasternThought",
"fogDensity" : 20, "fogDensity" : 20,
"fogColor" : 0xe0dcc3, "fogColor" : 0xe0dcc3,

View File

@ -8,7 +8,7 @@
"roughness" : 10, "roughness" : 10,
"hills" : 10, "hills" : 10,
"music" : "leaves", "music" : "cubyz:leaves",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -8,7 +8,7 @@
"roughness" : 10, "roughness" : 10,
"hills" : 10, "hills" : 10,
"music" : "mana-two-part-2", "music" : "cubyz:mana-two-part-2",
"validPlayerSpawn" : false, "validPlayerSpawn" : false,

View File

@ -7,7 +7,7 @@
"roughness" : 1, "roughness" : 1,
"hills" : 5, "hills" : 5,
"music" : "sunrise", "music" : "cubyz:sunrise",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -6,7 +6,7 @@
"minHeight" : 4, "minHeight" : 4,
"maxHeight" : 4, "maxHeight" : 4,
"music" : "sunrise", "music" : "cubyz:sunrise",
"radius" : 24, "radius" : 24,

View File

@ -6,7 +6,7 @@
"minHeight" : -10, "minHeight" : -10,
"maxHeight" : -10, "maxHeight" : -10,
"music" : "Sincerely", "music" : "cubyz:Sincerely",
"radius" : 64, "radius" : 64,

View File

@ -9,7 +9,7 @@
"roughness" : 10, "roughness" : 10,
"hills" : 10, "hills" : 10,
"music" : "leaves", "music" : "cubyz:leaves",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -11,7 +11,7 @@
"rivers" : true, "rivers" : true,
"music" : "under_the_water_sky", "music" : "cubyz:under_the_water_sky",
"ground_structure" : [ "ground_structure" : [
"2 to 3 cubyz:gravel" "2 to 3 cubyz:gravel"

View File

@ -7,7 +7,7 @@
"mountains" : 125, "mountains" : 125,
"music" : "DarkTimes", "music" : "cubyz:DarkTimes",
"ground_structure" : [ "ground_structure" : [
"3 to 6 cubyz:snow" "3 to 6 cubyz:snow"

View File

@ -10,7 +10,7 @@
"chance" : 0.01, "chance" : 0.01,
"music" : "leaves", "music" : "cubyz:leaves",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -7,7 +7,7 @@
"mountains" : 30, "mountains" : 30,
"music" : "sunrise", "music" : "cubyz:sunrise",
"ground_structure" : [ "ground_structure" : [
"cubyz:grass", "cubyz:grass",

View File

@ -9,7 +9,7 @@
"roughness" : 2, "roughness" : 2,
"hills" : 2, "hills" : 2,
"music" : "leaves", "music" : "cubyz:leaves",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -11,7 +11,7 @@
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -10,7 +10,7 @@
"mountains" : 30, "mountains" : 30,
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -11,7 +11,7 @@
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -10,7 +10,7 @@
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -10,7 +10,7 @@
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -10,7 +10,7 @@
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -9,7 +9,7 @@
"interpolation" : "linear", "interpolation" : "linear",
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -9,7 +9,7 @@
"interpolation" : "linear", "interpolation" : "linear",
"chance" : 0, "chance" : 0,
"music" : "out_of_breath", "music" : "cubyz:out_of_breath",
"parentBiomes" : [ "parentBiomes" : [
{ {

View File

@ -10,7 +10,7 @@
"roughness" : 10, "roughness" : 10,
"hills" : 10, "hills" : 10,
"music" : "leaves", "music" : "cubyz:leaves",
"validPlayerSpawn" : true, "validPlayerSpawn" : true,

View File

@ -10,7 +10,7 @@
"roughness" : 10, "roughness" : 10,
"hills" : 20, "hills" : 20,
"music" : "tides", "music" : "cubyz:tides",
"ground_structure" : [ "ground_structure" : [
"2 to 4 cubyz:sand" "2 to 4 cubyz:sand"

View File

@ -20,18 +20,33 @@ const AudioData = struct {
musicId: []const u8, musicId: []const u8,
data: []f32 = &.{}, data: []f32 = &.{},
fn open_vorbis_file_by_id(id: []const u8) ?*c.stb_vorbis {
const colonIndex = std.mem.indexOfScalar(u8, id, ':') orelse {
std.log.err("Invalid music id: {s}. Must be addon:file_name", .{id});
return null;
};
const addon = id[0..colonIndex];
const fileName = id[colonIndex+1..];
const path1 = std.fmt.allocPrintZ(main.stackAllocator.allocator, "assets/{s}/music/{s}.ogg", .{addon, fileName}) catch unreachable;
defer main.stackAllocator.free(path1);
var err: c_int = 0;
if(c.stb_vorbis_open_filename(path1.ptr, &err, null)) |ogg_stream| return ogg_stream;
const path2 = std.fmt.allocPrintZ(main.stackAllocator.allocator, "serverAssets/{s}/music/{s}.ogg", .{addon, fileName}) catch unreachable;
defer main.stackAllocator.free(path2);
if(c.stb_vorbis_open_filename(path2.ptr, &err, null)) |ogg_stream| return ogg_stream;
std.log.err("Couldn't find music with id \"{s}\". Searched path \"{s}\" and \"{s}\"", .{id, path1, path2});
return null;
}
fn init(musicId: []const u8) *AudioData { fn init(musicId: []const u8) *AudioData {
const self = main.globalAllocator.create(AudioData); const self = main.globalAllocator.create(AudioData);
self.* = .{.musicId = musicId}; self.* = .{.musicId = musicId};
var err: c_int = 0;
const path = std.fmt.allocPrintZ(main.stackAllocator.allocator, "assets/cubyz/music/{s}.ogg", .{musicId}) catch unreachable; const channels = 2;
defer main.stackAllocator.free(path); if(open_vorbis_file_by_id(musicId)) |ogg_stream| {
const ogg_stream = c.stb_vorbis_open_filename(path.ptr, &err, null); defer c.stb_vorbis_close(ogg_stream);
defer c.stb_vorbis_close(ogg_stream);
if(ogg_stream != null) {
const ogg_info: c.stb_vorbis_info = c.stb_vorbis_get_info(ogg_stream); const ogg_info: c.stb_vorbis_info = c.stb_vorbis_get_info(ogg_stream);
const samples = c.stb_vorbis_stream_length_in_samples(ogg_stream); const samples = c.stb_vorbis_stream_length_in_samples(ogg_stream);
const channels = 2;
if(sampleRate != @as(f32, @floatFromInt(ogg_info.sample_rate))) { if(sampleRate != @as(f32, @floatFromInt(ogg_info.sample_rate))) {
const tempData = main.stackAllocator.alloc(f32, samples*channels); const tempData = main.stackAllocator.alloc(f32, samples*channels);
defer main.stackAllocator.free(tempData); defer main.stackAllocator.free(tempData);
@ -57,7 +72,8 @@ const AudioData = struct {
_ = c.stb_vorbis_get_samples_float_interleaved(ogg_stream, channels, self.data.ptr, @as(c_int, @intCast(samples))*ogg_info.channels); _ = c.stb_vorbis_get_samples_float_interleaved(ogg_stream, channels, self.data.ptr, @as(c_int, @intCast(samples))*ogg_info.channels);
} }
} else { } else {
std.log.err("Couldn't read audio with id {s}", .{musicId}); self.data = main.globalAllocator.alloc(f32, channels);
@memset(self.data, 0);
} }
return self; return self;
} }
@ -231,7 +247,7 @@ var curIndex: u16 = 0;
var curEndIndex: std.atomic.Value(u16) = .{.value = sampleRate/60 & ~@as(u16, 1)}; var curEndIndex: std.atomic.Value(u16) = .{.value = sampleRate/60 & ~@as(u16, 1)};
fn addMusic(buffer: []f32) void { fn addMusic(buffer: []f32) void {
const musicId = if(main.game.world) |world| world.playerBiome.load(.monotonic).preferredMusic else "cubyz"; const musicId = if(main.game.world) |world| world.playerBiome.load(.monotonic).preferredMusic else "cubyz:cubyz";
if(!std.mem.eql(u8, musicId, activeMusicId)) { if(!std.mem.eql(u8, musicId, activeMusicId)) {
if(activeMusicId.len == 0) { if(activeMusicId.len == 0) {
if(findMusic(musicId)) |musicBuffer| { if(findMusic(musicId)) |musicBuffer| {

View File

@ -275,7 +275,7 @@ pub const Biome = struct {
.minHeight = json.get(i32, "minHeight", std.math.minInt(i32)), .minHeight = json.get(i32, "minHeight", std.math.minInt(i32)),
.maxHeight = json.get(i32, "maxHeight", std.math.maxInt(i32)), .maxHeight = json.get(i32, "maxHeight", std.math.maxInt(i32)),
.supportsRivers = json.get(bool, "rivers", false), .supportsRivers = json.get(bool, "rivers", false),
.preferredMusic = main.globalAllocator.dupe(u8, json.get([]const u8, "music", "")), .preferredMusic = main.globalAllocator.dupe(u8, json.get([]const u8, "music", "cubyz:cubyz")),
.isValidPlayerSpawn = json.get(bool, "validPlayerSpawn", false), .isValidPlayerSpawn = json.get(bool, "validPlayerSpawn", false),
.chance = json.get(f32, "chance", if(json == .JsonNull) 0 else 1), .chance = json.get(f32, "chance", if(json == .JsonNull) 0 else 1),
.maxSubBiomeCount = json.get(f32, "maxSubBiomeCount", std.math.floatMax(f32)), .maxSubBiomeCount = json.get(f32, "maxSubBiomeCount", std.math.floatMax(f32)),