diff --git a/src/environment.cpp b/src/environment.cpp index 902e2bda4..413bc7ff1 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -50,6 +50,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:" +// A number that is much smaller than the timeout for particle spawners should/could ever be +#define PARTICLE_SPAWNER_NO_EXPIRY -1024.f + Environment::Environment(): m_time_of_day_speed(0), m_time_of_day(9000), @@ -1544,6 +1547,49 @@ void ServerEnvironment::step(float dtime) */ removeRemovedObjects(); } + + /* + Manage particle spawner expiration + */ + if (m_particle_management_interval.step(dtime, 1.0)) { + for (std::map::iterator i = m_particle_spawners.begin(); + i != m_particle_spawners.end(); ) { + //non expiring spawners + if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) { + ++i; + continue; + } + + i->second -= 1.0f; + if (i->second <= 0.f) + m_particle_spawners.erase(i++); + else + ++i; + } + } +} + +u32 ServerEnvironment::addParticleSpawner(float exptime) +{ + // Timers with lifetime 0 do not expire + float time = exptime > 0.f ? exptime : PARTICLE_SPAWNER_NO_EXPIRY; + + u32 id = 0; + for (;;) { // look for unused particlespawner id + id++; + std::map::iterator f; + f = m_particle_spawners.find(id); + if (f == m_particle_spawners.end()) { + m_particle_spawners[id] = time; + break; + } + } + return id; +} + +void ServerEnvironment::deleteParticleSpawner(u32 id) +{ + m_particle_spawners.erase(id); } ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) diff --git a/src/environment.h b/src/environment.h index 660c6f1bc..c6786faed 100644 --- a/src/environment.h +++ b/src/environment.h @@ -337,6 +337,9 @@ public: // env_meta.txt doesn't exist (e.g. new world) void loadDefaultMeta(); + u32 addParticleSpawner(float exptime); + void deleteParticleSpawner(u32 id); + /* External ActiveObject interface ------------------------------------------- @@ -516,6 +519,10 @@ private: // Estimate for general maximum lag as determined by server. // Can raise to high values like 15s with eg. map generation mods. float m_max_lag_estimate; + + // Particles + IntervalLimiter m_particle_management_interval; + std::map m_particle_spawners; }; #ifndef SERVER diff --git a/src/server.cpp b/src/server.cpp index 6c008a2a1..0aba2796c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3194,19 +3194,7 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime, peer_id = player->peer_id; } - u32 id = 0; - for(;;) // look for unused particlespawner id - { - id++; - if (std::find(m_particlespawner_ids.begin(), - m_particlespawner_ids.end(), id) - == m_particlespawner_ids.end()) - { - m_particlespawner_ids.push_back(id); - break; - } - } - + u32 id = m_env->addParticleSpawner(spawntime); SendAddParticleSpawner(peer_id, amount, spawntime, minpos, maxpos, minvel, maxvel, minacc, maxacc, minexptime, maxexptime, minsize, maxsize, @@ -3229,13 +3217,16 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id) peer_id = player->peer_id; } - m_particlespawner_ids.erase( - std::remove(m_particlespawner_ids.begin(), - m_particlespawner_ids.end(), id), - m_particlespawner_ids.end()); + m_env->deleteParticleSpawner(id); SendDeleteParticleSpawner(peer_id, id); } +void Server::deleteParticleSpawnerAll(u32 id) +{ + m_env->deleteParticleSpawner(id); + SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id); +} + Inventory* Server::createDetachedInventory(const std::string &name) { if(m_detached_inventories.count(name) > 0){ diff --git a/src/server.h b/src/server.h index fd559ba14..daf51dee1 100644 --- a/src/server.h +++ b/src/server.h @@ -287,6 +287,7 @@ public: const std::string &playername); void deleteParticleSpawner(const std::string &playername, u32 id); + void deleteParticleSpawnerAll(u32 id); // Creates or resets inventory Inventory* createDetachedInventory(const std::string &name); @@ -662,11 +663,6 @@ private: // key = name std::map m_detached_inventories; - /* - Particles - */ - std::vector m_particlespawner_ids; - DISABLE_CLASS_COPY(Server); };