From 93219e3b9d2eae11a447556dfe837706baeff22a Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 24 Mar 2012 03:28:08 +0200 Subject: Add sounds, tune things --- games/mesetint/mods/default/init.lua | 115 ++++++++++++++++++++++++++++++++++- src/game.cpp | 111 ++++++++++++++++++++++----------- src/nodedef.cpp | 3 + src/nodedef.h | 1 + src/scriptapi.cpp | 9 +-- src/sound.h | 2 +- src/sound_openal.cpp | 4 ++ 7 files changed, 201 insertions(+), 44 deletions(-) diff --git a/games/mesetint/mods/default/init.lua b/games/mesetint/mods/default/init.lua index 0041e3588..042cb7cdf 100644 --- a/games/mesetint/mods/default/init.lua +++ b/games/mesetint/mods/default/init.lua @@ -623,6 +623,75 @@ minetest.register_craft({ -- Node definitions -- +-- Default node sounds + +function default.node_sound_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="", gain=1.0} + table.dug = table.dug or + {name="default_dug_node", gain=1.0} + return table +end + +function default.node_sound_stone_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="default_hard_footstep", gain=0.2} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_dirt_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="", gain=0.5} + --table.dug = table.dug or + -- {name="default_dirt_break", gain=0.5} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_sand_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="default_grass_footstep", gain=0.25} + table.dug = table.dug or + {name="default_dirt_break", gain=0.25} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_wood_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="default_hard_footstep", gain=0.3} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_leaves_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="default_grass_footstep", gain=0.25} + table.dug = table.dug or + {name="", gain=1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_glass_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name="default_stone_footstep", gain=0.25} + table.dug = table.dug or + {name="default_break_glass", gain=1.0} + default.node_sound_defaults(table) + return table +end + +-- + minetest.register_node("default:stone", { description = "Stone", tile_images = {"default_stone.png"}, @@ -630,6 +699,7 @@ minetest.register_node("default:stone", { groups = {cracky=3}, drop = 'default:cobble', legacy_mineral = true, + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:stone_with_coal", { @@ -638,6 +708,7 @@ minetest.register_node("default:stone_with_coal", { is_ground_content = true, groups = {cracky=3}, drop = 'default:coal_lump', + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:stone_with_iron", { @@ -646,6 +717,7 @@ minetest.register_node("default:stone_with_iron", { is_ground_content = true, groups = {cracky=3}, drop = 'default:iron_lump', + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:dirt_with_grass", { @@ -654,10 +726,9 @@ minetest.register_node("default:dirt_with_grass", { is_ground_content = true, groups = {crumbly=3}, drop = 'default:dirt', - sounds = { - --footstep = "default_grass_footstep", + sounds = default.node_sound_dirt_defaults({ footstep = {name="default_grass_footstep", gain=0.5}, - }, + }), }) minetest.register_node("default:dirt_with_grass_footsteps", { @@ -666,6 +737,9 @@ minetest.register_node("default:dirt_with_grass_footsteps", { is_ground_content = true, groups = {crumbly=3}, drop = 'default:dirt', + sounds = default.node_sound_dirt_defaults({ + footstep = {name="default_grass_footstep", gain=0.5}, + }), }) minetest.register_node("default:dirt", { @@ -673,6 +747,7 @@ minetest.register_node("default:dirt", { tile_images = {"default_dirt.png"}, is_ground_content = true, groups = {crumbly=3}, + sounds = default.node_sound_dirt_defaults(), }) minetest.register_node("default:sand", { @@ -680,6 +755,7 @@ minetest.register_node("default:sand", { tile_images = {"default_sand.png"}, is_ground_content = true, groups = {crumbly=3}, + sounds = default.node_sound_sand_defaults(), }) minetest.register_node("default:gravel", { @@ -687,6 +763,9 @@ minetest.register_node("default:gravel", { tile_images = {"default_gravel.png"}, is_ground_content = true, groups = {crumbly=2}, + sounds = default.node_sound_sand_defaults({ + footstep = {name="default_gravel_footstep", gain=0.5} + }), }) minetest.register_node("default:sandstone", { @@ -695,6 +774,7 @@ minetest.register_node("default:sandstone", { is_ground_content = true, groups = {crumbly=2,cracky=2}, drop = 'default:sand', + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:clay", { @@ -703,6 +783,9 @@ minetest.register_node("default:clay", { is_ground_content = true, groups = {crumbly=3}, drop = 'default:clay_lump 4', + sounds = default.node_sound_dirt_defaults({ + footstep = "", + }), }) minetest.register_node("default:brick", { @@ -711,6 +794,7 @@ minetest.register_node("default:brick", { is_ground_content = true, groups = {cracky=3}, drop = 'default:clay_brick 4', + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:tree", { @@ -718,6 +802,7 @@ minetest.register_node("default:tree", { tile_images = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, is_ground_content = true, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:jungletree", { @@ -725,6 +810,7 @@ minetest.register_node("default:jungletree", { tile_images = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, is_ground_content = true, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:junglegrass", { @@ -737,6 +823,7 @@ minetest.register_node("default:junglegrass", { paramtype = "light", walkable = false, groups = {snappy=3}, + sounds = default.node_sound_leaves_defaults(), }) minetest.register_node("default:leaves", { @@ -761,6 +848,7 @@ minetest.register_node("default:leaves", { } } }, + sounds = default.node_sound_leaves_defaults(), }) minetest.register_node("default:cactus", { @@ -768,6 +856,7 @@ minetest.register_node("default:cactus", { tile_images = {"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"}, is_ground_content = true, groups = {snappy=2,choppy=3}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:papyrus", { @@ -780,6 +869,7 @@ minetest.register_node("default:papyrus", { is_ground_content = true, walkable = false, groups = {snappy=3}, + sounds = default.node_sound_leaves_defaults(), }) minetest.register_node("default:bookshelf", { @@ -787,6 +877,7 @@ minetest.register_node("default:bookshelf", { tile_images = {"default_wood.png", "default_wood.png", "default_bookshelf.png"}, is_ground_content = true, groups = {snappy=2,choppy=3,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:glass", { @@ -798,6 +889,7 @@ minetest.register_node("default:glass", { sunlight_propagates = true, is_ground_content = true, groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), }) minetest.register_node("default:fence_wood", { @@ -813,6 +905,7 @@ minetest.register_node("default:fence_wood", { fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, }, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:rail", { @@ -850,6 +943,7 @@ minetest.register_node("default:ladder", { }, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=3}, legacy_wallmounted = true, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:wood", { @@ -857,6 +951,7 @@ minetest.register_node("default:wood", { tile_images = {"default_wood.png"}, is_ground_content = true, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:mese", { @@ -864,12 +959,14 @@ minetest.register_node("default:mese", { tile_images = {"default_mese.png"}, is_ground_content = true, groups = {cracky=1}, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:cloud", { description = "Cloud", tile_images = {"default_cloud.png"}, is_ground_content = true, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:water_flowing", { @@ -985,6 +1082,7 @@ minetest.register_node("default:torch", { }, groups = {choppy=2,dig_immediate=3}, legacy_wallmounted = true, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:sign_wall", { @@ -1006,6 +1104,7 @@ minetest.register_node("default:sign_wall", { }, groups = {choppy=2,dig_immediate=2}, legacy_wallmounted = true, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:chest", { @@ -1016,6 +1115,7 @@ minetest.register_node("default:chest", { metadata_name = "chest", groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, legacy_facedir_simple = true, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:chest_locked", { @@ -1026,6 +1126,7 @@ minetest.register_node("default:chest_locked", { metadata_name = "locked_chest", groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, legacy_facedir_simple = true, + sounds = default.node_sound_wood_defaults(), }) minetest.register_node("default:furnace", { @@ -1036,6 +1137,7 @@ minetest.register_node("default:furnace", { metadata_name = "furnace", groups = {cracky=2}, legacy_facedir_simple = true, + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:cobble", { @@ -1043,6 +1145,7 @@ minetest.register_node("default:cobble", { tile_images = {"default_cobble.png"}, is_ground_content = true, groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:mossycobble", { @@ -1050,6 +1153,7 @@ minetest.register_node("default:mossycobble", { tile_images = {"default_mossycobble.png"}, is_ground_content = true, groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:steelblock", { @@ -1057,6 +1161,7 @@ minetest.register_node("default:steelblock", { tile_images = {"default_steel_block.png"}, is_ground_content = true, groups = {snappy=1,bendy=2}, + sounds = default.node_sound_stone_defaults(), }) minetest.register_node("default:nyancat", { @@ -1067,6 +1172,7 @@ minetest.register_node("default:nyancat", { paramtype2 = "facedir", groups = {cracky=2}, legacy_facedir_simple = true, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:nyancat_rainbow", { @@ -1074,6 +1180,7 @@ minetest.register_node("default:nyancat_rainbow", { tile_images = {"default_nc_rb.png"}, inventory_image = "default_nc_rb.png", groups = {cracky=2}, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:sapling", { @@ -1086,6 +1193,7 @@ minetest.register_node("default:sapling", { paramtype = "light", walkable = false, groups = {snappy=2,dig_immediate=3}, + sounds = default.node_sound_defaults(), }) minetest.register_node("default:apple", { @@ -1099,6 +1207,7 @@ minetest.register_node("default:apple", { walkable = false, groups = {fleshy=3,dig_immediate=3}, on_use = minetest.item_eat(4), + sounds = default.node_sound_defaults(), }) -- diff --git a/src/game.cpp b/src/game.cpp index 3cad4c895..9715c6676 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -780,19 +780,34 @@ public: } }; -class SoundMaker +class NodeDugEvent: public MtEvent { public: - ISoundManager *m_sound; + v3s16 p; + MapNode n; + NodeDugEvent(v3s16 p, MapNode n): + p(p), + n(n) + {} + const char* getType() const + {return "NodeDug";} +}; + +class SoundMaker +{ + ISoundManager *m_sound; + INodeDefManager *m_ndef; +public: float m_player_step_timer; SimpleSoundSpec m_player_step_sound; SimpleSoundSpec m_player_leftpunch_sound; SimpleSoundSpec m_player_rightpunch_sound; - SoundMaker(ISoundManager *sound): + SoundMaker(ISoundManager *sound, INodeDefManager *ndef): m_sound(sound), + m_ndef(ndef), m_player_step_timer(0) { } @@ -805,20 +820,6 @@ public: } } - void playPlayerLeftPunch() - { - if(m_player_leftpunch_sound.exists()){ - m_sound->playSound(m_player_leftpunch_sound, false); - } - } - - void playPlayerRightPunch() - { - if(m_player_rightpunch_sound.exists()){ - m_sound->playSound(m_player_rightpunch_sound, false); - } - } - static void viewBobbingStep(MtEvent *e, void *data) { SoundMaker *sm = (SoundMaker*)data; @@ -839,13 +840,20 @@ public: static void cameraPunchLeft(MtEvent *e, void *data) { SoundMaker *sm = (SoundMaker*)data; - sm->playPlayerLeftPunch(); + sm->m_sound->playSound(sm->m_player_leftpunch_sound, false); } static void cameraPunchRight(MtEvent *e, void *data) { SoundMaker *sm = (SoundMaker*)data; - sm->playPlayerRightPunch(); + sm->m_sound->playSound(sm->m_player_rightpunch_sound, false); + } + + static void nodeDug(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker*)data; + NodeDugEvent *nde = (NodeDugEvent*)e; + sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false); } void registerReceiver(MtEventManager *mgr) @@ -855,6 +863,7 @@ public: mgr->reg("PlayerJump", SoundMaker::playerJump, this); mgr->reg("CameraPunchLeft", SoundMaker::cameraPunchLeft, this); mgr->reg("CameraPunchRight", SoundMaker::cameraPunchRight, this); + mgr->reg("NodeDug", SoundMaker::nodeDug, this); } void step(float dtime) @@ -863,6 +872,33 @@ public: } }; +// Locally stored sounds don't need to be preloaded because of this +class GameOnDemandSoundFetcher: public OnDemandSoundFetcher +{ + std::set m_fetched; +public: + + void fetchSounds(const std::string &name, + std::set &dst_paths, + std::set > &dst_datas) + { + if(m_fetched.count(name)) + return; + m_fetched.insert(name); + std::string base = porting::path_share + DIR_DELIM + "testsounds"; + dst_paths.insert(base + DIR_DELIM + name + ".ogg"); + dst_paths.insert(base + DIR_DELIM + name + "1.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "2.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "3.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "4.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "5.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "6.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "7.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "8.ogg"); + dst_paths.insert(base + DIR_DELIM + name + "9.ogg"); + } +}; + void the_game( bool &kill, bool random_input, @@ -911,12 +947,15 @@ void the_game( // Create node definition manager IWritableNodeDefManager *nodedef = createNodeDefManager(); + // Sound fetcher (useful when testing) + GameOnDemandSoundFetcher soundfetcher; + // Sound manager ISoundManager *sound = NULL; bool sound_is_dummy = false; #if USE_AUDIO infostream<<"Attempting to use OpenAL audio"<loadSound("default_grass_footstep", porting::path_share + DIR_DELIM + "sounds" + DIR_DELIM + "default_grass_walk1.ogg"); sound->loadSound("default_grass_footstep", porting::path_share + DIR_DELIM @@ -955,6 +995,7 @@ void the_game( + "sounds" + DIR_DELIM + "default_place_node2.ogg"); sound->loadSound("default_place_node", porting::path_share + DIR_DELIM + "sounds" + DIR_DELIM + "default_place_node3.ogg"); +#endif // Add chat log output for errors to be shown in chat LogOutputBuffer chat_log_error_buf(LMT_ERROR); @@ -2150,6 +2191,7 @@ void the_game( } bool left_punch = false; + soundmaker.m_player_leftpunch_sound.name = ""; if(playeritem_usable && input->getLeftState()) { @@ -2208,15 +2250,11 @@ void the_game( params = getDigParams(nodedef->get(n).groups, tp); } - soundmaker.m_player_leftpunch_sound.gain = 0.5; - if(params.main_group == "crumbly") - soundmaker.m_player_leftpunch_sound.name = - "default_dig_crumbly"; - else if(params.main_group == "cracky") + if(params.main_group != ""){ + soundmaker.m_player_leftpunch_sound.gain = 0.5; soundmaker.m_player_leftpunch_sound.name = - "default_dig_cracky"; - else - soundmaker.m_player_leftpunch_sound.name = ""; + std::string("default_dig_") + params.main_group; + } float dig_time_complete = 0.0; @@ -2256,6 +2294,7 @@ void the_game( infostream<<"Digging completed"< 0.5) - { - nodig_delay_timer = 0.5; - } + if(nodig_delay_timer > 0.3) + nodig_delay_timer = 0.3; // We want a slight delay to very little // time consuming nodes float mindelay = 0.15; if(nodig_delay_timer < mindelay) - { nodig_delay_timer = mindelay; - } + + // Send event to trigger sound + MtEvent *e = new NodeDugEvent(nodepos, wasnode); + gamedef->event()->put(e); } dig_time += dtime; diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 2a21136bf..954467d48 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -156,6 +156,7 @@ void ContentFeatures::reset() legacy_facedir_simple = false; legacy_wallmounted = false; sound_footstep = SimpleSoundSpec(); + sound_dug = SimpleSoundSpec(); } void ContentFeatures::serialize(std::ostream &os) @@ -203,6 +204,7 @@ void ContentFeatures::serialize(std::ostream &os) writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); serializeSimpleSoundSpec(sound_footstep, os); + serializeSimpleSoundSpec(sound_dug, os); } void ContentFeatures::deSerialize(std::istream &is) @@ -256,6 +258,7 @@ void ContentFeatures::deSerialize(std::istream &is) legacy_wallmounted = readU8(is); try{ deSerializeSimpleSoundSpec(sound_footstep, is); + deSerializeSimpleSoundSpec(sound_dug, is); }catch(SerializationError &e) {}; } diff --git a/src/nodedef.h b/src/nodedef.h index 3a0d0675f..585755b9d 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -203,6 +203,7 @@ struct ContentFeatures // Sound properties SimpleSoundSpec sound_footstep; + SimpleSoundSpec sound_dug; /* Methods diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 79da15c49..fce760eb8 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -811,11 +811,10 @@ static void push_pointed_thing(lua_State *L, const PointedThing& pointed) SimpleSoundSpec */ -static SimpleSoundSpec read_soundspec(lua_State *L, int index) +static void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) { if(index < 0) index = lua_gettop(L) + 1 + index; - SimpleSoundSpec spec; if(lua_isnil(L, index)){ } else if(lua_istable(L, index)){ getstringfield(L, index, "name", spec.name); @@ -823,7 +822,6 @@ static SimpleSoundSpec read_soundspec(lua_State *L, int index) } else if(lua_isstring(L, index)){ spec.name = lua_tostring(L, index); } - return spec; } /* @@ -1062,7 +1060,10 @@ static ContentFeatures read_content_features(lua_State *L, int index) lua_getfield(L, index, "sounds"); if(lua_istable(L, -1)){ lua_getfield(L, -1, "footstep"); - f.sound_footstep = read_soundspec(L, -1); + read_soundspec(L, -1, f.sound_footstep); + lua_pop(L, 1); + lua_getfield(L, -1, "dug"); + read_soundspec(L, -1, f.sound_dug); lua_pop(L, 1); } lua_pop(L, 1); diff --git a/src/sound.h b/src/sound.h index 6363d614e..7f6e4141e 100644 --- a/src/sound.h +++ b/src/sound.h @@ -61,7 +61,7 @@ public: virtual void updateListener(v3f pos, v3f vel, v3f at, v3f up) = 0; // playSound functions return -1 on failure, otherwise a handle to the - // sound + // sound. If name=="", call should be ignored without error. virtual int playSound(const std::string &name, bool loop, float volume) = 0; virtual int playSoundAt(const std::string &name, bool loop, diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp index 4f056888b..edcb9e8d4 100644 --- a/src/sound_openal.cpp +++ b/src/sound_openal.cpp @@ -454,6 +454,8 @@ public: int playSound(const std::string &name, bool loop, float volume) { maintain(); + if(name == "") + return 0; SoundBuffer *buf = getFetchBuffer(name); if(!buf){ infostream<<"OpenALSoundManager: \""<