aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--games/mesetint/mods/default/init.lua4
-rw-r--r--src/camera.cpp10
-rw-r--r--src/client.cpp8
-rw-r--r--src/client.h7
-rw-r--r--src/event.h72
-rw-r--r--src/event_manager.h115
-rw-r--r--src/game.cpp79
-rw-r--r--src/gamedef.h7
-rw-r--r--src/nodedef.cpp21
-rw-r--r--src/nodedef.h6
-rw-r--r--src/player.cpp10
-rw-r--r--src/scriptapi.cpp28
-rw-r--r--src/server.cpp12
-rw-r--r--src/server.h5
-rw-r--r--src/sound.h18
15 files changed, 388 insertions, 14 deletions
diff --git a/games/mesetint/mods/default/init.lua b/games/mesetint/mods/default/init.lua
index c850597ba..0041e3588 100644
--- a/games/mesetint/mods/default/init.lua
+++ b/games/mesetint/mods/default/init.lua
@@ -654,6 +654,10 @@ minetest.register_node("default:dirt_with_grass", {
is_ground_content = true,
groups = {crumbly=3},
drop = 'default:dirt',
+ sounds = {
+ --footstep = "default_grass_footstep",
+ footstep = {name="default_grass_footstep", gain=0.5},
+ },
})
minetest.register_node("default:dirt_with_grass_footsteps", {
diff --git a/src/camera.cpp b/src/camera.cpp
index 8dad8dc63..fada47608 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "noise.h" // easeCurve
#include "gamedef.h"
#include "sound.h"
+#include "event.h"
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
IGameDef *gamedef):
@@ -177,8 +178,10 @@ void Camera::step(f32 dtime)
bool step = (was == 0 ||
(was < 0.5f && m_view_bobbing_anim >= 0.5f) ||
(was > 0.5f && m_view_bobbing_anim <= 0.5f));
- if(step)
- m_gamedef->sound()->playSound("default_grass_walk", false, 1.0);
+ if(step){
+ MtEvent *e = new SimpleTriggerEvent("ViewBobbingStep");
+ m_gamedef->event()->put(e);
+ }
}
}
@@ -190,7 +193,8 @@ void Camera::step(f32 dtime)
{
m_digging_anim = 0;
m_digging_button = -1;
- m_gamedef->sound()->playSound("dig", false, 1.0);
+ MtEvent *e = new SimpleTriggerEvent("CameraDig");
+ m_gamedef->event()->put(e);
}
}
}
diff --git a/src/client.cpp b/src/client.cpp
index cb6d2075e..d8fb4eb77 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -226,12 +226,14 @@ Client::Client(
IWritableTextureSource *tsrc,
IWritableItemDefManager *itemdef,
IWritableNodeDefManager *nodedef,
- ISoundManager *sound
+ ISoundManager *sound,
+ MtEventManager *event
):
m_tsrc(tsrc),
m_itemdef(itemdef),
m_nodedef(nodedef),
m_sound(sound),
+ m_event(event),
m_mesh_update_thread(this),
m_env(
new ClientMap(this, this, control,
@@ -2330,4 +2332,8 @@ ISoundManager* Client::getSoundManager()
{
return m_sound;
}
+MtEventManager* Client::getEventManager()
+{
+ return m_event;
+}
diff --git a/src/client.h b/src/client.h
index 2a1681e92..13b36106c 100644
--- a/src/client.h
+++ b/src/client.h
@@ -44,6 +44,7 @@ class IWritableNodeDefManager;
//class IWritableCraftDefManager;
class ClientEnvironment;
struct MapDrawControl;
+class MtEventManager;
class ClientNotReadyException : public BaseException
{
@@ -175,7 +176,8 @@ public:
IWritableTextureSource *tsrc,
IWritableItemDefManager *itemdef,
IWritableNodeDefManager *nodedef,
- ISoundManager *sound
+ ISoundManager *sound,
+ MtEventManager *event
);
~Client();
@@ -308,6 +310,7 @@ public:
virtual ITextureSource* getTextureSource();
virtual u16 allocateUnknownNodeId(const std::string &name);
virtual ISoundManager* getSoundManager();
+ virtual MtEventManager* getEventManager();
private:
@@ -335,6 +338,8 @@ private:
IWritableItemDefManager *m_itemdef;
IWritableNodeDefManager *m_nodedef;
ISoundManager *m_sound;
+ MtEventManager *m_event;
+
MeshUpdateThread m_mesh_update_thread;
ClientEnvironment m_env;
con::Connection m_con;
diff --git a/src/event.h b/src/event.h
new file mode 100644
index 000000000..032cb2381
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,72 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef EVENT_HEADER
+#define EVENT_HEADER
+
+class MtEvent
+{
+public:
+ virtual ~MtEvent(){};
+ //virtual MtEvent* clone(){ return new IEvent; }
+ virtual const char* getType() const = 0;
+
+ MtEvent* checkIs(const std::string &type)
+ {
+ if(type == getType())
+ return this;
+ return NULL;
+ }
+};
+
+// An event with no parameters and customizable name
+class SimpleTriggerEvent: public MtEvent
+{
+ const char *type;
+public:
+ SimpleTriggerEvent(const char *type):
+ type(type)
+ {}
+ const char* getType() const
+ {return type;}
+};
+
+class MtEventReceiver
+{
+public:
+ virtual ~MtEventReceiver(){};
+ virtual void onEvent(MtEvent *e) = 0;
+};
+
+typedef void (*event_receive_func)(MtEvent *e, void *data);
+
+class MtEventManager
+{
+public:
+ virtual ~MtEventManager(){};
+ virtual void put(MtEvent *e) = 0;
+ virtual void reg(const char *type, event_receive_func f, void *data) = 0;
+ // If data==NULL, every occurence of f is deregistered.
+ virtual void dereg(const char *type, event_receive_func f, void *data) = 0;
+ virtual void reg(MtEventReceiver *r, const char *type) = 0;
+ virtual void dereg(MtEventReceiver *r, const char *type) = 0;
+};
+
+#endif
+
diff --git a/src/event_manager.h b/src/event_manager.h
new file mode 100644
index 000000000..b33d5a295
--- /dev/null
+++ b/src/event_manager.h
@@ -0,0 +1,115 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef EVENT_MANAGER_HEADER
+#define EVENT_MANAGER_HEADER
+
+#include "event.h"
+#include <list>
+#include <map>
+
+class EventManager: public MtEventManager
+{
+ static void receiverReceive(MtEvent *e, void *data)
+ {
+ MtEventReceiver *r = (MtEventReceiver*)data;
+ r->onEvent(e);
+ }
+ struct FuncSpec{
+ event_receive_func f;
+ void *d;
+ FuncSpec(event_receive_func f, void *d):
+ f(f), d(d)
+ {}
+ };
+ struct Dest{
+ std::list<FuncSpec> funcs;
+ };
+ std::map<std::string, Dest> m_dest;
+
+public:
+ ~EventManager()
+ {
+ }
+ void put(MtEvent *e)
+ {
+ std::map<std::string, Dest>::iterator i = m_dest.find(e->getType());
+ if(i != m_dest.end()){
+ std::list<FuncSpec> &funcs = i->second.funcs;
+ for(std::list<FuncSpec>::iterator i = funcs.begin();
+ i != funcs.end(); i++){
+ (*(i->f))(e, i->d);
+ }
+ }
+ delete e;
+ }
+ void reg(const char *type, event_receive_func f, void *data)
+ {
+ std::map<std::string, Dest>::iterator i = m_dest.find(type);
+ if(i != m_dest.end()){
+ i->second.funcs.push_back(FuncSpec(f, data));
+ } else{
+ std::list<FuncSpec> funcs;
+ Dest dest;
+ dest.funcs.push_back(FuncSpec(f, data));
+ m_dest[type] = dest;
+ }
+ }
+ void dereg(const char *type, event_receive_func f, void *data)
+ {
+ if(type != NULL){
+ std::map<std::string, Dest>::iterator i = m_dest.find(type);
+ if(i != m_dest.end()){
+ std::list<FuncSpec> &funcs = i->second.funcs;
+ std::list<FuncSpec>::iterator i = funcs.begin();
+ while(i != funcs.end()){
+ bool remove = (i->f == f && (!data || i->d == data));
+ if(remove)
+ funcs.erase(i++);
+ else
+ i++;
+ }
+ }
+ } else{
+ for(std::map<std::string, Dest>::iterator
+ i = m_dest.begin(); i != m_dest.end(); i++){
+ std::list<FuncSpec> &funcs = i->second.funcs;
+ std::list<FuncSpec>::iterator i = funcs.begin();
+ while(i != funcs.end()){
+ bool remove = (i->f == f && (!data || i->d == data));
+ if(remove)
+ funcs.erase(i++);
+ else
+ i++;
+ }
+ }
+ }
+ }
+ void reg(MtEventReceiver *r, const char *type)
+ {
+ reg(type, EventManager::receiverReceive, r);
+ }
+ void dereg(MtEventReceiver *r, const char *type)
+ {
+ dereg(type, EventManager::receiverReceive, r);
+ }
+};
+
+#endif
+
diff --git a/src/game.cpp b/src/game.cpp
index 1b24df59b..4c9442c00 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -59,6 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#if USE_AUDIO
#include "sound_openal.h"
#endif
+#include "event_manager.h"
#include <list>
/*
@@ -779,6 +780,58 @@ public:
}
};
+class SoundMaker
+{
+public:
+ ISoundManager *m_sound;
+
+ SimpleSoundSpec m_player_step_sound;
+ float m_player_step_timer;
+
+ SoundMaker(ISoundManager *sound):
+ m_sound(sound),
+ m_player_step_sound("default_grass_walk"),
+ m_player_step_timer(0)
+ {
+ }
+
+ void playPlayerStep()
+ {
+ if(m_player_step_timer <= 0 && m_player_step_sound.exists()){
+ m_player_step_timer = 0.03;
+ m_sound->playSound(m_player_step_sound, false);
+ }
+ }
+
+ static void viewBobbingStep(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker*)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerRegainGround(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker*)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerJump(MtEvent *e, void *data)
+ {
+ }
+
+ void registerReceiver(MtEventManager *mgr)
+ {
+ mgr->reg("ViewBobbingStep", SoundMaker::viewBobbingStep, this);
+ mgr->reg("PlayerRegainGround", SoundMaker::playerRegainGround, this);
+ mgr->reg("PlayerJump", SoundMaker::playerJump, this);
+ }
+
+ void step(float dtime)
+ {
+ m_player_step_timer -= dtime;
+ }
+};
+
void the_game(
bool &kill,
bool random_input,
@@ -841,10 +894,19 @@ void the_game(
sound = &dummySoundManager;
sound_is_dummy = true;
}
+
+ // Event manager
+ EventManager eventmgr;
+
+ // Sound maker
+ SoundMaker soundmaker(sound);
+ soundmaker.registerReceiver(&eventmgr);
// Test sounds
- sound->loadSound("default_grass_walk", porting::path_share + DIR_DELIM
+ sound->loadSound("default_grass_footstep", porting::path_share + DIR_DELIM
+ "sounds" + DIR_DELIM + "default_grass_walk3_mono.ogg");
+ sound->loadSound("default_grass_footstep", porting::path_share + DIR_DELIM
+ + "sounds" + DIR_DELIM + "default_grass_walk4_mono.ogg");
//sound->playSound("default_grass_walk", false, 1.0);
//sound->playSoundAt("default_grass_walk", true, 1.0, v3f(0,10,0)*BS);
@@ -879,7 +941,7 @@ void the_game(
MapDrawControl draw_control;
Client client(device, playername.c_str(), password, draw_control,
- tsrc, itemdef, nodedef, sound);
+ tsrc, itemdef, nodedef, sound, &eventmgr);
// Client acts as our GameDef
IGameDef *gamedef = &client;
@@ -1257,7 +1319,7 @@ void the_game(
if(object_hit_delay_timer >= 0)
object_hit_delay_timer -= dtime;
time_from_last_punch += dtime;
-
+
g_profiler->add("Elapsed time", dtime);
g_profiler->avg("FPS", 1./dtime);
@@ -1955,6 +2017,17 @@ void the_game(
camera.getCameraNode()->getUpVector());
/*
+ Update sound maker
+ */
+ {
+ soundmaker.step(dtime);
+
+ ClientMap &map = client.getEnv().getClientMap();
+ MapNode n = map.getNodeNoEx(player->getStandingNodePos());
+ soundmaker.m_player_step_sound = nodedef->get(n).sound_footstep;
+ }
+
+ /*
Calculate what block is the crosshair pointing to
*/
diff --git a/src/gamedef.h b/src/gamedef.h
index 91bcc0e65..3b5ad5cae 100644
--- a/src/gamedef.h
+++ b/src/gamedef.h
@@ -28,6 +28,7 @@ class INodeDefManager;
class ICraftDefManager;
class ITextureSource;
class ISoundManager;
+class MtEventManager;
/*
An interface for fetching game-global definitions like tool and
@@ -47,17 +48,19 @@ public:
// pointers in other threads than main thread will make things explode.
virtual ITextureSource* getTextureSource()=0;
- virtual ISoundManager* getSoundManager()=0;
-
// Used for keeping track of names/ids of unknown nodes
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
+ virtual ISoundManager* getSoundManager()=0;
+ virtual MtEventManager* getEventManager()=0;
+
// Shorthands
IItemDefManager* idef(){return getItemDefManager();}
INodeDefManager* ndef(){return getNodeDefManager();}
ICraftDefManager* cdef(){return getCraftDefManager();}
ITextureSource* tsrc(){return getTextureSource();}
ISoundManager* sound(){return getSoundManager();}
+ MtEventManager* event(){return getEventManager();}
};
#endif
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index f1946830f..2a21136bf 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -79,6 +79,22 @@ void MaterialSpec::deSerialize(std::istream &is)
}
/*
+ SimpleSoundSpec serialization
+*/
+
+static void serializeSimpleSoundSpec(const SimpleSoundSpec &ss,
+ std::ostream &os)
+{
+ os<<serializeString(ss.name);
+ writeF1000(os, ss.gain);
+}
+static void deSerializeSimpleSoundSpec(SimpleSoundSpec &ss, std::istream &is)
+{
+ ss.name = deSerializeString(is);
+ ss.gain = readF1000(is);
+}
+
+/*
ContentFeatures
*/
@@ -139,6 +155,7 @@ void ContentFeatures::reset()
selection_box = NodeBox();
legacy_facedir_simple = false;
legacy_wallmounted = false;
+ sound_footstep = SimpleSoundSpec();
}
void ContentFeatures::serialize(std::ostream &os)
@@ -185,6 +202,7 @@ void ContentFeatures::serialize(std::ostream &os)
selection_box.serialize(os);
writeU8(os, legacy_facedir_simple);
writeU8(os, legacy_wallmounted);
+ serializeSimpleSoundSpec(sound_footstep, os);
}
void ContentFeatures::deSerialize(std::istream &is)
@@ -236,6 +254,9 @@ void ContentFeatures::deSerialize(std::istream &is)
selection_box.deSerialize(is);
legacy_facedir_simple = readU8(is);
legacy_wallmounted = readU8(is);
+ try{
+ deSerializeSimpleSoundSpec(sound_footstep, is);
+ }catch(SerializationError &e) {};
}
/*
diff --git a/src/nodedef.h b/src/nodedef.h
index 2842b81e7..3a0d0675f 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef NODEDEF_HEADER
#define NODEDEF_HEADER
-#include "common_irrlicht.h"
+#include "irrlichttypes.h"
#include <string>
#include <iostream>
#include <map>
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tile.h"
#endif
#include "itemgroup.h"
+#include "sound.h" // SimpleSoundSpec
class IItemDefManager;
class ITextureSource;
class IGameDef;
@@ -200,6 +201,9 @@ struct ContentFeatures
// Set to true if wall_mounted used to be set to true
bool legacy_wallmounted;
+ // Sound properties
+ SimpleSoundSpec sound_footstep;
+
/*
Methods
*/
diff --git a/src/player.cpp b/src/player.cpp
index 48d2c2907..0d4a1cb69 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "collision.h"
#include "environment.h"
#include "gamedef.h"
+#include "event.h"
Player::Player(IGameDef *gamedef):
touching_ground(false),
@@ -367,6 +368,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
Player is allowed to jump when this is true.
*/
+ bool touching_ground_was = touching_ground;
touching_ground = false;
/*std::cout<<"Checking collisions for ("
@@ -608,6 +610,11 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
collision_info->push_back(info);
}
}
+
+ if(!touching_ground_was && touching_ground){
+ MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround");
+ m_gamedef->event()->put(e);
+ }
}
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
@@ -723,6 +730,9 @@ void LocalPlayer::applyControl(float dtime)
{
speed.Y = 6.5*BS;
setSpeed(speed);
+
+ MtEvent *e = new SimpleTriggerEvent("PlayerJump");
+ m_gamedef->event()->put(e);
}
}
// Use the oscillating value for getting out of water
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 27ab2950b..79da15c49 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -808,6 +808,25 @@ static void push_pointed_thing(lua_State *L, const PointedThing& pointed)
}
/*
+ SimpleSoundSpec
+*/
+
+static SimpleSoundSpec read_soundspec(lua_State *L, int index)
+{
+ 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);
+ getfloatfield(L, index, "gain", spec.gain);
+ } else if(lua_isstring(L, index)){
+ spec.name = lua_tostring(L, index);
+ }
+ return spec;
+}
+
+/*
ItemDefinition
*/
@@ -1038,6 +1057,15 @@ static ContentFeatures read_content_features(lua_State *L, int index)
getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
// Set to true if wall_mounted used to be set to true
getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
+
+ // Sound table
+ lua_getfield(L, index, "sounds");
+ if(lua_istable(L, -1)){
+ lua_getfield(L, -1, "footstep");
+ f.sound_footstep = read_soundspec(L, -1);
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
return f;
}
diff --git a/src/server.cpp b/src/server.cpp
index d762f2688..e781f1284 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tool.h"
#include "utility_string.h"
#include "sound.h" // dummySoundManager
+#include "event_manager.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@@ -853,6 +854,7 @@ Server::Server(
m_itemdef(createItemDefManager()),
m_nodedef(createNodeDefManager()),
m_craftdef(createCraftDefManager()),
+ m_event(new EventManager()),
m_thread(this),
m_emergethread(this),
m_time_of_day_send_timer(0),
@@ -1064,10 +1066,10 @@ Server::~Server()
delete i.getNode()->getValue();
}
}
-
- // Delete Environment
+
+ // Delete things in the reverse order of creation
delete m_env;
-
+ delete m_event;
delete m_itemdef;
delete m_nodedef;
delete m_craftdef;
@@ -4275,6 +4277,10 @@ ISoundManager* Server::getSoundManager()
{
return &dummySoundManager;
}
+MtEventManager* Server::getEventManager()
+{
+ return m_event;
+}
IWritableItemDefManager* Server::getWritableItemDefManager()
{
diff --git a/src/server.h b/src/server.h
index cdedd06d8..3baeb433d 100644
--- a/src/server.h
+++ b/src/server.h
@@ -40,6 +40,7 @@ typedef struct lua_State lua_State;
class IWritableItemDefManager;
class IWritableNodeDefManager;
class IWritableCraftDefManager;
+class EventManager;
class ServerError : public std::exception
{
@@ -514,6 +515,7 @@ public:
virtual ITextureSource* getTextureSource();
virtual u16 allocateUnknownNodeId(const std::string &name);
virtual ISoundManager* getSoundManager();
+ virtual MtEventManager* getEventManager();
IWritableItemDefManager* getWritableItemDefManager();
IWritableNodeDefManager* getWritableNodeDefManager();
@@ -684,6 +686,9 @@ private:
// Craft definition manager
IWritableCraftDefManager *m_craftdef;
+ // Event manager
+ EventManager *m_event;
+
// Mods
core::list<ModSpec> m_mods;
diff --git a/src/sound.h b/src/sound.h
index 72764345e..6363d614e 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -33,6 +33,18 @@ public:
std::set<std::vector<char> > &dst_datas) = 0;
};
+struct SimpleSoundSpec
+{
+ std::string name;
+ float gain;
+ SimpleSoundSpec(std::string name="", float gain=1.0):
+ name(name),
+ gain(gain)
+ {}
+ bool exists() {return name != "";}
+ // Serialization intentionally left out
+};
+
class ISoundManager
{
public:
@@ -47,6 +59,7 @@ public:
const std::vector<char> &filedata) = 0;
virtual void updateListener(v3f pos, v3f vel, v3f at, v3f up) = 0;
+
// playSound functions return -1 on failure, otherwise a handle to the
// sound
virtual int playSound(const std::string &name, bool loop,
@@ -54,6 +67,11 @@ public:
virtual int playSoundAt(const std::string &name, bool loop,
float volume, v3f pos) = 0;
virtual void stopSound(int sound) = 0;
+
+ int playSound(const SimpleSoundSpec &spec, bool loop)
+ { return playSound(spec.name, loop, spec.gain); }
+ int playSoundAt(const SimpleSoundSpec &spec, bool loop, v3f pos)
+ { return playSoundAt(spec.name, loop, spec.gain, pos); }
};
class DummySoundManager: public ISoundManager