aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api
Commit message (Collapse)AuthorAge
* Move client-specific files to 'src/client' (#7902)Quentin Bazin2018-11-28
| | | | | Update Android.mk Remove 'src/client' from include_directories
* Add Lua methods 'set_rotation()' and 'get_rotation()' (#7395)CoderForTheBetter2018-11-28
| | | | * Adds Lua methods 'set_rotation()' and 'get_rotation'. Also changed some method names to be more clear. Instead of an f32 being sent over network for yaw, now a v3f is sent for rotation on xyz axes. Perserved Lua method set_yaw/setyaw so that old mods still work, other wise to set yaw they would need to switch to set_rotation(0, yaw, 0).
* Content store: Add setting to filter non-free packages (#7766)rubenwardy2018-11-08
| | | | Defaulting to hiding in order to help with Debian/etc distribution. This could be changed at a later date.
* clear_craft: Return false if recipe not found, don't throw error (#7804)Paramat2018-10-24
|
* Add core.remove_detached_inventory (#7684)SmallJoker2018-10-10
| | | | Breaks backwards compatibility for good Bump protocol version
* markAliasDeprecated: Fix MSVC buildSmallJoker2018-09-11
|
* Particles: Make collision with objects optional (#7682)Paramat2018-09-08
| | | | | | Also set it to false for node dig particles, as they are often created and high in number. Improve particle documentation.
* Raycast: export exact pointing location (#6304)Dániel Juhász2018-08-16
| | | | | * Return intersection point in node coordinates. * Clarify 'intersection_point' documentation
* Replace auth.txt with SQLite auth database (#7279)Ben Deutsch2018-08-05
| | | | * Replace auth.txt with SQLite auth database
* LuaVoxelManip: Throw warning or error instead of silently doing nothing (#7567)HybridDog2018-08-02
| | | | Error on missing parameter. Warning when using a method on the incorrect type of LuaVoxelManip.
* Add protocol_version and supported package types to ContentDB urlsrubenwardy2018-07-29
|
* Lua templating reading (part 4): s16, v2s16, v2f (#7512)Loïc Blot2018-07-08
|
* Log deprecated Lua function calls (#7491)SmallJoker2018-07-01
|
* Modernize lua read (part 2 & 3): C++ templating assurance (#7410)Loïc Blot2018-06-30
| | | | | | | | | * Modernize lua read (part 2 & 3): C++ templating assurance Implement the boolean reader Implement the string reader Also remove unused & unimplemented script_error_handler Add a reader with default value
* Fix memory leaks in mod storage (#7500)red-0012018-06-30
|
* Fix world deletion (#7494)Vitaliy2018-06-30
| | | | * Fix world deletion
* Fix a memleak before assertion in l_get_mod_storageLoic Blot2018-06-30
|
* Fix mod channels crash (#7481)red-0012018-06-27
|
* Rename CSM flavours to restrictionsSmallJoker2018-06-26
| | | | & Satisfy LINT
* Update to new ContentDB APIrubenwardy2018-06-18
|
* Fix narrow/utf8 difference in incoming/outcoming messagesnumber Zero2018-06-10
|
* Modernize lua read (part 1): C++ templating insurance (#7394)Loïc Blot2018-06-04
| | | | | | | * Modernize lua read (part 1): C++ templating assurance Implement the float reader
* Fix isNan on setYaw Lua call (#7380)Loïc Blot2018-05-31
| | | | * Fix isNan on setYaw Lua call
* Fix missing ignore textures (#7326)you2018-05-20
|
* Add screenshots to online content browserrubenwardy2018-05-20
|
* Add updating to online content browserrubenwardy2018-05-16
|
* Allow damage for attached objects, add attach/detach callbacks (#6786)SmallJoker2018-04-30
| | | * Allow right-clicking on attached LuaEntities
* MetaDataRef: Add contains() and get() (#7214)rubenwardy2018-04-30
|
* Add online content repositoryrubenwardy2018-04-19
| | | | Replaces mods and texture pack tabs with a single content tab
* Biome API / dungeons: Add biome-defined dungeon nodesParamat2018-04-07
| | | | | | | | | | Add new biome fields 'node_dungeon', 'node_dungeon_alt', 'node_dungeon_stair'. If 'node_dungeon' is not defined dungeons fall back to classic behaviour. Remove messy and imprecise dungeon material code from 'generateBiomes()'. Code deciding dungeon materials is now in 'generateDungeons()' and uses the biome at mapchunk centre for more precision. Remove hardcoded 'MG_STONE' types as long intended.
* Add player:get_meta(), deprecate player attributes (#7202)rubenwardy2018-04-06
| | | | * Add player:get_meta(), deprecate player attributes
* Biome API / cavegen: Add definable cave liquid for a biome (#7192)Paramat2018-04-05
| | | | Add 'node_cave_liquid' as a new field in biome registration. If field is absent cave liquids fall back to classic behaviour.
* Fix last clang-tidy reported problems for performance-type-promotion-in-math-fnLoic Blot2018-04-03
| | | | | | Based on https://travis-ci.org/minetest/minetest/jobs/361810382 output Also fix 2 missing copyright notices
* Fix many issues reported by clang-tidy (#7189)Loïc Blot2018-04-02
| | | | | | | | | | | * Fix many issues reported by clang-tidy We have many issues in code related to some performance to float <-> double. Clang-tidy reported it in performance-type-promotion-in-math-fn I fixed many of them. It's not ready for a promote to blocking Also fix some value which should be const-ref
* ObjectRef: Add add_velocity() (#3208)you2018-03-31
| | | | Allow changing the velocity of objects relatively to their current velocity
* Load dependencies and description from mod.confAndrew Ward2018-03-28
|
* Add reasons to on_dieplayer and on_hpchangeAndrew Ward2018-03-28
|
* Add formspec theming using prepended stringsAndrew Ward2018-03-28
|
* Mapgen: Remove unused mgv7 code and some unused biometypesParamat2018-03-26
|
* Cleanup sound manager class (#7158)Loïc Blot2018-03-24
| | | | | | | | | | * Cleanup sound manager client * Use some const refs * Use auto on iterators * Drop unused parameters * Move sound_openal.* to client folder * Move sound.cpp + OnDemandSoundFetcher to client/ folder + reorganize includes properly
* Biome API: Add 'get_biome_name(biome_id)' APIparamat2018-03-11
| | | | Change name of default biome to a more suitable lowercase 'default'.
* Spawn level: Add 'get_spawn_level(x, z)' APIparamat2018-03-10
| | | | Returns a suitable player spawn y co-ordinate for unmodified terrain.
* Biomes: Add 'min_pos'/'max_pos' xyz biome limitsparamat2018-03-09
| | | | 'y_min' and 'y_max' are still accepted for compatibility.
* Cleanup & bugfixLoic Blot2018-03-08
| | | | | | | | * ObjectRef::set_local_animation: fix wrong lua return (should push a boolean, currently returns nil) * ObjectRef::set_eye_offset: fix wrong lua return (should push a boolean, currently returns nil) * Fix various Server functions which depends on RemotePlayer objet and return true/false when player object is nil whereas it's a caller implementation error. Change those bool functions to void and add sanitize_check call instead. Current callers are always checking player object validity * Optimize Server::setClouds : use CloudParams object ref instead of attribute deserialization from structure & perform RemotePlayer::setCloudParams directly in server class like many other calls * Optimize Server::SendCloudParams: use CloudParams object ref instead of deserialized attributes
* Cleanup: drop Server::hudGetHotbarSelectedImage()Loic Blot2018-03-08
| | | | Call directly accessible RemotePlayer::getHotbarSelectedImage() from server api
* Cleanup: drop Server::hudGetHotbarImage()Loic Blot2018-03-08
| | | | Call directly accessible RemotePlayer::getHotbarImage() from server api & make it const ref
* Cleanup: drop Server::hudGetHotbarItemcount()Loic Blot2018-03-08
| | | | Call directly accessible RemotePlayer::getHotbarItemcount() from server api
* Gennotify: Add 'minetest.get_decoration_id' APIparamat2018-03-03
| | | | | | Returns the decoration ID for the provided decoration name string. For use with gennotify, to know the decoration IDs for use in 'minetest.set_gen_notify'.
* Place schematic (on vmanip): Enable use of 'place center' flagsparamat2018-02-27
| | | | | | For 'place schematic' and 'place schematic on vmanip' APIs. Fix 'place center' code to properly centre schematics. Fix some comments.
* Find nodes in area (under air): Raise volume limit and document itparamat2018-02-21
|
n> 0; // 0 for Little-Endian, 1 for Big-Endian int bitStream; long bytes; char array[BUFFER_SIZE]; // Local fixed size array vorbis_info *pInfo; SoundBuffer *snd = new SoundBuffer; // Get some information about the OGG file pInfo = ov_info(oggFile, -1); // Check the number of channels... always use 16-bit samples if(pInfo->channels == 1) snd->format = AL_FORMAT_MONO16; else snd->format = AL_FORMAT_STEREO16; // The frequency of the sampling rate snd->freq = pInfo->rate; // Keep reading until all is read do { // Read up to a buffer's worth of decoded sound data bytes = ov_read(oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream); if(bytes < 0) { ov_clear(oggFile); infostream << "Audio: Error decoding " << filename_for_logging << std::endl; delete snd; return NULL; } // Append to end of buffer snd->buffer.insert(snd->buffer.end(), array, array + bytes); } while (bytes > 0); alGenBuffers(1, &snd->buffer_id); alBufferData(snd->buffer_id, snd->format, &(snd->buffer[0]), snd->buffer.size(), snd->freq); ALenum error = alGetError(); if(error != AL_NO_ERROR){ infostream<<"Audio: OpenAL error: "<<alErrorString(error) <<"preparing sound buffer"<<std::endl; } infostream << "Audio file " << filename_for_logging << " loaded" << std::endl; // Clean up! ov_clear(oggFile); return snd; } SoundBuffer *load_ogg_from_file(const std::string &path) { OggVorbis_File oggFile; // Try opening the given file. // This requires libvorbis >= 1.3.2, as // previous versions expect a non-const char * if (ov_fopen(path.c_str(), &oggFile) != 0) { infostream << "Audio: Error opening " << path << " for decoding" << std::endl; return NULL; } return load_opened_ogg_file(&oggFile, path); } struct BufferSource { const char *buf; size_t cur_offset; size_t len; }; size_t buffer_sound_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) { BufferSource *s = (BufferSource *)datasource; size_t copied_size = MYMIN(s->len - s->cur_offset, size); memcpy(ptr, s->buf + s->cur_offset, copied_size); s->cur_offset += copied_size; return copied_size; } int buffer_sound_seek_func(void *datasource, ogg_int64_t offset, int whence) { BufferSource *s = (BufferSource *)datasource; if (whence == SEEK_SET) { if (offset < 0 || (size_t)MYMAX(offset, 0) >= s->len) { // offset out of bounds return -1; } s->cur_offset = offset; return 0; } else if (whence == SEEK_CUR) { if ((size_t)MYMIN(-offset, 0) > s->cur_offset || s->cur_offset + offset > s->len) { // offset out of bounds return -1; } s->cur_offset += offset; return 0; } // invalid whence param (SEEK_END doesn't have to be supported) return -1; } long BufferSourceell_func(void *datasource) { BufferSource *s = (BufferSource *)datasource; return s->cur_offset; } static ov_callbacks g_buffer_ov_callbacks = { &buffer_sound_read_func, &buffer_sound_seek_func, NULL, &BufferSourceell_func }; SoundBuffer *load_ogg_from_buffer(const std::string &buf, const std::string &id_for_log) { OggVorbis_File oggFile; BufferSource s; s.buf = buf.c_str(); s.cur_offset = 0; s.len = buf.size(); if (ov_open_callbacks(&s, &oggFile, NULL, 0, g_buffer_ov_callbacks) != 0) { infostream << "Audio: Error opening " << id_for_log << " for decoding" << std::endl; return NULL; } return load_opened_ogg_file(&oggFile, id_for_log); } struct PlayingSound { ALuint source_id; bool loop; }; class OpenALSoundManager: public ISoundManager { private: OnDemandSoundFetcher *m_fetcher; ALCdevice *m_device; ALCcontext *m_context; int m_next_id; std::unordered_map<std::string, std::vector<SoundBuffer*>> m_buffers; std::unordered_map<int, PlayingSound*> m_sounds_playing; v3f m_listener_pos; struct FadeState { FadeState() {} FadeState(float step, float current_gain, float target_gain): step(step), current_gain(current_gain), target_gain(target_gain) {} float step; float current_gain; float target_gain; }; std::unordered_map<int, FadeState> m_sounds_fading; float m_fade_delay; public: bool m_is_initialized; OpenALSoundManager(OnDemandSoundFetcher *fetcher): m_fetcher(fetcher), m_device(NULL), m_context(NULL), m_next_id(1), m_fade_delay(0), m_is_initialized(false) { ALCenum error = ALC_NO_ERROR; infostream<<"Audio: Initializing..."<<std::endl; m_device = alcOpenDevice(NULL); if(!m_device){ infostream<<"Audio: No audio device available, audio system " <<"not initialized"<<std::endl; return; } m_context = alcCreateContext(m_device, NULL); if(!m_context){ error = alcGetError(m_device); infostream<<"Audio: Unable to initialize audio context, " <<"aborting audio initialization ("<<alcErrorString(error) <<")"<<std::endl; alcCloseDevice(m_device); m_device = NULL; return; } if(!alcMakeContextCurrent(m_context) || (error = alcGetError(m_device) != ALC_NO_ERROR)) { infostream<<"Audio: Error setting audio context, aborting audio " <<"initialization ("<<alcErrorString(error)<<")"<<std::endl; alcDestroyContext(m_context); m_context = NULL; alcCloseDevice(m_device); m_device = NULL; return; } alDistanceModel(AL_INVERSE_DISTANCE); infostream<<"Audio: Initialized: OpenAL "<<alGetString(AL_VERSION) <<", using "<<alcGetString(m_device, ALC_DEVICE_SPECIFIER) <<std::endl; m_is_initialized = true; } ~OpenALSoundManager() { infostream<<"Audio: Deinitializing..."<<std::endl; // KABOOM! // TODO: Clear SoundBuffers alcMakeContextCurrent(NULL); alcDestroyContext(m_context); m_context = NULL; alcCloseDevice(m_device); m_device = NULL; for (std::unordered_map<std::string, std::vector<SoundBuffer*>>::iterator i = m_buffers.begin(); i != m_buffers.end(); ++i) { for (std::vector<SoundBuffer*>::iterator iter = (*i).second.begin(); iter != (*i).second.end(); ++iter) { delete *iter; } (*i).second.clear(); } m_buffers.clear(); infostream<<"Audio: Deinitialized."<<std::endl; } void step(float dtime) { doFades(dtime); } void addBuffer(const std::string &name, SoundBuffer *buf) { std::unordered_map<std::string, std::vector<SoundBuffer*>>::iterator i = m_buffers.find(name); if(i != m_buffers.end()){ i->second.push_back(buf); return; } std::vector<SoundBuffer*> bufs; bufs.push_back(buf); m_buffers[name] = bufs; return; } SoundBuffer* getBuffer(const std::string &name) { std::unordered_map<std::string, std::vector<SoundBuffer*>>::iterator i = m_buffers.find(name); if(i == m_buffers.end()) return NULL; std::vector<SoundBuffer*> &bufs = i->second; int j = myrand() % bufs.size(); return bufs[j]; } PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop, float volume) { infostream<<"OpenALSoundManager: Creating playing sound"<<std::endl; assert(buf); PlayingSound *sound = new PlayingSound; assert(sound); warn_if_error(alGetError(), "before createPlayingSound"); alGenSources(1, &sound->source_id); alSourcei(sound->source_id, AL_BUFFER, buf->buffer_id); alSourcei(sound->source_id, AL_SOURCE_RELATIVE, true); alSource3f(sound->source_id, AL_POSITION, 0, 0, 0); alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); volume = MYMAX(0.0, volume); alSourcef(sound->source_id, AL_GAIN, volume); alSourcePlay(sound->source_id); warn_if_error(alGetError(), "createPlayingSound"); return sound; } PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop, float volume, v3f pos) { infostream<<"OpenALSoundManager: Creating positional playing sound" <<std::endl; assert(buf); PlayingSound *sound = new PlayingSound; assert(sound); warn_if_error(alGetError(), "before createPlayingSoundAt"); alGenSources(1, &sound->source_id); alSourcei(sound->source_id, AL_BUFFER, buf->buffer_id); alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false); alSource3f(sound->source_id, AL_POSITION, pos.X, pos.Y, pos.Z); alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); volume = MYMAX(0.0, volume); alSourcef(sound->source_id, AL_GAIN, volume); alSourcePlay(sound->source_id); warn_if_error(alGetError(), "createPlayingSoundAt"); return sound; } int playSoundRaw(SoundBuffer *buf, bool loop, float volume) { assert(buf); PlayingSound *sound = createPlayingSound(buf, loop, volume); if(!sound) return -1; int id = m_next_id++; m_sounds_playing[id] = sound; return id; } int playSoundRawAt(SoundBuffer *buf, bool loop, float volume, v3f pos) { assert(buf); PlayingSound *sound = createPlayingSoundAt(buf, loop, volume, pos); if(!sound) return -1; int id = m_next_id++; m_sounds_playing[id] = sound; return id; } void deleteSound(int id) { std::unordered_map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id); if(i == m_sounds_playing.end()) return; PlayingSound *sound = i->second; alDeleteSources(1, &sound->source_id); delete sound; m_sounds_playing.erase(id); } /* If buffer does not exist, consult the fetcher */ SoundBuffer* getFetchBuffer(const std::string &name) { SoundBuffer *buf = getBuffer(name); if(buf) return buf; if(!m_fetcher) return NULL; std::set<std::string> paths; std::set<std::string> datas; m_fetcher->fetchSounds(name, paths, datas); for(std::set<std::string>::iterator i = paths.begin(); i != paths.end(); ++i){ loadSoundFile(name, *i); } for(std::set<std::string>::iterator i = datas.begin(); i != datas.end(); ++i){ loadSoundData(name, *i); } return getBuffer(name); } // Remove stopped sounds void maintain() { verbosestream<<"OpenALSoundManager::maintain(): " <<m_sounds_playing.size()<<" playing sounds, " <<m_buffers.size()<<" sound names loaded"<<std::endl; std::set<int> del_list; for(std::unordered_map<int, PlayingSound*>::iterator i = m_sounds_playing.begin(); i != m_sounds_playing.end(); ++i) { int id = i->first; PlayingSound *sound = i->second; // If not playing, remove it { ALint state; alGetSourcei(sound->source_id, AL_SOURCE_STATE, &state); if(state != AL_PLAYING){ del_list.insert(id); } } } if(!del_list.empty()) verbosestream<<"OpenALSoundManager::maintain(): deleting " <<del_list.size()<<" playing sounds"<<std::endl; for(std::set<int>::iterator i = del_list.begin(); i != del_list.end(); ++i) { deleteSound(*i); } } /* Interface */ bool loadSoundFile(const std::string &name, const std::string &filepath) { SoundBuffer *buf = load_ogg_from_file(filepath); if (buf) addBuffer(name, buf); return false; } bool loadSoundData(const std::string &name, const std::string &filedata) { SoundBuffer *buf = load_ogg_from_buffer(filedata, name); if (buf) addBuffer(name, buf); return false; } void updateListener(v3f pos, v3f vel, v3f at, v3f up) { m_listener_pos = pos; alListener3f(AL_POSITION, pos.X, pos.Y, pos.Z); alListener3f(AL_VELOCITY, vel.X, vel.Y, vel.Z); ALfloat f[6]; f3_set(f, at); f3_set(f+3, -up); alListenerfv(AL_ORIENTATION, f); warn_if_error(alGetError(), "updateListener"); } void setListenerGain(float gain) { alListenerf(AL_GAIN, gain); } int playSound(const std::string &name, bool loop, float volume, float fade) { maintain(); if(name == "") return 0; SoundBuffer *buf = getFetchBuffer(name); if(!buf){ infostream<<"OpenALSoundManager: \""<<name<<"\" not found." <<std::endl; return -1; } int handle = -1; if (fade > 0) { handle = playSoundRaw(buf, loop, 0); fadeSound(handle, fade, volume); } else { handle = playSoundRaw(buf, loop, volume); } return handle; } int playSoundAt(const std::string &name, bool loop, float volume, v3f pos) { maintain(); if(name == "") return 0; SoundBuffer *buf = getFetchBuffer(name); if(!buf){ infostream<<"OpenALSoundManager: \""<<name<<"\" not found." <<std::endl; return -1; } return playSoundRawAt(buf, loop, volume, pos); } void stopSound(int sound) { maintain(); deleteSound(sound); } void fadeSound(int soundid, float step, float gain) { m_sounds_fading[soundid] = FadeState(step, getSoundGain(soundid), gain); } void doFades(float dtime) { m_fade_delay += dtime; if (m_fade_delay < 0.1f) return; float chkGain = 0; for (std::unordered_map<int, FadeState>::iterator i = m_sounds_fading.begin(); i != m_sounds_fading.end();) { if (i->second.step < 0.f) chkGain = -(i->second.current_gain); else chkGain = i->second.current_gain; if (chkGain < i->second.target_gain) { i->second.current_gain += (i->second.step * m_fade_delay); i->second.current_gain = rangelim(i->second.current_gain, 0, 1); updateSoundGain(i->first, i->second.current_gain); ++i; } else { if (i->second.target_gain <= 0.f) stopSound(i->first); m_sounds_fading.erase(i++); } } m_fade_delay = 0; } bool soundExists(int sound) { maintain(); return (m_sounds_playing.count(sound) != 0); } void updateSoundPosition(int id, v3f pos) { std::unordered_map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id); if (i == m_sounds_playing.end()) return; PlayingSound *sound = i->second; alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false); alSource3f(sound->source_id, AL_POSITION, pos.X, pos.Y, pos.Z); alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0); } bool updateSoundGain(int id, float gain) { std::unordered_map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id); if (i == m_sounds_playing.end()) return false; PlayingSound *sound = i->second; alSourcef(sound->source_id, AL_GAIN, gain); return true; } float getSoundGain(int id) { std::unordered_map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id); if (i == m_sounds_playing.end()) return 0; PlayingSound *sound = i->second; ALfloat gain; alGetSourcef(sound->source_id, AL_GAIN, &gain); return gain; } }; ISoundManager *createOpenALSoundManager(OnDemandSoundFetcher *fetcher) { OpenALSoundManager *m = new OpenALSoundManager(fetcher); if(m->m_is_initialized) return m; delete m; return NULL; };