Cleanup of particle & particlespawner structures and code (#9893)
authorsfan5 <sfan5@live.de>
Fri, 22 May 2020 11:23:25 +0000 (13:23 +0200)
committerGitHub <noreply@github.com>
Fri, 22 May 2020 11:23:25 +0000 (13:23 +0200)
src/CMakeLists.txt
src/client/clientevent.h
src/client/particles.cpp
src/client/particles.h
src/network/clientpackethandler.cpp
src/particles.cpp [new file with mode: 0644]
src/particles.h [new file with mode: 0644]
src/script/lua_api/l_particles.cpp
src/script/lua_api/l_particles_local.cpp
src/server.cpp
src/server.h

index dd68ceec9d759e07b6832815103de3e56ef79d64..3d6d1b0ea7274f1e5ebf9d6c06a0b61ad877a02a 100644 (file)
@@ -427,6 +427,7 @@ set(common_SRCS
        noise.cpp
        objdef.cpp
        object_properties.cpp
+       particles.cpp
        pathfinder.cpp
        player.cpp
        porting.cpp
index 7f3984b03ff5c1bdb9738bc88b91ae2a57282987..9bd31efce0eaaa7ac2aff53c88f16fa887935175 100644 (file)
@@ -21,8 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include <string>
 #include "irrlichttypes_bloated.h"
-#include "hud.h"
-#include "skyparams.h"
+
+struct ParticleParameters;
+struct ParticleSpawnerParameters;
+struct SkyboxParams;
+struct SunParams;
+struct MoonParams;
+struct StarParams;
 
 enum ClientEventType : u8
 {
@@ -77,44 +82,12 @@ struct ClientEvent
                } show_formspec;
                // struct{
                //} textures_updated;
+               ParticleParameters *spawn_particle;
                struct
                {
-                       v3f *pos;
-                       v3f *vel;
-                       v3f *acc;
-                       f32 expirationtime;
-                       f32 size;
-                       bool collisiondetection;
-                       bool collision_removal;
-                       bool object_collision;
-                       bool vertical;
-                       std::string *texture;
-                       struct TileAnimationParams animation;
-                       u8 glow;
-               } spawn_particle;
-               struct
-               {
-                       u16 amount;
-                       f32 spawntime;
-                       v3f *minpos;
-                       v3f *maxpos;
-                       v3f *minvel;
-                       v3f *maxvel;
-                       v3f *minacc;
-                       v3f *maxacc;
-                       f32 minexptime;
-                       f32 maxexptime;
-                       f32 minsize;
-                       f32 maxsize;
-                       bool collisiondetection;
-                       bool collision_removal;
-                       bool object_collision;
+                       ParticleSpawnerParameters *p;
                        u16 attached_id;
-                       bool vertical;
-                       std::string *texture;
                        u64 id;
-                       struct TileAnimationParams animation;
-                       u8 glow;
                } add_particlespawner;
                struct
                {
index a0e4e54eb397cbb4972ecf45a1bbe8046cacec08..c2e751b4fddf290d513c7cf63688dc0c341af646 100644 (file)
@@ -37,32 +37,31 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        Utility
 */
 
-v3f random_v3f(v3f min, v3f max)
+static f32 random_f32(f32 min, f32 max)
+{
+       return rand() / (float)RAND_MAX * (max - min) + min;
+}
+
+static v3f random_v3f(v3f min, v3f max)
 {
        return v3f(
-               rand() / (float)RAND_MAX * (max.X - min.X) + min.X,
-               rand() / (float)RAND_MAX * (max.Y - min.Y) + min.Y,
-               rand() / (float)RAND_MAX * (max.Z - min.Z) + min.Z);
+               random_f32(min.X, max.X),
+               random_f32(min.Y, max.Y),
+               random_f32(min.Z, max.Z));
 }
 
+/*
+       Particle
+*/
+
 Particle::Particle(
        IGameDef *gamedef,
        LocalPlayer *player,
        ClientEnvironment *env,
-       v3f pos,
-       v3f velocity,
-       v3f acceleration,
-       float expirationtime,
-       float size,
-       bool collisiondetection,
-       bool collision_removal,
-       bool object_collision,
-       bool vertical,
+       const ParticleParameters &p,
        video::ITexture *texture,
        v2f texpos,
        v2f texsize,
-       const struct TileAnimationParams &anim,
-       u8 glow,
        video::SColor color
 ):
        scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
@@ -81,33 +80,28 @@ Particle::Particle(
        m_material.setTexture(0, texture);
        m_texpos = texpos;
        m_texsize = texsize;
-       m_animation = anim;
+       m_animation = p.animation;
 
        // Color
        m_base_color = color;
        m_color = color;
 
        // Particle related
-       m_pos = pos;
-       m_velocity = velocity;
-       m_acceleration = acceleration;
-       m_expiration = expirationtime;
+       m_pos = p.pos;
+       m_velocity = p.vel;
+       m_acceleration = p.acc;
+       m_expiration = p.expirationtime;
        m_player = player;
-       m_size = size;
-       m_collisiondetection = collisiondetection;
-       m_collision_removal = collision_removal;
-       m_object_collision = object_collision;
-       m_vertical = vertical;
-       m_glow = glow;
+       m_size = p.size;
+       m_collisiondetection = p.collisiondetection;
+       m_collision_removal = p.collision_removal;
+       m_object_collision = p.object_collision;
+       m_vertical = p.vertical;
+       m_glow = p.glow;
 
        // Irrlicht stuff
-       m_collisionbox = aabb3f(
-               -size / 2,
-               -size / 2,
-               -size / 2,
-                size / 2,
-                size / 2,
-                size / 2);
+       const float c = p.size / 2;
+       m_collisionbox = aabb3f(-c, -c, -c, c, c, c);
        this->setAutomaticCulling(scene::EAC_OFF);
 
        // Init lighting
@@ -255,52 +249,22 @@ void Particle::updateVertices()
 ParticleSpawner::ParticleSpawner(
        IGameDef *gamedef,
        LocalPlayer *player,
-       u16 amount,
-       float time,
-       v3f minpos, v3f maxpos,
-       v3f minvel, v3f maxvel,
-       v3f minacc, v3f maxacc,
-       float minexptime, float maxexptime,
-       float minsize, float maxsize,
-       bool collisiondetection,
-       bool collision_removal,
-       bool object_collision,
+       const ParticleSpawnerParameters &p,
        u16 attached_id,
-       bool vertical,
        video::ITexture *texture,
-       const struct TileAnimationParams &anim,
-       u8 glow,
        ParticleManager *p_manager
 ):
-       m_particlemanager(p_manager)
+       m_particlemanager(p_manager), p(p)
 {
        m_gamedef = gamedef;
        m_player = player;
-       m_amount = amount;
-       m_spawntime = time;
-       m_minpos = minpos;
-       m_maxpos = maxpos;
-       m_minvel = minvel;
-       m_maxvel = maxvel;
-       m_minacc = minacc;
-       m_maxacc = maxacc;
-       m_minexptime = minexptime;
-       m_maxexptime = maxexptime;
-       m_minsize = minsize;
-       m_maxsize = maxsize;
-       m_collisiondetection = collisiondetection;
-       m_collision_removal = collision_removal;
-       m_object_collision = object_collision;
        m_attached_id = attached_id;
-       m_vertical = vertical;
        m_texture = texture;
        m_time = 0;
-       m_animation = anim;
-       m_glow = glow;
 
-       for (u16 i = 0; i <= m_amount; i++)
-       {
-               float spawntime = (float)rand() / (float)RAND_MAX * m_spawntime;
+       m_spawntimes.reserve(p.amount + 1);
+       for (u16 i = 0; i <= p.amount; i++) {
+               float spawntime = rand() / (float)RAND_MAX * p.time;
                m_spawntimes.push_back(spawntime);
        }
 }
@@ -309,7 +273,7 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
        const core::matrix4 *attached_absolute_pos_rot_matrix)
 {
        v3f ppos = m_player->getPosition() / BS;
-       v3f pos = random_v3f(m_minpos, m_maxpos);
+       v3f pos = random_v3f(p.minpos, p.maxpos);
 
        // Need to apply this first or the following check
        // will be wrong for attached spawners
@@ -326,41 +290,32 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
        if (pos.getDistanceFrom(ppos) > radius)
                return;
 
-       v3f vel = random_v3f(m_minvel, m_maxvel);
-       v3f acc = random_v3f(m_minacc, m_maxacc);
+       // Parameters for the single particle we're about to spawn
+       ParticleParameters pp;
+       pp.pos = pos;
+
+       pp.vel = random_v3f(p.minvel, p.maxvel);
+       pp.acc = random_v3f(p.minacc, p.maxacc);
 
        if (attached_absolute_pos_rot_matrix) {
                // Apply attachment rotation
-               attached_absolute_pos_rot_matrix->rotateVect(vel);
-               attached_absolute_pos_rot_matrix->rotateVect(acc);
+               attached_absolute_pos_rot_matrix->rotateVect(pp.vel);
+               attached_absolute_pos_rot_matrix->rotateVect(pp.acc);
        }
 
-       float exptime = rand() / (float)RAND_MAX
-               * (m_maxexptime - m_minexptime)
-               + m_minexptime;
+       pp.expirationtime = random_f32(p.minexptime, p.maxexptime);
+       pp.size = random_f32(p.minsize, p.maxsize);
 
-       float size = rand() / (float)RAND_MAX
-               * (m_maxsize - m_minsize)
-               + m_minsize;
+       p.copyCommon(pp);
 
        m_particlemanager->addParticle(new Particle(
                m_gamedef,
                m_player,
                env,
-               pos,
-               vel,
-               acc,
-               exptime,
-               size,
-               m_collisiondetection,
-               m_collision_removal,
-               m_object_collision,
-               m_vertical,
+               pp,
                m_texture,
                v2f(0.0, 0.0),
-               v2f(1.0, 1.0),
-               m_animation,
-               m_glow
+               v2f(1.0, 1.0)
        ));
 }
 
@@ -381,12 +336,11 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
                }
        }
 
-       if (m_spawntime != 0) {
+       if (p.time != 0) {
                // Spawner exists for a predefined timespan
-               for (std::vector<float>::iterator i = m_spawntimes.begin();
-                               i != m_spawntimes.end();) {
-                       if ((*i) <= m_time && m_amount > 0) {
-                               --m_amount;
+               for (auto i = m_spawntimes.begin(); i != m_spawntimes.end(); ) {
+                       if ((*i) <= m_time && p.amount > 0) {
+                               --p.amount;
 
                                // Pretend to, but don't actually spawn a particle if it is
                                // attached to an unloaded object or distant from player.
@@ -405,13 +359,16 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
                if (unloaded)
                        return;
 
-               for (int i = 0; i <= m_amount; i++) {
+               for (int i = 0; i <= p.amount; i++) {
                        if (rand() / (float)RAND_MAX < dtime)
                                spawnParticle(env, radius, attached_absolute_pos_rot_matrix);
                }
        }
 }
 
+/*
+       ParticleManager
+*/
 
 ParticleManager::ParticleManager(ClientEnvironment *env) :
        m_env(env)
@@ -479,99 +436,84 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
 {
        switch (event->type) {
                case CE_DELETE_PARTICLESPAWNER: {
-                       MutexAutoLock lock(m_spawner_list_lock);
-                       if (m_particle_spawners.find(event->delete_particlespawner.id) !=
-                                       m_particle_spawners.end()) {
-                               delete m_particle_spawners.find(event->delete_particlespawner.id)->second;
-                               m_particle_spawners.erase(event->delete_particlespawner.id);
-                       }
+                       deleteParticleSpawner(event->delete_particlespawner.id);
                        // no allocated memory in delete event
                        break;
                }
                case CE_ADD_PARTICLESPAWNER: {
-                       {
-                               MutexAutoLock lock(m_spawner_list_lock);
-                               if (m_particle_spawners.find(event->add_particlespawner.id) !=
-                                               m_particle_spawners.end()) {
-                                       delete m_particle_spawners.find(event->add_particlespawner.id)->second;
-                                       m_particle_spawners.erase(event->add_particlespawner.id);
-                               }
-                       }
+                       deleteParticleSpawner(event->add_particlespawner.id);
+
+                       const ParticleSpawnerParameters &p = *event->add_particlespawner.p;
 
                        video::ITexture *texture =
-                               client->tsrc()->getTextureForMesh(*(event->add_particlespawner.texture));
+                               client->tsrc()->getTextureForMesh(p.texture);
 
                        auto toadd = new ParticleSpawner(client, player,
-                                       event->add_particlespawner.amount,
-                                       event->add_particlespawner.spawntime,
-                                       *event->add_particlespawner.minpos,
-                                       *event->add_particlespawner.maxpos,
-                                       *event->add_particlespawner.minvel,
-                                       *event->add_particlespawner.maxvel,
-                                       *event->add_particlespawner.minacc,
-                                       *event->add_particlespawner.maxacc,
-                                       event->add_particlespawner.minexptime,
-                                       event->add_particlespawner.maxexptime,
-                                       event->add_particlespawner.minsize,
-                                       event->add_particlespawner.maxsize,
-                                       event->add_particlespawner.collisiondetection,
-                                       event->add_particlespawner.collision_removal,
-                                       event->add_particlespawner.object_collision,
+                                       p,
                                        event->add_particlespawner.attached_id,
-                                       event->add_particlespawner.vertical,
                                        texture,
-                                       event->add_particlespawner.animation,
-                                       event->add_particlespawner.glow,
                                        this);
 
-                       /* delete allocated content of event */
-                       delete event->add_particlespawner.minpos;
-                       delete event->add_particlespawner.maxpos;
-                       delete event->add_particlespawner.minvel;
-                       delete event->add_particlespawner.maxvel;
-                       delete event->add_particlespawner.minacc;
-                       delete event->add_particlespawner.texture;
-                       delete event->add_particlespawner.maxacc;
-
-                       {
-                               MutexAutoLock lock(m_spawner_list_lock);
-                               m_particle_spawners[event->add_particlespawner.id] = toadd;
-                       }
+                       addParticleSpawner(event->add_particlespawner.id, toadd);
+
+                       delete event->add_particlespawner.p;
                        break;
                }
                case CE_SPAWN_PARTICLE: {
+                       const ParticleParameters &p = *event->spawn_particle;
                        video::ITexture *texture =
-                               client->tsrc()->getTextureForMesh(*(event->spawn_particle.texture));
+                               client->tsrc()->getTextureForMesh(p.texture);
 
                        Particle *toadd = new Particle(client, player, m_env,
-                                       *event->spawn_particle.pos,
-                                       *event->spawn_particle.vel,
-                                       *event->spawn_particle.acc,
-                                       event->spawn_particle.expirationtime,
-                                       event->spawn_particle.size,
-                                       event->spawn_particle.collisiondetection,
-                                       event->spawn_particle.collision_removal,
-                                       event->spawn_particle.object_collision,
-                                       event->spawn_particle.vertical,
+                                       p,
                                        texture,
                                        v2f(0.0, 0.0),
-                                       v2f(1.0, 1.0),
-                                       event->spawn_particle.animation,
-                                       event->spawn_particle.glow);
+                                       v2f(1.0, 1.0));
 
                        addParticle(toadd);
 
-                       delete event->spawn_particle.pos;
-                       delete event->spawn_particle.vel;
-                       delete event->spawn_particle.acc;
-                       delete event->spawn_particle.texture;
-
+                       delete event->spawn_particle;
                        break;
                }
                default: break;
        }
 }
 
+bool ParticleManager::getNodeParticleParams(const MapNode &n,
+       const ContentFeatures &f, ParticleParameters &p,
+       video::ITexture **texture, v2f &texpos, v2f &texsize, video::SColor *color)
+{
+       // No particles for "airlike" nodes
+       if (f.drawtype == NDT_AIRLIKE)
+               return false;
+
+       // Texture
+       u8 texid = rand() % 6;
+       const TileLayer &tile = f.tiles[texid].layers[0];
+       p.animation.type = TAT_NONE;
+
+       // Only use first frame of animated texture
+       if (tile.material_flags & MATERIAL_FLAG_ANIMATION)
+               *texture = (*tile.frames)[0].texture;
+       else
+               *texture = tile.texture;
+
+       float size = (rand() % 8) / 64.0f;
+       p.size = BS * size;
+       if (tile.scale)
+               size /= tile.scale;
+       texsize = v2f(size * 2.0f, size * 2.0f);
+       texpos.X = (rand() % 64) / 64.0f - texsize.X;
+       texpos.Y = (rand() % 64) / 64.0f - texsize.Y;
+
+       if (tile.has_color)
+               *color = tile.color;
+       else
+               n.getColor(f, color);
+
+       return true;
+}
+
 // The final burst of particles when a node is finally dug, *not* particles
 // spawned during the digging of a node.
 
@@ -593,73 +535,41 @@ void ParticleManager::addDiggingParticles(IGameDef *gamedef,
 void ParticleManager::addNodeParticle(IGameDef *gamedef,
        LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f)
 {
-       // No particles for "airlike" nodes
-       if (f.drawtype == NDT_AIRLIKE)
-               return;
-
-       // Texture
-       u8 texid = myrand_range(0, 5);
-       const TileLayer &tile = f.tiles[texid].layers[0];
+       ParticleParameters p;
        video::ITexture *texture;
-       struct TileAnimationParams anim;
-       anim.type = TAT_NONE;
+       v2f texpos, texsize;
+       video::SColor color;
 
-       // Only use first frame of animated texture
-       if (tile.material_flags & MATERIAL_FLAG_ANIMATION)
-               texture = (*tile.frames)[0].texture;
-       else
-               texture = tile.texture;
+       if (!getNodeParticleParams(n, f, p, &texture, texpos, texsize, &color))
+               return;
 
-       float size = (rand() % 8) / 64.0f;
-       float visual_size = BS * size;
-       if (tile.scale)
-               size /= tile.scale;
-       v2f texsize(size * 2.0f, size * 2.0f);
-       v2f texpos;
-       texpos.X = (rand() % 64) / 64.0f - texsize.X;
-       texpos.Y = (rand() % 64) / 64.0f - texsize.Y;
+       p.expirationtime = (rand() % 100) / 100.0f;
 
        // Physics
-       v3f velocity(
+       p.vel = v3f(
                (rand() % 150) / 50.0f - 1.5f,
                (rand() % 150) / 50.0f,
                (rand() % 150) / 50.0f - 1.5f
        );
-       v3f acceleration(
+       p.acc = v3f(
                0.0f,
                -player->movement_gravity * player->physics_override_gravity / BS,
                0.0f
        );
-       v3f particlepos = v3f(
+       p.pos = v3f(
                (f32)pos.X + (rand() % 100) / 200.0f - 0.25f,
                (f32)pos.Y + (rand() % 100) / 200.0f - 0.25f,
                (f32)pos.Z + (rand() % 100) / 200.0f - 0.25f
        );
 
-       video::SColor color;
-       if (tile.has_color)
-               color = tile.color;
-       else
-               n.getColor(f, &color);
-
        Particle *toadd = new Particle(
                gamedef,
                player,
                m_env,
-               particlepos,
-               velocity,
-               acceleration,
-               (rand() % 100) / 100.0f, // expiration time
-               visual_size,
-               true,
-               false,
-               false,
-               false,
+               p,
                texture,
                texpos,
                texsize,
-               anim,
-               0,
                color);
 
        addParticle(toadd);
@@ -670,3 +580,20 @@ void ParticleManager::addParticle(Particle *toadd)
        MutexAutoLock lock(m_particle_list_lock);
        m_particles.push_back(toadd);
 }
+
+
+void ParticleManager::addParticleSpawner(u64 id, ParticleSpawner *toadd)
+{
+       MutexAutoLock lock(m_spawner_list_lock);
+       m_particle_spawners[id] = toadd;
+}
+
+void ParticleManager::deleteParticleSpawner(u64 id)
+{
+       MutexAutoLock lock(m_spawner_list_lock);
+       auto it = m_particle_spawners.find(id);
+       if (it != m_particle_spawners.end()) {
+               delete it->second;
+               m_particle_spawners.erase(it);
+       }
+}
index e7b8cbe24896a6f66cb3ceec28217d89bd2fd203..7dda0e1b15b6d37e04db941bbfc6c8da64b9fda9 100644 (file)
@@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irrlichttypes_extrabloated.h"
 #include "client/tile.h"
 #include "localplayer.h"
-#include "tileanimation.h"
+#include "../particles.h"
 
 struct ClientEvent;
 class ParticleManager;
@@ -38,20 +38,10 @@ class Particle : public scene::ISceneNode
                IGameDef* gamedef,
                LocalPlayer *player,
                ClientEnvironment *env,
-               v3f pos,
-               v3f velocity,
-               v3f acceleration,
-               float expirationtime,
-               float size,
-               bool collisiondetection,
-               bool collision_removal,
-               bool object_collision,
-               bool vertical,
+               const ParticleParameters &p,
                video::ITexture *texture,
                v2f texpos,
                v2f texsize,
-               const struct TileAnimationParams &anim,
-               u8 glow,
                video::SColor color = video::SColor(0xFFFFFFFF)
        );
        ~Particle() = default;
@@ -119,20 +109,9 @@ class ParticleSpawner
 public:
        ParticleSpawner(IGameDef* gamedef,
                LocalPlayer *player,
-               u16 amount,
-               float time,
-               v3f minp, v3f maxp,
-               v3f minvel, v3f maxvel,
-               v3f minacc, v3f maxacc,
-               float minexptime, float maxexptime,
-               float minsize, float maxsize,
-               bool collisiondetection,
-               bool collision_removal,
-               bool object_collision,
+               const ParticleSpawnerParameters &p,
                u16 attached_id,
-               bool vertical,
                video::ITexture *texture,
-               const struct TileAnimationParams &anim, u8 glow,
                ParticleManager* p_manager);
 
        ~ParticleSpawner() = default;
@@ -140,7 +119,7 @@ public:
        void step(float dtime, ClientEnvironment *env);
 
        bool get_expired ()
-       { return (m_amount <= 0) && m_spawntime != 0; }
+       { return p.amount <= 0 && p.time != 0; }
 
 private:
        void spawnParticle(ClientEnvironment *env, float radius,
@@ -150,27 +129,10 @@ private:
        float m_time;
        IGameDef *m_gamedef;
        LocalPlayer *m_player;
-       u16 m_amount;
-       float m_spawntime;
-       v3f m_minpos;
-       v3f m_maxpos;
-       v3f m_minvel;
-       v3f m_maxvel;
-       v3f m_minacc;
-       v3f m_maxacc;
-       float m_minexptime;
-       float m_maxexptime;
-       float m_minsize;
-       float m_maxsize;
+       ParticleSpawnerParameters p;
        video::ITexture *m_texture;
        std::vector<float> m_spawntimes;
-       bool m_collisiondetection;
-       bool m_collision_removal;
-       bool m_object_collision;
-       bool m_vertical;
        u16 m_attached_id;
-       struct TileAnimationParams m_animation;
-       u8 m_glow;
 };
 
 /**
@@ -197,8 +159,8 @@ public:
        /**
         * This function is only used by client particle spawners
         *
-        * We don't need to check the particle spawner list because client ID will n
-        * ever overlap (u64)
+        * We don't need to check the particle spawner list because client ID will
+        * never overlap (u64)
         * @return new id
         */
        u64 generateSpawnerId()
@@ -207,9 +169,15 @@ public:
        }
 
 protected:
+       static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
+               ParticleParameters &p, video::ITexture **texture, v2f &texpos,
+               v2f &texsize, video::SColor *color);
+
        void addParticle(Particle* toadd);
 
 private:
+       void addParticleSpawner(u64 id, ParticleSpawner *toadd);
+       void deleteParticleSpawner(u64 id);
 
        void stepParticles(float dtime);
        void stepSpawners(float dtime);
index 7b1b1368cfb87f811b58ae38cd99a9f7ecfa4c4f..054e60c3c84c1084b5ee9d126046061e4a239e65 100644 (file)
@@ -958,114 +958,56 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
        std::string datastring(pkt->getString(0), pkt->getSize());
        std::istringstream is(datastring, std::ios_base::binary);
 
-       v3f pos                 = readV3F32(is);
-       v3f vel                 = readV3F32(is);
-       v3f acc                 = readV3F32(is);
-       float expirationtime    = readF32(is);
-       float size              = readF32(is);
-       bool collisiondetection = readU8(is);
-       std::string texture     = deSerializeLongString(is);
-
-       bool vertical          = false;
-       bool collision_removal = false;
-       TileAnimationParams animation;
-       animation.type         = TAT_NONE;
-       u8 glow                = 0;
-       bool object_collision  = false;
-       try {
-               vertical = readU8(is);
-               collision_removal = readU8(is);
-               animation.deSerialize(is, m_proto_ver);
-               glow = readU8(is);
-               object_collision = readU8(is);
-       } catch (...) {}
+       ParticleParameters p;
+       p.deSerialize(is, m_proto_ver);
 
        ClientEvent *event = new ClientEvent();
-       event->type                              = CE_SPAWN_PARTICLE;
-       event->spawn_particle.pos                = new v3f (pos);
-       event->spawn_particle.vel                = new v3f (vel);
-       event->spawn_particle.acc                = new v3f (acc);
-       event->spawn_particle.expirationtime     = expirationtime;
-       event->spawn_particle.size               = size;
-       event->spawn_particle.collisiondetection = collisiondetection;
-       event->spawn_particle.collision_removal  = collision_removal;
-       event->spawn_particle.object_collision   = object_collision;
-       event->spawn_particle.vertical           = vertical;
-       event->spawn_particle.texture            = new std::string(texture);
-       event->spawn_particle.animation          = animation;
-       event->spawn_particle.glow               = glow;
+       event->type           = CE_SPAWN_PARTICLE;
+       event->spawn_particle = new ParticleParameters(p);
 
        m_client_event_queue.push(event);
 }
 
 void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
 {
-       u16 amount;
-       float spawntime;
-       v3f minpos;
-       v3f maxpos;
-       v3f minvel;
-       v3f maxvel;
-       v3f minacc;
-       v3f maxacc;
-       float minexptime;
-       float maxexptime;
-       float minsize;
-       float maxsize;
-       bool collisiondetection;
-       u32 server_id;
-
-       *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
-               >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
-               >> maxsize >> collisiondetection;
-
-       std::string texture = pkt->readLongString();
-
-       *pkt >> server_id;
-
-       bool vertical          = false;
-       bool collision_removal = false;
-       u16 attached_id        = 0;
-       TileAnimationParams animation;
-       animation.type         = TAT_NONE;
-       u8 glow                = 0;
-       bool object_collision  = false;
-       try {
-               *pkt >> vertical;
-               *pkt >> collision_removal;
-               *pkt >> attached_id;
+       std::string datastring(pkt->getString(0), pkt->getSize());
+       std::istringstream is(datastring, std::ios_base::binary);
 
-               // This is horrible but required (why are there two ways to deserialize pkts?)
-               std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
-               std::istringstream is(datastring, std::ios_base::binary);
-               animation.deSerialize(is, m_proto_ver);
-               glow = readU8(is);
-               object_collision = readU8(is);
-       } catch (...) {}
+       ParticleSpawnerParameters p;
+       u32 server_id;
+       u16 attached_id = 0;
+
+       p.amount             = readU16(is);
+       p.time               = readF32(is);
+       p.minpos             = readV3F32(is);
+       p.maxpos             = readV3F32(is);
+       p.minvel             = readV3F32(is);
+       p.maxvel             = readV3F32(is);
+       p.minacc             = readV3F32(is);
+       p.maxacc             = readV3F32(is);
+       p.minexptime         = readF32(is);
+       p.maxexptime         = readF32(is);
+       p.minsize            = readF32(is);
+       p.maxsize            = readF32(is);
+       p.collisiondetection = readU8(is);
+       p.texture            = deSerializeLongString(is);
+
+       server_id = readU32(is);
+
+       p.vertical = readU8(is);
+       p.collision_removal = readU8(is);
+
+       attached_id = readU16(is);
+
+       p.animation.deSerialize(is, m_proto_ver);
+       p.glow = readU8(is);
+       p.object_collision = readU8(is);
 
        auto event = new ClientEvent();
-       event->type                                   = CE_ADD_PARTICLESPAWNER;
-       event->add_particlespawner.amount             = amount;
-       event->add_particlespawner.spawntime          = spawntime;
-       event->add_particlespawner.minpos             = new v3f (minpos);
-       event->add_particlespawner.maxpos             = new v3f (maxpos);
-       event->add_particlespawner.minvel             = new v3f (minvel);
-       event->add_particlespawner.maxvel             = new v3f (maxvel);
-       event->add_particlespawner.minacc             = new v3f (minacc);
-       event->add_particlespawner.maxacc             = new v3f (maxacc);
-       event->add_particlespawner.minexptime         = minexptime;
-       event->add_particlespawner.maxexptime         = maxexptime;
-       event->add_particlespawner.minsize            = minsize;
-       event->add_particlespawner.maxsize            = maxsize;
-       event->add_particlespawner.collisiondetection = collisiondetection;
-       event->add_particlespawner.collision_removal  = collision_removal;
-       event->add_particlespawner.object_collision   = object_collision;
-       event->add_particlespawner.attached_id        = attached_id;
-       event->add_particlespawner.vertical           = vertical;
-       event->add_particlespawner.texture            = new std::string(texture);
-       event->add_particlespawner.id                 = server_id;
-       event->add_particlespawner.animation          = animation;
-       event->add_particlespawner.glow               = glow;
+       event->type                            = CE_ADD_PARTICLESPAWNER;
+       event->add_particlespawner.p           = new ParticleSpawnerParameters(p);
+       event->add_particlespawner.attached_id = attached_id;
+       event->add_particlespawner.id          = server_id;
 
        m_client_event_queue.push(event);
 }
diff --git a/src/particles.cpp b/src/particles.cpp
new file mode 100644 (file)
index 0000000..711d189
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+Minetest
+Copyright (C) 2020 sfan5 <sfan5@live.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser 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.
+*/
+
+#include "particles.h"
+#include "util/serialize.h"
+
+void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
+{
+       writeV3F32(os, pos);
+       writeV3F32(os, vel);
+       writeV3F32(os, acc);
+       writeF32(os, expirationtime);
+       writeF32(os, size);
+       writeU8(os, collisiondetection);
+       os << serializeLongString(texture);
+       writeU8(os, vertical);
+       writeU8(os, collision_removal);
+       animation.serialize(os, 6); /* NOT the protocol ver */
+       writeU8(os, glow);
+       writeU8(os, object_collision);
+}
+
+void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
+{
+       pos                = readV3F32(is);
+       vel                = readV3F32(is);
+       acc                = readV3F32(is);
+       expirationtime     = readF32(is);
+       size               = readF32(is);
+       collisiondetection = readU8(is);
+       texture            = deSerializeLongString(is);
+       vertical           = readU8(is);
+       collision_removal  = readU8(is);
+       animation.deSerialize(is, 6); /* NOT the protocol ver */
+       glow               = readU8(is);
+       object_collision   = readU8(is);
+}
diff --git a/src/particles.h b/src/particles.h
new file mode 100644 (file)
index 0000000..659c124
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Minetest
+Copyright (C) 2013 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 Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser 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.
+*/
+
+#pragma once
+
+#include <string>
+#include "irrlichttypes_bloated.h"
+#include "tileanimation.h"
+
+// This file defines the particle-related structures that both the server and
+// client need. The ParticleManager and rendering is in client/particles.h
+
+struct CommonParticleParams {
+       bool collisiondetection = false;
+       bool collision_removal = false;
+       bool object_collision = false;
+       bool vertical = false;
+       std::string texture;
+       struct TileAnimationParams animation;
+       u8 glow = 0;
+
+       CommonParticleParams() {
+               animation.type = TAT_NONE;
+       }
+
+       /* This helper is useful for copying params from
+        * ParticleSpawnerParameters to ParticleParameters */
+       inline void copyCommon(CommonParticleParams &to) const {
+               to.collisiondetection = collisiondetection;
+               to.collision_removal = collision_removal;
+               to.object_collision = object_collision;
+               to.vertical = vertical;
+               to.texture = texture;
+               to.animation = animation;
+               to.glow = glow;
+       }
+};
+
+struct ParticleParameters : CommonParticleParams {
+       v3f pos;
+       v3f vel;
+       v3f acc;
+       f32 expirationtime = 1;
+       f32 size = 1;
+
+       void serialize(std::ostream &os, u16 protocol_ver) const;
+       void deSerialize(std::istream &is, u16 protocol_ver);
+};
+
+struct ParticleSpawnerParameters : CommonParticleParams {
+       u16 amount = 1;
+       v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
+       f32 time = 1;
+       f32 minexptime = 1, maxexptime = 1, minsize = 1, maxsize = 1;
+
+       // For historical reasons no (de-)serialization methods here
+};
index 340903ebf69b69d26f0d0213d4be497858a6b829..7680aa17bd77b5dc67c94f0da0d929f94f6080ac 100644 (file)
@@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "common/c_converter.h"
 #include "common/c_content.h"
 #include "server.h"
-#include "client/particles.h"
+#include "particles.h"
 
 // add_particle({pos=, velocity=, acceleration=, expirationtime=,
 //     size=, collisiondetection=, collision_removal=, object_collision=,
@@ -40,85 +40,81 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 // glow = num
 int ModApiParticles::l_add_particle(lua_State *L)
 {
-       MAP_LOCK_REQUIRED;
+       NO_MAP_LOCK_REQUIRED;
 
        // Get parameters
-       v3f pos, vel, acc;
-       float expirationtime, size;
-       expirationtime = size = 1;
-       bool collisiondetection, vertical, collision_removal, object_collision;
-       collisiondetection = vertical = collision_removal = object_collision = false;
-       struct TileAnimationParams animation;
-       animation.type = TAT_NONE;
-       std::string texture;
+       struct ParticleParameters p;
        std::string playername;
-       u8 glow = 0;
 
        if (lua_gettop(L) > 1) // deprecated
        {
-               log_deprecated(L, "Deprecated add_particle call with individual parameters instead of definition");
-               pos = check_v3f(L, 1);
-               vel = check_v3f(L, 2);
-               acc = check_v3f(L, 3);
-               expirationtime = luaL_checknumber(L, 4);
-               size = luaL_checknumber(L, 5);
-               collisiondetection = readParam<bool>(L, 6);
-               texture = luaL_checkstring(L, 7);
+               log_deprecated(L, "Deprecated add_particle call with "
+                       "individual parameters instead of definition");
+               p.pos = check_v3f(L, 1);
+               p.vel = check_v3f(L, 2);
+               p.acc = check_v3f(L, 3);
+               p.expirationtime = luaL_checknumber(L, 4);
+               p.size = luaL_checknumber(L, 5);
+               p.collisiondetection = readParam<bool>(L, 6);
+               p.texture = luaL_checkstring(L, 7);
                if (lua_gettop(L) == 8) // only spawn for a single player
                        playername = luaL_checkstring(L, 8);
        }
        else if (lua_istable(L, 1))
        {
                lua_getfield(L, 1, "pos");
-               pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f();
+               if (lua_istable(L, -1))
+                       p.pos = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "vel");
                if (lua_istable(L, -1)) {
-                       vel = check_v3f(L, -1);
+                       p.vel = check_v3f(L, -1);
                        log_deprecated(L, "The use of vel is deprecated. "
                                "Use velocity instead");
                }
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "velocity");
-               vel = lua_istable(L, -1) ? check_v3f(L, -1) : vel;
+               if (lua_istable(L, -1))
+                       p.vel = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "acc");
                if (lua_istable(L, -1)) {
-                       acc = check_v3f(L, -1);
+                       p.acc = check_v3f(L, -1);
                        log_deprecated(L, "The use of acc is deprecated. "
                                "Use acceleration instead");
                }
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "acceleration");
-               acc = lua_istable(L, -1) ? check_v3f(L, -1) : acc;
+               if (lua_istable(L, -1))
+                       p.acc = check_v3f(L, -1);
                lua_pop(L, 1);
 
-               expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
-               size = getfloatfield_default(L, 1, "size", 1);
-               collisiondetection = getboolfield_default(L, 1,
-                       "collisiondetection", collisiondetection);
-               collision_removal = getboolfield_default(L, 1,
-                       "collision_removal", collision_removal);
-               object_collision = getboolfield_default(L, 1,
-                       "object_collision", object_collision);
-               vertical = getboolfield_default(L, 1, "vertical", vertical);
+               p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
+                       p.expirationtime);
+               p.size = getfloatfield_default(L, 1, "size", p.size);
+               p.collisiondetection = getboolfield_default(L, 1,
+                       "collisiondetection", p.collisiondetection);
+               p.collision_removal = getboolfield_default(L, 1,
+                       "collision_removal", p.collision_removal);
+               p.object_collision = getboolfield_default(L, 1,
+                       "object_collision", p.object_collision);
+               p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
 
                lua_getfield(L, 1, "animation");
-               animation = read_animation_definition(L, -1);
+               p.animation = read_animation_definition(L, -1);
                lua_pop(L, 1);
 
-               texture = getstringfield_default(L, 1, "texture", "");
-               playername = getstringfield_default(L, 1, "playername", "");
+               p.texture = getstringfield_default(L, 1, "texture", p.texture);
+               p.glow = getintfield_default(L, 1, "glow", p.glow);
 
-               glow = getintfield_default(L, 1, "glow", 0);
+               playername = getstringfield_default(L, 1, "playername", "");
        }
-       getServer(L)->spawnParticle(playername, pos, vel, acc, expirationtime, size,
-                       collisiondetection, collision_removal, object_collision, vertical,
-                       texture, animation, glow);
+
+       getServer(L)->spawnParticle(playername, p);
        return 1;
 }
 
@@ -146,84 +142,82 @@ int ModApiParticles::l_add_particle(lua_State *L)
 // glow = num
 int ModApiParticles::l_add_particlespawner(lua_State *L)
 {
-       MAP_LOCK_REQUIRED;
+       NO_MAP_LOCK_REQUIRED;
 
        // Get parameters
-       u16 amount = 1;
-       v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
-       float time, minexptime, maxexptime, minsize, maxsize;
-       time = minexptime = maxexptime = minsize = maxsize = 1;
-       bool collisiondetection, vertical, collision_removal, object_collision;
-       collisiondetection = vertical = collision_removal = object_collision = false;
-       struct TileAnimationParams animation;
-       animation.type = TAT_NONE;
+       ParticleSpawnerParameters p;
        ServerActiveObject *attached = NULL;
-       std::string texture;
        std::string playername;
-       u8 glow = 0;
 
        if (lua_gettop(L) > 1) //deprecated
        {
-               log_deprecated(L,"Deprecated add_particlespawner call with individual parameters instead of definition");
-               amount = luaL_checknumber(L, 1);
-               time = luaL_checknumber(L, 2);
-               minpos = check_v3f(L, 3);
-               maxpos = check_v3f(L, 4);
-               minvel = check_v3f(L, 5);
-               maxvel = check_v3f(L, 6);
-               minacc = check_v3f(L, 7);
-               maxacc = check_v3f(L, 8);
-               minexptime = luaL_checknumber(L, 9);
-               maxexptime = luaL_checknumber(L, 10);
-               minsize = luaL_checknumber(L, 11);
-               maxsize = luaL_checknumber(L, 12);
-               collisiondetection = readParam<bool>(L, 13);
-               texture = luaL_checkstring(L, 14);
+               log_deprecated(L, "Deprecated add_particlespawner call with "
+                       "individual parameters instead of definition");
+               p.amount = luaL_checknumber(L, 1);
+               p.time = luaL_checknumber(L, 2);
+               p.minpos = check_v3f(L, 3);
+               p.maxpos = check_v3f(L, 4);
+               p.minvel = check_v3f(L, 5);
+               p.maxvel = check_v3f(L, 6);
+               p.minacc = check_v3f(L, 7);
+               p.maxacc = check_v3f(L, 8);
+               p.minexptime = luaL_checknumber(L, 9);
+               p.maxexptime = luaL_checknumber(L, 10);
+               p.minsize = luaL_checknumber(L, 11);
+               p.maxsize = luaL_checknumber(L, 12);
+               p.collisiondetection = readParam<bool>(L, 13);
+               p.texture = luaL_checkstring(L, 14);
                if (lua_gettop(L) == 15) // only spawn for a single player
                        playername = luaL_checkstring(L, 15);
        }
        else if (lua_istable(L, 1))
        {
-               amount = getintfield_default(L, 1, "amount", amount);
-               time = getfloatfield_default(L, 1, "time", time);
+               p.amount = getintfield_default(L, 1, "amount", p.amount);
+               p.time = getfloatfield_default(L, 1, "time", p.time);
 
                lua_getfield(L, 1, "minpos");
-               minpos = lua_istable(L, -1) ? check_v3f(L, -1) : minpos;
+               if (lua_istable(L, -1))
+                       p.minpos = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "maxpos");
-               maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : maxpos;
+               if (lua_istable(L, -1))
+                       p.maxpos = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "minvel");
-               minvel = lua_istable(L, -1) ? check_v3f(L, -1) : minvel;
+               if (lua_istable(L, -1))
+                       p.minvel = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "maxvel");
-               maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : maxvel;
+               if (lua_istable(L, -1))
+                       p.maxvel = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "minacc");
-               minacc = lua_istable(L, -1) ? check_v3f(L, -1) : minacc;
+               if (lua_istable(L, -1))
+                       p.minacc = check_v3f(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "maxacc");
-               maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : maxacc;
+               if (lua_istable(L, -1))
+                       p.maxacc = check_v3f(L, -1);
                lua_pop(L, 1);
 
-               minexptime = getfloatfield_default(L, 1, "minexptime", minexptime);
-               maxexptime = getfloatfield_default(L, 1, "maxexptime", maxexptime);
-               minsize = getfloatfield_default(L, 1, "minsize", minsize);
-               maxsize = getfloatfield_default(L, 1, "maxsize", maxsize);
-               collisiondetection = getboolfield_default(L, 1,
-                       "collisiondetection", collisiondetection);
-               collision_removal = getboolfield_default(L, 1,
-                       "collision_removal", collision_removal);
-               object_collision = getboolfield_default(L, 1,
-                       "object_collision", object_collision);
+               p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
+               p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
+               p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
+               p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
+               p.collisiondetection = getboolfield_default(L, 1,
+                       "collisiondetection", p.collisiondetection);
+               p.collision_removal = getboolfield_default(L, 1,
+                       "collision_removal", p.collision_removal);
+               p.object_collision = getboolfield_default(L, 1,
+                       "object_collision", p.object_collision);
 
                lua_getfield(L, 1, "animation");
-               animation = read_animation_definition(L, -1);
+               p.animation = read_animation_definition(L, -1);
                lua_pop(L, 1);
 
                lua_getfield(L, 1, "attached");
@@ -233,25 +227,13 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
                        attached = ObjectRef::getobject(ref);
                }
 
-               vertical = getboolfield_default(L, 1, "vertical", vertical);
-               texture = getstringfield_default(L, 1, "texture", "");
+               p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
+               p.texture = getstringfield_default(L, 1, "texture", p.texture);
                playername = getstringfield_default(L, 1, "playername", "");
-               glow = getintfield_default(L, 1, "glow", 0);
+               p.glow = getintfield_default(L, 1, "glow", p.glow);
        }
 
-       u32 id = getServer(L)->addParticleSpawner(amount, time,
-                       minpos, maxpos,
-                       minvel, maxvel,
-                       minacc, maxacc,
-                       minexptime, maxexptime,
-                       minsize, maxsize,
-                       collisiondetection,
-                       collision_removal,
-                       object_collision,
-                       attached,
-                       vertical,
-                       texture, playername,
-                       animation, glow);
+       u32 id = getServer(L)->addParticleSpawner(p, attached, playername);
        lua_pushnumber(L, id);
 
        return 1;
@@ -261,7 +243,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
 // player (string) is optional
 int ModApiParticles::l_delete_particlespawner(lua_State *L)
 {
-       MAP_LOCK_REQUIRED;
+       NO_MAP_LOCK_REQUIRED;
 
        // Get parameters
        u32 id = luaL_checknumber(L, 1);
index a9bf55665b44c76bfb6ea458cf29af0fb3d7b094..9595b2fab5a4b2f953c09f5320873e655b7691f3 100644 (file)
@@ -32,56 +32,44 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L)
        luaL_checktype(L, 1, LUA_TTABLE);
 
        // Get parameters
-       v3f pos, vel, acc;
-       float expirationtime, size;
-       bool collisiondetection, vertical, collision_removal;
-
-       struct TileAnimationParams animation;
-       animation.type = TAT_NONE;
-
-       std::string texture;
-
-       u8 glow;
+       ParticleParameters p;
 
        lua_getfield(L, 1, "pos");
-       pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.pos = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "velocity");
-       vel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.vel = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "acceleration");
-       acc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.acc = check_v3f(L, -1);
        lua_pop(L, 1);
 
-       expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
-       size = getfloatfield_default(L, 1, "size", 1);
-       collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
-       collision_removal = getboolfield_default(L, 1, "collision_removal", false);
-       vertical = getboolfield_default(L, 1, "vertical", false);
+       p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
+               p.expirationtime);
+       p.size = getfloatfield_default(L, 1, "size", p.size);
+       p.collisiondetection = getboolfield_default(L, 1,
+               "collisiondetection", p.collisiondetection);
+       p.collision_removal = getboolfield_default(L, 1,
+               "collision_removal", p.collision_removal);
+       p.object_collision = getboolfield_default(L, 1,
+               "object_collision", p.object_collision);
+       p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
 
        lua_getfield(L, 1, "animation");
-       animation = read_animation_definition(L, -1);
+       p.animation = read_animation_definition(L, -1);
        lua_pop(L, 1);
 
-       texture = getstringfield_default(L, 1, "texture", "");
-
-       glow = getintfield_default(L, 1, "glow", 0);
+       p.texture = getstringfield_default(L, 1, "texture", p.texture);
+       p.glow = getintfield_default(L, 1, "glow", p.glow);
 
        ClientEvent *event = new ClientEvent();
-       event->type                              = CE_SPAWN_PARTICLE;
-       event->spawn_particle.pos                = new v3f (pos);
-       event->spawn_particle.vel                = new v3f (vel);
-       event->spawn_particle.acc                = new v3f (acc);
-       event->spawn_particle.expirationtime     = expirationtime;
-       event->spawn_particle.size               = size;
-       event->spawn_particle.collisiondetection = collisiondetection;
-       event->spawn_particle.collision_removal  = collision_removal;
-       event->spawn_particle.vertical           = vertical;
-       event->spawn_particle.texture            = new std::string(texture);
-       event->spawn_particle.animation          = animation;
-       event->spawn_particle.glow               = glow;
+       event->type           = CE_SPAWN_PARTICLE;
+       event->spawn_particle = new ParticleParameters(p);
        getClient(L)->pushToEventQueue(event);
 
        return 0;
@@ -90,94 +78,69 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L)
 int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
 {
        luaL_checktype(L, 1, LUA_TTABLE);
-       // Get parameters
-       u16 amount;
-       v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
-       float time, minexptime, maxexptime, minsize, maxsize;
-       bool collisiondetection, vertical, collision_removal;
 
-       struct TileAnimationParams animation;
-       animation.type = TAT_NONE;
-       // TODO: Implement this when there is a way to get an objectref.
-       // ServerActiveObject *attached = NULL;
-       std::string texture;
-       u8 glow;
+       // Get parameters
+       ParticleSpawnerParameters p;
 
-       amount = getintfield_default(L, 1, "amount", 1);
-       time = getfloatfield_default(L, 1, "time", 1);
+       p.amount = getintfield_default(L, 1, "amount", p.amount);
+       p.time = getfloatfield_default(L, 1, "time", p.time);
 
        lua_getfield(L, 1, "minpos");
-       minpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.minpos = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "maxpos");
-       maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.maxpos = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "minvel");
-       minvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.minvel = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "maxvel");
-       maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.maxvel = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "minacc");
-       minacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.minacc = check_v3f(L, -1);
        lua_pop(L, 1);
 
        lua_getfield(L, 1, "maxacc");
-       maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+       if (lua_istable(L, -1))
+               p.maxacc = check_v3f(L, -1);
        lua_pop(L, 1);
 
-       minexptime = getfloatfield_default(L, 1, "minexptime", 1);
-       maxexptime = getfloatfield_default(L, 1, "maxexptime", 1);
-       minsize = getfloatfield_default(L, 1, "minsize", 1);
-       maxsize = getfloatfield_default(L, 1, "maxsize", 1);
-
-       collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
-       collision_removal = getboolfield_default(L, 1, "collision_removal", false);
-       vertical = getboolfield_default(L, 1, "vertical", false);
+       p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
+       p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
+       p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
+       p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
+       p.collisiondetection = getboolfield_default(L, 1,
+               "collisiondetection", p.collisiondetection);
+       p.collision_removal = getboolfield_default(L, 1,
+               "collision_removal", p.collision_removal);
+       p.object_collision = getboolfield_default(L, 1,
+               "object_collision", p.object_collision);
 
        lua_getfield(L, 1, "animation");
-       animation = read_animation_definition(L, -1);
+       p.animation = read_animation_definition(L, -1);
        lua_pop(L, 1);
 
-       // TODO: Implement this when a way to get an objectref on the client is added
-//     lua_getfield(L, 1, "attached");
-//     if (!lua_isnil(L, -1)) {
-//             ObjectRef *ref = ObjectRef::checkobject(L, -1);
-//             lua_pop(L, 1);
-//             attached = ObjectRef::getobject(ref);
-//     }
-
-       texture = getstringfield_default(L, 1, "texture", "");
-       glow = getintfield_default(L, 1, "glow", 0);
+       p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
+       p.texture = getstringfield_default(L, 1, "texture", p.texture);
+       p.glow = getintfield_default(L, 1, "glow", p.glow);
 
        u64 id = getClient(L)->getParticleManager()->generateSpawnerId();
 
        auto event = new ClientEvent();
-       event->type                                   = CE_ADD_PARTICLESPAWNER;
-       event->add_particlespawner.amount             = amount;
-       event->add_particlespawner.spawntime          = time;
-       event->add_particlespawner.minpos             = new v3f (minpos);
-       event->add_particlespawner.maxpos             = new v3f (maxpos);
-       event->add_particlespawner.minvel             = new v3f (minvel);
-       event->add_particlespawner.maxvel             = new v3f (maxvel);
-       event->add_particlespawner.minacc             = new v3f (minacc);
-       event->add_particlespawner.maxacc             = new v3f (maxacc);
-       event->add_particlespawner.minexptime         = minexptime;
-       event->add_particlespawner.maxexptime         = maxexptime;
-       event->add_particlespawner.minsize            = minsize;
-       event->add_particlespawner.maxsize            = maxsize;
-       event->add_particlespawner.collisiondetection = collisiondetection;
-       event->add_particlespawner.collision_removal  = collision_removal;
-       event->add_particlespawner.attached_id        = 0;
-       event->add_particlespawner.vertical           = vertical;
-       event->add_particlespawner.texture            = new std::string(texture);
-       event->add_particlespawner.id                 = id;
-       event->add_particlespawner.animation          = animation;
-       event->add_particlespawner.glow               = glow;
+       event->type                            = CE_ADD_PARTICLESPAWNER;
+       event->add_particlespawner.p           = new ParticleSpawnerParameters(p);
+       event->add_particlespawner.attached_id = 0;
+       event->add_particlespawner.id          = id;
 
        getClient(L)->pushToEventQueue(event);
        lua_pushnumber(L, id);
index 92870f972b9c91aef7d746f570d6f72201a044fe..68b0131d42980368861ccede6c521d7a99e60129 100644 (file)
@@ -1504,17 +1504,15 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms
 
 // Spawns a particle on peer with peer_id
 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
-                               v3f pos, v3f velocity, v3f acceleration,
-                               float expirationtime, float size, bool collisiondetection,
-                               bool collision_removal, bool object_collision,
-                               bool vertical, const std::string &texture,
-                               const struct TileAnimationParams &animation, u8 glow)
+       const ParticleParameters &p)
 {
        static thread_local const float radius =
                        g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
 
        if (peer_id == PEER_ID_INEXISTENT) {
                std::vector<session_t> clients = m_clients.getClientIDs();
+               const v3f pos = p.pos * BS;
+               const float radius_sq = radius * radius;
 
                for (const session_t client_id : clients) {
                        RemotePlayer *player = m_env->getPlayer(client_id);
@@ -1526,76 +1524,59 @@ void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
                                continue;
 
                        // Do not send to distant clients
-                       if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
+                       if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
                                continue;
 
-                       SendSpawnParticle(client_id, player->protocol_version,
-                                       pos, velocity, acceleration,
-                                       expirationtime, size, collisiondetection, collision_removal,
-                                       object_collision, vertical, texture, animation, glow);
+                       SendSpawnParticle(client_id, player->protocol_version, p);
                }
                return;
        }
+       assert(protocol_version != 0);
 
        NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
 
-       pkt << pos << velocity << acceleration << expirationtime
-                       << size << collisiondetection;
-       pkt.putLongString(texture);
-       pkt << vertical;
-       pkt << collision_removal;
-       // This is horrible but required (why are there two ways to serialize pkts?)
-       std::ostringstream os(std::ios_base::binary);
-       animation.serialize(os, protocol_version);
-       pkt.putRawString(os.str());
-       pkt << glow;
-       pkt << object_collision;
+       {
+               // NetworkPacket and iostreams are incompatible...
+               std::ostringstream oss(std::ios_base::binary);
+               p.serialize(oss, protocol_version);
+               pkt.putRawString(oss.str());
+       }
 
        Send(&pkt);
 }
 
 // Adds a ParticleSpawner on peer with peer_id
 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
-       u16 amount, float spawntime, v3f minpos, v3f maxpos,
-       v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
-       float minsize, float maxsize, bool collisiondetection, bool collision_removal,
-       bool object_collision, u16 attached_id, bool vertical, const std::string &texture, u32 id,
-       const struct TileAnimationParams &animation, u8 glow)
+       const ParticleSpawnerParameters &p, u16 attached_id, u32 id)
 {
        if (peer_id == PEER_ID_INEXISTENT) {
-               // This sucks and should be replaced:
                std::vector<session_t> clients = m_clients.getClientIDs();
                for (const session_t client_id : clients) {
                        RemotePlayer *player = m_env->getPlayer(client_id);
                        if (!player)
                                continue;
                        SendAddParticleSpawner(client_id, player->protocol_version,
-                                       amount, spawntime, minpos, maxpos,
-                                       minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
-                                       minsize, maxsize, collisiondetection, collision_removal,
-                                       object_collision, attached_id, vertical, texture, id,
-                                       animation, glow);
+                               p, attached_id, id);
                }
                return;
        }
+       assert(protocol_version != 0);
 
-       NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
+       NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id);
 
-       pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
-                       << minacc << maxacc << minexptime << maxexptime << minsize
-                       << maxsize << collisiondetection;
+       pkt << p.amount << p.time << p.minpos << p.maxpos << p.minvel
+               << p.maxvel << p.minacc << p.maxacc << p.minexptime << p.maxexptime
+               << p.minsize << p.maxsize << p.collisiondetection;
 
-       pkt.putLongString(texture);
+       pkt.putLongString(p.texture);
 
-       pkt << id << vertical;
-       pkt << collision_removal;
-       pkt << attached_id;
-       // This is horrible but required
-       std::ostringstream os(std::ios_base::binary);
-       animation.serialize(os, protocol_version);
-       pkt.putRawString(os.str());
-       pkt << glow;
-       pkt << object_collision;
+       pkt << id << p.vertical << p.collision_removal << attached_id;
+       {
+               std::ostringstream os(std::ios_base::binary);
+               p.animation.serialize(os, protocol_version);
+               pkt.putRawString(os.str());
+       }
+       pkt << p.glow << p.object_collision;
 
        Send(&pkt);
 }
@@ -1604,7 +1585,6 @@ void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
 {
        NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
 
-       // Ugly error in this packet
        pkt << id;
 
        if (peer_id != PEER_ID_INEXISTENT)
@@ -3365,12 +3345,8 @@ void Server::notifyPlayers(const std::wstring &msg)
        SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
 }
 
-void Server::spawnParticle(const std::string &playername, v3f pos,
-       v3f velocity, v3f acceleration,
-       float expirationtime, float size, bool
-       collisiondetection, bool collision_removal, bool object_collision,
-       bool vertical, const std::string &texture,
-       const struct TileAnimationParams &animation, u8 glow)
+void Server::spawnParticle(const std::string &playername,
+       const ParticleParameters &p)
 {
        // m_env will be NULL if the server is initializing
        if (!m_env)
@@ -3386,18 +3362,11 @@ void Server::spawnParticle(const std::string &playername, v3f pos,
                proto_ver = player->protocol_version;
        }
 
-       SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
-                       expirationtime, size, collisiondetection, collision_removal,
-                       object_collision, vertical, texture, animation, glow);
+       SendSpawnParticle(peer_id, proto_ver, p);
 }
 
-u32 Server::addParticleSpawner(u16 amount, float spawntime,
-       v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
-       float minexptime, float maxexptime, float minsize, float maxsize,
-       bool collisiondetection, bool collision_removal, bool object_collision,
-       ServerActiveObject *attached, bool vertical, const std::string &texture,
-       const std::string &playername, const struct TileAnimationParams &animation,
-       u8 glow)
+u32 Server::addParticleSpawner(const ParticleSpawnerParameters &p,
+       ServerActiveObject *attached, const std::string &playername)
 {
        // m_env will be NULL if the server is initializing
        if (!m_env)
@@ -3417,16 +3386,11 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
 
        u32 id;
        if (attached_id == 0)
-               id = m_env->addParticleSpawner(spawntime);
+               id = m_env->addParticleSpawner(p.time);
        else
-               id = m_env->addParticleSpawner(spawntime, attached_id);
-
-       SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
-               minpos, maxpos, minvel, maxvel, minacc, maxacc,
-               minexptime, maxexptime, minsize, maxsize, collisiondetection,
-               collision_removal, object_collision, attached_id, vertical,
-               texture, id, animation, glow);
+               id = m_env->addParticleSpawner(p.time, attached_id);
 
+       SendAddParticleSpawner(peer_id, proto_ver, p, attached_id, id);
        return id;
 }
 
index 7a1de9370d13ac53e4d02a268e42337666cf2d4a..27943cc296cf43f25e71d32935e8408636af4b72 100644 (file)
@@ -27,7 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "content/mods.h"
 #include "inventorymanager.h"
 #include "content/subgames.h"
-#include "tileanimation.h" // struct TileAnimationParams
+#include "tileanimation.h" // TileAnimationParams
+#include "particles.h" // ParticleParams
 #include "network/peerhandler.h"
 #include "network/address.h"
 #include "util/numeric.h"
@@ -226,24 +227,12 @@ public:
 
        void notifyPlayer(const char *name, const std::wstring &msg);
        void notifyPlayers(const std::wstring &msg);
+
        void spawnParticle(const std::string &playername,
-               v3f pos, v3f velocity, v3f acceleration,
-               float expirationtime, float size,
-               bool collisiondetection, bool collision_removal, bool object_collision,
-               bool vertical, const std::string &texture,
-               const struct TileAnimationParams &animation, u8 glow);
-
-       u32 addParticleSpawner(u16 amount, float spawntime,
-               v3f minpos, v3f maxpos,
-               v3f minvel, v3f maxvel,
-               v3f minacc, v3f maxacc,
-               float minexptime, float maxexptime,
-               float minsize, float maxsize,
-               bool collisiondetection, bool collision_removal, bool object_collision,
-               ServerActiveObject *attached,
-               bool vertical, const std::string &texture,
-               const std::string &playername, const struct TileAnimationParams &animation,
-               u8 glow);
+               const ParticleParameters &p);
+
+       u32 addParticleSpawner(const ParticleSpawnerParameters &p,
+               ServerActiveObject *attached, const std::string &playername);
 
        void deleteParticleSpawner(const std::string &playername, u32 id);
 
@@ -453,26 +442,13 @@ private:
 
        // Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all)
        void SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
-               u16 amount, float spawntime,
-               v3f minpos, v3f maxpos,
-               v3f minvel, v3f maxvel,
-               v3f minacc, v3f maxacc,
-               float minexptime, float maxexptime,
-               float minsize, float maxsize,
-               bool collisiondetection, bool collision_removal, bool object_collision,
-               u16 attached_id,
-               bool vertical, const std::string &texture, u32 id,
-               const struct TileAnimationParams &animation, u8 glow);
+               const ParticleSpawnerParameters &p, u16 attached_id, u32 id);
 
        void SendDeleteParticleSpawner(session_t peer_id, u32 id);
 
        // Spawns particle on peer with peer_id (PEER_ID_INEXISTENT == all)
        void SendSpawnParticle(session_t peer_id, u16 protocol_version,
-               v3f pos, v3f velocity, v3f acceleration,
-               float expirationtime, float size,
-               bool collisiondetection, bool collision_removal, bool object_collision,
-               bool vertical, const std::string &texture,
-               const struct TileAnimationParams &animation, u8 glow);
+               const ParticleParameters &p);
 
        void SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao);
        void SendActiveObjectMessages(session_t peer_id, const std::string &datas,