summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/android/native/jni/Android.mk1
-rw-r--r--doc/lua_api.txt30
-rw-r--r--src/client/particles.cpp75
-rw-r--r--src/client/particles.h4
-rw-r--r--src/network/clientpackethandler.cpp10
-rw-r--r--src/particles.cpp10
-rw-r--r--src/particles.h6
-rw-r--r--src/script/lua_api/l_particles.cpp14
-rw-r--r--src/script/lua_api/l_particles_local.cpp14
-rw-r--r--src/server.cpp1
10 files changed, 145 insertions, 20 deletions
diff --git a/build/android/native/jni/Android.mk b/build/android/native/jni/Android.mk
index a5cb099e6..140947e6a 100644
--- a/build/android/native/jni/Android.mk
+++ b/build/android/native/jni/Android.mk
@@ -164,6 +164,7 @@ LOCAL_SRC_FILES := \
../../../src/noise.cpp \
../../../src/objdef.cpp \
../../../src/object_properties.cpp \
+ ../../../src/particles.cpp \
../../../src/pathfinder.cpp \
../../../src/player.cpp \
../../../src/porting.cpp \
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 26061eccb..5b3f61c99 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -7835,6 +7835,8 @@ Used by `minetest.add_particle`.
size = 1,
-- Scales the visual size of the particle texture.
+ -- If `node` is set, size can be set to 0 to spawn a randomly-sized
+ -- particle (just like actual node dig particles).
collisiondetection = false,
-- If true collides with `walkable` nodes and, depending on the
@@ -7853,6 +7855,7 @@ Used by `minetest.add_particle`.
-- If true faces player using y axis only
texture = "image.png",
+ -- The texture of the particle
playername = "singleplayer",
-- Optional, if specified spawns particle only on the player's client
@@ -7863,6 +7866,17 @@ Used by `minetest.add_particle`.
glow = 0
-- Optional, specify particle self-luminescence in darkness.
-- Values 0-14.
+
+ node = {name = "ignore", param2 = 0},
+ -- Optional, if specified the particle will have the same appearance as
+ -- node dig particles for the given node.
+ -- `texture` and `animation` will be ignored if this is set.
+
+ node_tile = 0,
+ -- Optional, only valid in combination with `node`
+ -- If set to a valid number 1-6, specifies the tile from which the
+ -- particle texture is picked.
+ -- Otherwise, the default behavior is used. (currently: any random tile)
}
@@ -7892,7 +7906,9 @@ Used by `minetest.add_particlespawner`.
maxsize = 1,
-- The particles' properties are random values between the min and max
-- values.
- -- pos, velocity, acceleration, expirationtime, size
+ -- applies to: pos, velocity, acceleration, expirationtime, size
+ -- If `node` is set, min and maxsize can be set to 0 to spawn
+ -- randomly-sized particles (just like actual node dig particles).
collisiondetection = false,
-- If true collide with `walkable` nodes and, depending on the
@@ -7915,6 +7931,7 @@ Used by `minetest.add_particlespawner`.
-- If true face player using y axis only
texture = "image.png",
+ -- The texture of the particle
playername = "singleplayer",
-- Optional, if specified spawns particles only on the player's client
@@ -7925,6 +7942,17 @@ Used by `minetest.add_particlespawner`.
glow = 0
-- Optional, specify particle self-luminescence in darkness.
-- Values 0-14.
+
+ node = {name = "ignore", param2 = 0},
+ -- Optional, if specified the particles will have the same appearance as
+ -- node dig particles for the given node.
+ -- `texture` and `animation` will be ignored if this is set.
+
+ node_tile = 0,
+ -- Optional, only valid in combination with `node`
+ -- If set to a valid number 1-6, specifies the tile from which the
+ -- particle texture is picked.
+ -- Otherwise, the default behavior is used. (currently: any random tile)
}
`HTTPRequest` definition
diff --git a/src/client/particles.cpp b/src/client/particles.cpp
index c2e751b4f..c78a3e71a 100644
--- a/src/client/particles.cpp
+++ b/src/client/particles.cpp
@@ -304,18 +304,37 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
}
pp.expirationtime = random_f32(p.minexptime, p.maxexptime);
- pp.size = random_f32(p.minsize, p.maxsize);
-
p.copyCommon(pp);
+ video::ITexture *texture;
+ v2f texpos, texsize;
+ video::SColor color(0xFFFFFFFF);
+
+ if (p.node.getContent() != CONTENT_IGNORE) {
+ const ContentFeatures &f =
+ m_particlemanager->m_env->getGameDef()->ndef()->get(p.node);
+ if (!ParticleManager::getNodeParticleParams(p.node, f, pp, &texture,
+ texpos, texsize, &color, p.node_tile))
+ return;
+ } else {
+ texture = m_texture;
+ texpos = v2f(0.0f, 0.0f);
+ texsize = v2f(1.0f, 1.0f);
+ }
+
+ // Allow keeping default random size
+ if (p.maxsize > 0.0f)
+ pp.size = random_f32(p.minsize, p.maxsize);
+
m_particlemanager->addParticle(new Particle(
m_gamedef,
m_player,
env,
pp,
- m_texture,
- v2f(0.0, 0.0),
- v2f(1.0, 1.0)
+ texture,
+ texpos,
+ texsize,
+ color
));
}
@@ -460,17 +479,35 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
break;
}
case CE_SPAWN_PARTICLE: {
- const ParticleParameters &p = *event->spawn_particle;
- video::ITexture *texture =
- client->tsrc()->getTextureForMesh(p.texture);
+ ParticleParameters &p = *event->spawn_particle;
- Particle *toadd = new Particle(client, player, m_env,
- p,
- texture,
- v2f(0.0, 0.0),
- v2f(1.0, 1.0));
+ video::ITexture *texture;
+ v2f texpos, texsize;
+ video::SColor color(0xFFFFFFFF);
+
+ f32 oldsize = p.size;
+
+ if (p.node.getContent() != CONTENT_IGNORE) {
+ const ContentFeatures &f = m_env->getGameDef()->ndef()->get(p.node);
+ if (!getNodeParticleParams(p.node, f, p, &texture, texpos,
+ texsize, &color, p.node_tile))
+ texture = nullptr;
+ } else {
+ texture = client->tsrc()->getTextureForMesh(p.texture);
+ texpos = v2f(0.0f, 0.0f);
+ texsize = v2f(1.0f, 1.0f);
+ }
+
+ // Allow keeping default random size
+ if (oldsize > 0.0f)
+ p.size = oldsize;
- addParticle(toadd);
+ if (texture) {
+ Particle *toadd = new Particle(client, player, m_env,
+ p, texture, texpos, texsize, color);
+
+ addParticle(toadd);
+ }
delete event->spawn_particle;
break;
@@ -480,15 +517,19 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
}
bool ParticleManager::getNodeParticleParams(const MapNode &n,
- const ContentFeatures &f, ParticleParameters &p,
- video::ITexture **texture, v2f &texpos, v2f &texsize, video::SColor *color)
+ const ContentFeatures &f, ParticleParameters &p, video::ITexture **texture,
+ v2f &texpos, v2f &texsize, video::SColor *color, u8 tilenum)
{
// No particles for "airlike" nodes
if (f.drawtype == NDT_AIRLIKE)
return false;
// Texture
- u8 texid = rand() % 6;
+ u8 texid;
+ if (tilenum > 0 && tilenum <= 6)
+ texid = tilenum - 1;
+ else
+ texid = rand() % 6;
const TileLayer &tile = f.tiles[texid].layers[0];
p.animation.type = TAT_NONE;
diff --git a/src/client/particles.h b/src/client/particles.h
index 7dda0e1b1..2011f0262 100644
--- a/src/client/particles.h
+++ b/src/client/particles.h
@@ -42,7 +42,7 @@ class Particle : public scene::ISceneNode
video::ITexture *texture,
v2f texpos,
v2f texsize,
- video::SColor color = video::SColor(0xFFFFFFFF)
+ video::SColor color
);
~Particle() = default;
@@ -171,7 +171,7 @@ public:
protected:
static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
ParticleParameters &p, video::ITexture **texture, v2f &texpos,
- v2f &texsize, video::SColor *color);
+ v2f &texsize, video::SColor *color, u8 tilenum = 0);
void addParticle(Particle* toadd);
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 054e60c3c..e000acc92 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -1003,6 +1003,16 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
p.glow = readU8(is);
p.object_collision = readU8(is);
+ // This is kinda awful
+ do {
+ u16 tmp_param0 = readU16(is);
+ if (is.eof())
+ break;
+ p.node.param0 = tmp_param0;
+ p.node.param2 = readU8(is);
+ p.node_tile = readU8(is);
+ } while (0);
+
auto event = new ClientEvent();
event->type = CE_ADD_PARTICLESPAWNER;
event->add_particlespawner.p = new ParticleSpawnerParameters(p);
diff --git a/src/particles.cpp b/src/particles.cpp
index 711d189f6..fd81238dc 100644
--- a/src/particles.cpp
+++ b/src/particles.cpp
@@ -34,6 +34,9 @@ void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
animation.serialize(os, 6); /* NOT the protocol ver */
writeU8(os, glow);
writeU8(os, object_collision);
+ writeU16(os, node.param0);
+ writeU8(os, node.param2);
+ writeU8(os, node_tile);
}
void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
@@ -50,4 +53,11 @@ void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
animation.deSerialize(is, 6); /* NOT the protocol ver */
glow = readU8(is);
object_collision = readU8(is);
+ // This is kinda awful
+ u16 tmp_param0 = readU16(is);
+ if (is.eof())
+ return;
+ node.param0 = tmp_param0;
+ node.param2 = readU8(is);
+ node_tile = readU8(is);
}
diff --git a/src/particles.h b/src/particles.h
index 659c1249f..6f518b771 100644
--- a/src/particles.h
+++ b/src/particles.h
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
#include "irrlichttypes_bloated.h"
#include "tileanimation.h"
+#include "mapnode.h"
// This file defines the particle-related structures that both the server and
// client need. The ParticleManager and rendering is in client/particles.h
@@ -34,9 +35,12 @@ struct CommonParticleParams {
std::string texture;
struct TileAnimationParams animation;
u8 glow = 0;
+ MapNode node;
+ u8 node_tile = 0;
CommonParticleParams() {
animation.type = TAT_NONE;
+ node.setContent(CONTENT_IGNORE);
}
/* This helper is useful for copying params from
@@ -49,6 +53,8 @@ struct CommonParticleParams {
to.texture = texture;
to.animation = animation;
to.glow = glow;
+ to.node = node;
+ to.node_tile = node_tile;
}
};
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index 7680aa17b..a51c4fe20 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -111,6 +111,13 @@ int ModApiParticles::l_add_particle(lua_State *L)
p.texture = getstringfield_default(L, 1, "texture", p.texture);
p.glow = getintfield_default(L, 1, "glow", p.glow);
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
+
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
+
playername = getstringfield_default(L, 1, "playername", "");
}
@@ -231,6 +238,13 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
p.texture = getstringfield_default(L, 1, "texture", p.texture);
playername = getstringfield_default(L, 1, "playername", "");
p.glow = getintfield_default(L, 1, "glow", p.glow);
+
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
+
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
}
u32 id = getServer(L)->addParticleSpawner(p, attached, playername);
diff --git a/src/script/lua_api/l_particles_local.cpp b/src/script/lua_api/l_particles_local.cpp
index 9595b2fab..cc68b13a5 100644
--- a/src/script/lua_api/l_particles_local.cpp
+++ b/src/script/lua_api/l_particles_local.cpp
@@ -67,6 +67,13 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L)
p.texture = getstringfield_default(L, 1, "texture", p.texture);
p.glow = getintfield_default(L, 1, "glow", p.glow);
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
+
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
+
ClientEvent *event = new ClientEvent();
event->type = CE_SPAWN_PARTICLE;
event->spawn_particle = new ParticleParameters(p);
@@ -134,6 +141,13 @@ int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
p.texture = getstringfield_default(L, 1, "texture", p.texture);
p.glow = getintfield_default(L, 1, "glow", p.glow);
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
+
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
+
u64 id = getClient(L)->getParticleManager()->generateSpawnerId();
auto event = new ClientEvent();
diff --git a/src/server.cpp b/src/server.cpp
index 68b0131d4..d6e545498 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1577,6 +1577,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
pkt.putRawString(os.str());
}
pkt << p.glow << p.object_collision;
+ pkt << p.node.param0 << p.node.param2 << p.node_tile;
Send(&pkt);
}