aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/client/clientevent.h45
-rw-r--r--src/client/particles.cpp333
-rw-r--r--src/client/particles.h58
-rw-r--r--src/network/clientpackethandler.cpp136
-rw-r--r--src/particles.cpp53
-rw-r--r--src/particles.h73
-rw-r--r--src/script/lua_api/l_particles.cpp186
-rw-r--r--src/script/lua_api/l_particles_local.cpp149
-rw-r--r--src/server.cpp106
-rw-r--r--src/server.h42
11 files changed, 502 insertions, 680 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dd68ceec9..3d6d1b0ea 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -427,6 +427,7 @@ set(common_SRCS
noise.cpp
objdef.cpp
object_properties.cpp
+ particles.cpp
pathfinder.cpp
player.cpp
porting.cpp
diff --git a/src/client/clientevent.h b/src/client/clientevent.h
index 7f3984b03..9bd31efce 100644
--- a/src/client/clientevent.h
+++ b/src/client/clientevent.h
@@ -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
{
diff --git a/src/client/particles.cpp b/src/client/particles.cpp
index a0e4e54eb..c2e751b4f 100644
--- a/src/client/particles.cpp
+++ b/src/client/particles.cpp
@@ -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);
+ }
+}
diff --git a/src/client/particles.h b/src/client/particles.h
index e7b8cbe24..7dda0e1b1 100644
--- a/src/client/particles.h
+++ b/src/client/particles.h
@@ -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);
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 7b1b1368c..054e60c3c 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -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
index 000000000..711d189f6
--- /dev/null
+++ b/src/particles.cpp
@@ -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
index 000000000..659c1249f
--- /dev/null
+++ b/src/particles.h
@@ -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
+};
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index 340903ebf..7680aa17b 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -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);
diff --git a/src/script/lua_api/l_particles_local.cpp b/src/script/lua_api/l_particles_local.cpp
index a9bf55665..9595b2fab 100644
--- a/src/script/lua_api/l_particles_local.cpp
+++ b/src/script/lua_api/l_particles_local.cpp
@@ -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);
diff --git a/src/server.cpp b/src/server.cpp
index 92870f972..68b0131d4 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -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;
}
diff --git a/src/server.h b/src/server.h
index 7a1de9370..27943cc29 100644
--- a/src/server.h
+++ b/src/server.h
@@ -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,