aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeija <norrepli@gmail.com>2013-01-23 18:32:02 +0100
committerPilzAdam <pilzadam@minetest.net>2013-03-23 23:16:29 +0100
commite1ff5b13619666e5b987ecf4faaf294400ffd979 (patch)
tree13885f396367c79625a72a4445fe6e81819d92c5
parentab57fdac44bae20e43500b3edd39bac9a0f563c5 (diff)
Allow spawning particles from the server, from lua
Spawn single particles or make use of ParticleSpawner for many randomly spawned particles. Accessible in Lua using minetest.spawn_particle and minetest.add_particlespawner. Increase Protocol Version to 17. Conflicts: src/clientserver.h
-rw-r--r--doc/lua_api.txt31
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/client.cpp83
-rw-r--r--src/client.h34
-rw-r--r--src/clientserver.h44
-rw-r--r--src/game.cpp49
-rw-r--r--src/particles.cpp320
-rw-r--r--src/particles.h72
-rw-r--r--src/scriptapi.cpp4
-rw-r--r--src/scriptapi_particles.cpp143
-rw-r--r--src/scriptapi_particles.h32
-rw-r--r--src/server.cpp232
-rw-r--r--src/server.h69
13 files changed, 1059 insertions, 55 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 3d47785ba..4edca5adb 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1028,6 +1028,37 @@ minetest.get_ban_description(ip_or_name) -> ban description (string)
minetest.ban_player(name) -> ban a player
minetest.unban_player_or_ip(name) -> unban player or IP address
+Particles:
+minetest.add_particle(pos, velocity, acceleration, expirationtime,
+ size, collisiondetection, texture, playername)
+^ Spawn particle at pos with velocity and acceleration
+^ Disappears after expirationtime seconds
+^ collisiondetection: if true collides with physical objects
+^ Uses texture (string)
+^ Playername is optional, if specified spawns particle only on the player's client
+
+minetest.add_particlespawner(amount, time,
+ minpos, maxpos,
+ minvel, maxvel,
+ minacc, maxacc,
+ minexptime, maxexptime,
+ minsize, maxsize,
+ collisiondetection, texture, playername)
+^ Add a particlespawner, an object that spawns an amount of particles over time seconds
+^ The particle's properties are random values in between the boundings:
+^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
+^ minsize/maxsize, minexptime/maxexptime (expirationtime)
+^ collisiondetection: if true uses collisiondetection
+^ Uses texture (string)
+^ Playername is optional, if specified spawns particle only on the player's client
+^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
+^ Returns and id
+
+minetest.delete_particlespawner(id, player)
+^ Delete ParticleSpawner with id (return value from add_particlespawner)
+^ If playername is specified, only deletes on the player's client,
+^ otherwise on all clients
+
Random:
minetest.get_connected_players() -> list of ObjectRefs
minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8c2890f76..8f0cc1ac5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -219,6 +219,7 @@ set(common_SRCS
scriptapi_object.cpp
scriptapi_nodemeta.cpp
scriptapi_inventory.cpp
+ scriptapi_particles.cpp
scriptapi.cpp
script.cpp
log.cpp
diff --git a/src/client.cpp b/src/client.cpp
index 2ccace842..f27f95d98 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -1936,6 +1936,89 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
event.show_formspec.formname = new std::string(formname);
m_client_event_queue.push_back(event);
}
+ else if(command == TOCLIENT_SPAWN_PARTICLE)
+ {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ v3f pos = readV3F1000(is);
+ v3f vel = readV3F1000(is);
+ v3f acc = readV3F1000(is);
+ float expirationtime = readF1000(is);
+ float size = readF1000(is);
+ bool collisiondetection = readU8(is);
+ std::string texture = deSerializeLongString(is);
+
+ ClientEvent event;
+ 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.add_particlespawner.collisiondetection =
+ collisiondetection;
+ event.spawn_particle.texture = new std::string(texture);
+
+ m_client_event_queue.push_back(event);
+ }
+ else if(command == TOCLIENT_ADD_PARTICLESPAWNER)
+ {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ u16 amount = readU16(is);
+ float spawntime = readF1000(is);
+ v3f minpos = readV3F1000(is);
+ v3f maxpos = readV3F1000(is);
+ v3f minvel = readV3F1000(is);
+ v3f maxvel = readV3F1000(is);
+ v3f minacc = readV3F1000(is);
+ v3f maxacc = readV3F1000(is);
+ float minexptime = readF1000(is);
+ float maxexptime = readF1000(is);
+ float minsize = readF1000(is);
+ float maxsize = readF1000(is);
+ bool collisiondetection = readU8(is);
+ std::string texture = deSerializeLongString(is);
+ u32 id = readU32(is);
+
+ ClientEvent event;
+ 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.texture = new std::string(texture);
+ event.add_particlespawner.id = id;
+
+ m_client_event_queue.push_back(event);
+ }
+ else if(command == TOCLIENT_DELETE_PARTICLESPAWNER)
+ {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ u32 id = readU16(is);
+
+ ClientEvent event;
+ event.type = CE_DELETE_PARTICLESPAWNER;
+ event.delete_particlespawner.id = id;
+
+ m_client_event_queue.push_back(event);
+ }
else
{
infostream<<"Client: Ignoring unknown command "
diff --git a/src/client.h b/src/client.h
index 570a6b3b0..d476a1d51 100644
--- a/src/client.h
+++ b/src/client.h
@@ -157,7 +157,10 @@ enum ClientEventType
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
CE_TEXTURES_UPDATED,
- CE_SHOW_FORMSPEC
+ CE_SHOW_FORMSPEC,
+ CE_SPAWN_PARTICLE,
+ CE_ADD_PARTICLESPAWNER,
+ CE_DELETE_PARTICLESPAWNER
};
struct ClientEvent
@@ -185,6 +188,35 @@ struct ClientEvent
} show_formspec;
struct{
} textures_updated;
+ struct{
+ v3f *pos;
+ v3f *vel;
+ v3f *acc;
+ f32 expirationtime;
+ f32 size;
+ bool collisiondetection;
+ std::string *texture;
+ } 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;
+ std::string *texture;
+ u32 id;
+ } add_particlespawner;
+ struct{
+ u32 id;
+ } delete_particlespawner;
};
};
diff --git a/src/clientserver.h b/src/clientserver.h
index 6d830b92b..535fc04d8 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -82,6 +82,9 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
PROTOCOL_VERSION 17:
Serialization format change: include backface_culling flag in TileDef
Added rightclickable field in nodedef
+ TOCLIENT_SPAWN_PARTICLE
+ TOCLIENT_ADD_PARTICLESPAWNER
+ TOCLIENT_DELETE_PARTICLESPAWNER
*/
#define LATEST_PROTOCOL_VERSION 17
@@ -359,6 +362,7 @@ enum ToClientCommand
u8[len] name
[2] serialized inventory
*/
+
TOCLIENT_SHOW_FORMSPEC = 0x44,
/*
[0] u16 command
@@ -384,6 +388,46 @@ enum ToClientCommand
f1000 movement_liquid_sink
f1000 movement_gravity
*/
+
+ TOCLIENT_SPAWN_PARTICLE = 0x46,
+ /*
+ u16 command
+ v3f1000 pos
+ v3f1000 velocity
+ v3f1000 acceleration
+ f1000 expirationtime
+ f1000 size
+ u8 bool collisiondetection
+ u32 len
+ u8[len] texture
+ */
+
+ TOCLIENT_ADD_PARTICLESPAWNER = 0x47,
+ /*
+ u16 command
+ u16 amount
+ f1000 spawntime
+ v3f1000 minpos
+ v3f1000 maxpos
+ v3f1000 minvel
+ v3f1000 maxvel
+ v3f1000 minacc
+ v3f1000 maxacc
+ f1000 minexptime
+ f1000 maxexptime
+ f1000 minsize
+ f1000 maxsize
+ u8 bool collisiondetection
+ u32 len
+ u8[len] texture
+ u32 id
+ */
+
+ TOCLIENT_DELETE_PARTICLESPAWNER = 0x48,
+ /*
+ u16 command
+ u32 id
+ */
};
enum ToServerCommand
diff --git a/src/game.cpp b/src/game.cpp
index 1ae29b13b..58ca654a0 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -2186,6 +2186,47 @@ void the_game(
{
update_wielded_item_trigger = true;
}
+ else if(event.type == CE_SPAWN_PARTICLE)
+ {
+ LocalPlayer* player = client.getEnv().getLocalPlayer();
+ AtlasPointer ap =
+ gamedef->tsrc()->getTexture(*(event.spawn_particle.texture));
+
+ new Particle(gamedef, smgr, player, client.getEnv(),
+ *event.spawn_particle.pos,
+ *event.spawn_particle.vel,
+ *event.spawn_particle.acc,
+ event.spawn_particle.expirationtime,
+ event.spawn_particle.size,
+ event.spawn_particle.collisiondetection, ap);
+ }
+ else if(event.type == CE_ADD_PARTICLESPAWNER)
+ {
+ LocalPlayer* player = client.getEnv().getLocalPlayer();
+ AtlasPointer ap =
+ gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture));
+
+ new ParticleSpawner(gamedef, smgr, 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,
+ ap,
+ event.add_particlespawner.id);
+ }
+ else if(event.type == CE_DELETE_PARTICLESPAWNER)
+ {
+ delete_particlespawner (event.delete_particlespawner.id);
+ }
}
}
@@ -2415,7 +2456,8 @@ void the_game(
const ContentFeatures &features =
client.getNodeDefManager()->get(n);
addPunchingParticles
- (gamedef, smgr, player, nodepos, features.tiles);
+ (gamedef, smgr, player, client.getEnv(),
+ nodepos, features.tiles);
}
}
@@ -2453,7 +2495,8 @@ void the_game(
const ContentFeatures &features =
client.getNodeDefManager()->get(wasnode);
addDiggingParticles
- (gamedef, smgr, player, nodepos, features.tiles);
+ (gamedef, smgr, player, client.getEnv(),
+ nodepos, features.tiles);
}
dig_time = 0;
@@ -2734,6 +2777,7 @@ void the_game(
*/
allparticles_step(dtime, client.getEnv());
+ allparticlespawners_step(dtime, client.getEnv());
/*
Fog
@@ -3220,6 +3264,7 @@ void the_game(
clouds->drop();
if(gui_chat_console)
gui_chat_console->drop();
+ clear_particles ();
/*
Draw a "shutting down" screen, which will be shown while the map
diff --git a/src/particles.cpp b/src/particles.cpp
index fef21d91b..0445d7726 100644
--- a/src/particles.cpp
+++ b/src/particles.cpp
@@ -32,19 +32,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "clientmap.h"
#include "mapnode.h"
+/*
+ Utility
+*/
+
+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);
+}
+
+std::vector<Particle*> all_particles;
+std::map<u32, ParticleSpawner*> all_particlespawners;
+
Particle::Particle(
IGameDef *gamedef,
scene::ISceneManager* smgr,
LocalPlayer *player,
- s32 id,
+ ClientEnvironment &env,
v3f pos,
v3f velocity,
v3f acceleration,
float expirationtime,
float size,
+ bool collisiondetection,
AtlasPointer ap
):
- scene::ISceneNode(smgr->getRootSceneNode(), smgr, id)
+ scene::ISceneNode(smgr->getRootSceneNode(), smgr)
{
// Misc
m_gamedef = gamedef;
@@ -57,7 +72,6 @@ Particle::Particle(
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_material.setTexture(0, ap.atlas);
m_ap = ap;
- m_light = 0;
// Particle related
@@ -68,10 +82,20 @@ Particle::Particle(
m_time = 0;
m_player = player;
m_size = size;
+ m_collisiondetection = collisiondetection;
- // Irrlicht stuff (TODO)
- m_collisionbox = core::aabbox3d<f32>(-size/2,-size/2,-size/2,size/2,size/2,size/2);
+ // Irrlicht stuff
+ m_collisionbox = core::aabbox3d<f32>
+ (-size/2,-size/2,-size/2,size/2,size/2,size/2);
this->setAutomaticCulling(scene::EAC_OFF);
+
+ // Init lighting
+ updateLight(env);
+
+ // Init model
+ updateVertices();
+
+ all_particles.push_back(this);
}
Particle::~Particle()
@@ -82,8 +106,10 @@ void Particle::OnRegisterSceneNode()
{
if (IsVisible)
{
- SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
- SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
+ SceneManager->registerNodeForRendering
+ (this, scene::ESNRP_TRANSPARENT);
+ SceneManager->registerNodeForRendering
+ (this, scene::ESNRP_SOLID);
}
ISceneNode::OnRegisterSceneNode();
@@ -96,45 +122,45 @@ void Particle::render()
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(m_material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
- video::SColor c(255, m_light, m_light, m_light);
-
- video::S3DVertex vertices[4] =
- {
- video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x0(), m_ap.y1()),
- video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y1()),
- video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y0()),
- video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, c ,m_ap.x0(), m_ap.y0()),
- };
-
- for(u16 i=0; i<4; i++)
- {
- vertices[i].Pos.rotateYZBy(m_player->getPitch());
- vertices[i].Pos.rotateXZBy(m_player->getYaw());
- m_box.addInternalPoint(vertices[i].Pos);
- vertices[i].Pos += m_pos*BS;
- }
u16 indices[] = {0,1,2, 2,3,0};
- driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
- video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+ driver->drawVertexPrimitiveList(m_vertices, 4,
+ indices, 2, video::EVT_STANDARD,
+ scene::EPT_TRIANGLES, video::EIT_16BIT);
}
void Particle::step(float dtime, ClientEnvironment &env)
{
- core::aabbox3d<f32> box = m_collisionbox;
- v3f p_pos = m_pos*BS;
- v3f p_velocity = m_velocity*BS;
- v3f p_acceleration = m_acceleration*BS;
- collisionMoveSimple(&env.getClientMap(), m_gamedef,
- BS*0.5, box,
- 0, dtime,
- p_pos, p_velocity, p_acceleration);
- m_pos = p_pos/BS;
- m_velocity = p_velocity/BS;
- m_acceleration = p_acceleration/BS;
m_time += dtime;
+ if (m_collisiondetection)
+ {
+ core::aabbox3d<f32> box = m_collisionbox;
+ v3f p_pos = m_pos*BS;
+ v3f p_velocity = m_velocity*BS;
+ v3f p_acceleration = m_acceleration*BS;
+ collisionMoveSimple(&env.getClientMap(), m_gamedef,
+ BS*0.5, box,
+ 0, dtime,
+ p_pos, p_velocity, p_acceleration);
+ m_pos = p_pos/BS;
+ m_velocity = p_velocity/BS;
+ m_acceleration = p_acceleration/BS;
+ }
+ else
+ {
+ m_velocity += m_acceleration * dtime;
+ m_pos += m_velocity * dtime;
+ }
// Update lighting
+ updateLight(env);
+
+ // Update model
+ updateVertices();
+}
+
+void Particle::updateLight(ClientEnvironment &env)
+{
u8 light = 0;
try{
v3s16 p = v3s16(
@@ -151,11 +177,37 @@ void Particle::step(float dtime, ClientEnvironment &env)
m_light = decode_light(light);
}
-std::vector<Particle*> all_particles;
+void Particle::updateVertices()
+{
+ video::SColor c(255, m_light, m_light, m_light);
+ m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
+ c, m_ap.x0(), m_ap.y1());
+ m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
+ c, m_ap.x1(), m_ap.y1());
+ m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
+ c, m_ap.x1(), m_ap.y0());
+ m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
+ c ,m_ap.x0(), m_ap.y0());
+
+ for(u16 i=0; i<4; i++)
+ {
+ m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
+ m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
+ m_box.addInternalPoint(m_vertices[i].Pos);
+ m_vertices[i].Pos += m_pos*BS;
+ }
+}
+
+
+/*
+ Helpers
+*/
+
void allparticles_step (float dtime, ClientEnvironment &env)
{
- for(std::vector<Particle*>::iterator i = all_particles.begin(); i != all_particles.end();)
+ for(std::vector<Particle*>::iterator i = all_particles.begin();
+ i != all_particles.end();)
{
if ((*i)->get_expired())
{
@@ -171,22 +223,28 @@ void allparticles_step (float dtime, ClientEnvironment &env)
}
}
-void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
+ const TileSpec tiles[])
{
for (u16 j = 0; j < 32; j++) // set the amount of particles here
{
- addNodeParticle(gamedef, smgr, player, pos, tiles);
+ addNodeParticle(gamedef, smgr, player, env, pos, tiles);
}
}
-void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env,
+ v3s16 pos, const TileSpec tiles[])
{
- addNodeParticle(gamedef, smgr, player, pos, tiles);
+ addNodeParticle(gamedef, smgr, player, env, pos, tiles);
}
// add a particle of a node
// used by digging and punching particles
-void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
+ const TileSpec tiles[])
{
// Texture
u8 texid = myrand_range(0,5);
@@ -205,7 +263,10 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
// Physics
- v3f velocity((rand()%100/50.-1)/1.5, rand()%100/35., (rand()%100/50.-1)/1.5);
+ v3f velocity( (rand()%100/50.-1)/1.5,
+ rand()%100/35.,
+ (rand()%100/50.-1)/1.5);
+
v3f acceleration(0,-9,0);
v3f particlepos = v3f(
(f32)pos.X+rand()%100/200.-0.25,
@@ -213,17 +274,180 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
(f32)pos.Z+rand()%100/200.-0.25
);
- Particle *particle = new Particle(
+ new Particle(
gamedef,
smgr,
player,
- 0,
+ env,
particlepos,
velocity,
acceleration,
rand()%100/100., // expiration time
visual_size,
+ true,
ap);
+}
- all_particles.push_back(particle);
+/*
+ ParticleSpawner
+*/
+
+ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, 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, AtlasPointer ap, u32 id)
+{
+ m_gamedef = gamedef;
+ m_smgr = smgr;
+ 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_ap = ap;
+ m_time = 0;
+
+ for (u16 i = 0; i<=m_amount; i++)
+ {
+ float spawntime = (float)rand()/(float)RAND_MAX*m_spawntime;
+ m_spawntimes.push_back(spawntime);
+ }
+
+ all_particlespawners.insert(std::pair<u32, ParticleSpawner*>(id, this));
+}
+
+ParticleSpawner::~ParticleSpawner() {}
+
+void ParticleSpawner::step(float dtime, ClientEnvironment &env)
+{
+ m_time += dtime;
+
+ if (m_spawntime != 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--;
+
+ v3f pos = random_v3f(m_minpos, m_maxpos);
+ v3f vel = random_v3f(m_minvel, m_maxvel);
+ v3f acc = random_v3f(m_minacc, m_maxacc);
+ float exptime = rand()/(float)RAND_MAX
+ *(m_maxexptime-m_minexptime)
+ +m_minexptime;
+ float size = rand()/(float)RAND_MAX
+ *(m_maxsize-m_minsize)
+ +m_minsize;
+
+ new Particle(
+ m_gamedef,
+ m_smgr,
+ m_player,
+ env,
+ pos,
+ vel,
+ acc,
+ exptime,
+ size,
+ m_collisiondetection,
+ m_ap);
+ m_spawntimes.erase(i);
+ }
+ else
+ {
+ i++;
+ }
+ }
+ }
+ else // Spawner exists for an infinity timespan, spawn on a per-second base
+ {
+ for (int i = 0; i <= m_amount; i++)
+ {
+ if (rand()/(float)RAND_MAX < dtime)
+ {
+ v3f pos = random_v3f(m_minpos, m_maxpos);
+ v3f vel = random_v3f(m_minvel, m_maxvel);
+ v3f acc = random_v3f(m_minacc, m_maxacc);
+ float exptime = rand()/(float)RAND_MAX
+ *(m_maxexptime-m_minexptime)
+ +m_minexptime;
+ float size = rand()/(float)RAND_MAX
+ *(m_maxsize-m_minsize)
+ +m_minsize;
+
+ new Particle(
+ m_gamedef,
+ m_smgr,
+ m_player,
+ env,
+ pos,
+ vel,
+ acc,
+ exptime,
+ size,
+ m_collisiondetection,
+ m_ap);
+ }
+ }
+ }
+}
+
+void allparticlespawners_step (float dtime, ClientEnvironment &env)
+{
+ for(std::map<u32, ParticleSpawner*>::iterator i =
+ all_particlespawners.begin();
+ i != all_particlespawners.end();)
+ {
+ if (i->second->get_expired())
+ {
+ delete i->second;
+ all_particlespawners.erase(i++);
+ }
+ else
+ {
+ i->second->step(dtime, env);
+ i++;
+ }
+ }
+}
+
+void delete_particlespawner (u32 id)
+{
+ if (all_particlespawners.find(id) != all_particlespawners.end())
+ {
+ delete all_particlespawners.find(id)->second;
+ all_particlespawners.erase(id);
+ }
+}
+
+void clear_particles ()
+{
+ for(std::map<u32, ParticleSpawner*>::iterator i =
+ all_particlespawners.begin();
+ i != all_particlespawners.end();)
+ {
+ delete i->second;
+ all_particlespawners.erase(i++);
+ }
+
+ for(std::vector<Particle*>::iterator i =
+ all_particles.begin();
+ i != all_particles.end();)
+ {
+ (*i)->remove();
+ delete *i;
+ all_particles.erase(i);
+ }
}
diff --git a/src/particles.h b/src/particles.h
index b317549e7..308da551f 100644
--- a/src/particles.h
+++ b/src/particles.h
@@ -35,12 +35,13 @@ class Particle : public scene::ISceneNode
IGameDef* gamedef,
scene::ISceneManager* mgr,
LocalPlayer *player,
- s32 id,
+ ClientEnvironment &env,
v3f pos,
v3f velocity,
v3f acceleration,
float expirationtime,
float size,
+ bool collisiondetection,
AtlasPointer texture
);
~Particle();
@@ -69,6 +70,10 @@ class Particle : public scene::ISceneNode
{ return m_expiration < m_time; }
private:
+ void updateLight(ClientEnvironment &env);
+ void updateVertices();
+
+ video::S3DVertex m_vertices[4];
float m_time;
float m_expiration;
@@ -87,12 +92,71 @@ private:
float m_size;
AtlasPointer m_ap;
u8 m_light;
+ bool m_collisiondetection;
+};
+
+class ParticleSpawner
+{
+ public:
+ ParticleSpawner(IGameDef* gamedef,
+ scene::ISceneManager *smgr,
+ 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,
+ AtlasPointer ap,
+ u32 id);
+
+ ~ParticleSpawner();
+
+ void step(float dtime, ClientEnvironment &env);
+
+ bool get_expired ()
+ { return (m_amount <= 0) && m_spawntime != 0; }
+
+ private:
+ float m_time;
+ IGameDef *m_gamedef;
+ scene::ISceneManager *m_smgr;
+ 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;
+ AtlasPointer m_ap;
+ std::vector<float> m_spawntimes;
+ bool m_collisiondetection;
};
void allparticles_step (float dtime, ClientEnvironment &env);
+void allparticlespawners_step (float dtime, ClientEnvironment &env);
+
+void delete_particlespawner (u32 id);
+void clear_particles ();
+
+void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
+ const TileSpec tiles[]);
+
+void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
+ const TileSpec tiles[]);
-void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
-void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
-void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
+void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
+ LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
+ const TileSpec tiles[]);
#endif
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 13696eabf..29494ff69 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -44,6 +44,7 @@ extern "C" {
#include "scriptapi_item.h"
#include "scriptapi_content.h"
#include "scriptapi_craft.h"
+#include "scriptapi_particles.h"
/*****************************************************************************/
/* Mod related */
@@ -1089,6 +1090,9 @@ static const struct luaL_Reg minetest_f [] = {
{"get_all_craft_recipes", l_get_all_craft_recipes},
{"rollback_get_last_node_actor", l_rollback_get_last_node_actor},
{"rollback_revert_actions_by", l_rollback_revert_actions_by},
+ {"add_particle", l_add_particle},
+ {"add_particlespawner", l_add_particlespawner},
+ {"delete_particlespawner", l_delete_particlespawner},
{NULL, NULL}
};
diff --git a/src/scriptapi_particles.cpp b/src/scriptapi_particles.cpp
new file mode 100644
index 000000000..dc9b3776e
--- /dev/null
+++ b/src/scriptapi_particles.cpp
@@ -0,0 +1,143 @@
+/*
+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.
+*/
+
+#include "scriptapi.h"
+#include "scriptapi_particles.h"
+#include "server.h"
+#include "script.h"
+#include "scriptapi_types.h"
+#include "scriptapi_common.h"
+
+// add_particle(pos, velocity, acceleration, expirationtime,
+// size, collisiondetection, texture, player)
+// pos/velocity/acceleration = {x=num, y=num, z=num}
+// expirationtime = num (seconds)
+// size = num
+// texture = e.g."default_wood.png"
+int l_add_particle(lua_State *L)
+{
+ // Get server from registry
+ Server *server = get_server(L);
+ // Get parameters
+ v3f pos = check_v3f(L, 1);
+ v3f vel = check_v3f(L, 2);
+ v3f acc = check_v3f(L, 3);
+ float expirationtime = luaL_checknumber(L, 4);
+ float size = luaL_checknumber(L, 5);
+ bool collisiondetection = lua_toboolean(L, 6);
+ std::string texture = luaL_checkstring(L, 7);
+
+ if (lua_gettop(L) == 8) // only spawn for a single player
+ {
+ const char *playername = luaL_checkstring(L, 8);
+ server->spawnParticle(playername,
+ pos, vel, acc, expirationtime,
+ size, collisiondetection, texture);
+ }
+ else // spawn for all players
+ {
+ server->spawnParticleAll(pos, vel, acc,
+ expirationtime, size, collisiondetection, texture);
+ }
+ return 1;
+}
+
+// add_particlespawner(amount, time,
+// minpos, maxpos,
+// minvel, maxvel,
+// minacc, maxacc,
+// minexptime, maxexptime,
+// minsize, maxsize,
+// collisiondetection,
+// texture,
+// player)
+// minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num}
+// minexptime/maxexptime = num (seconds)
+// minsize/maxsize = num
+// collisiondetection = bool
+// texture = e.g."default_wood.png"
+int l_add_particlespawner(lua_State *L)
+{
+ // Get server from registry
+ Server *server = get_server(L);
+ // Get parameters
+ u16 amount = luaL_checknumber(L, 1);
+ float time = luaL_checknumber(L, 2);
+ v3f minpos = check_v3f(L, 3);
+ v3f maxpos = check_v3f(L, 4);
+ v3f minvel = check_v3f(L, 5);
+ v3f maxvel = check_v3f(L, 6);
+ v3f minacc = check_v3f(L, 7);
+ v3f maxacc = check_v3f(L, 8);
+ float minexptime = luaL_checknumber(L, 9);
+ float maxexptime = luaL_checknumber(L, 10);
+ float minsize = luaL_checknumber(L, 11);
+ float maxsize = luaL_checknumber(L, 12);
+ bool collisiondetection = lua_toboolean(L, 13);
+ std::string texture = luaL_checkstring(L, 14);
+
+ if (lua_gettop(L) == 15) // only spawn for a single player
+ {
+ const char *playername = luaL_checkstring(L, 15);
+ u32 id = server->addParticleSpawner(playername,
+ amount, time,
+ minpos, maxpos,
+ minvel, maxvel,
+ minacc, maxacc,
+ minexptime, maxexptime,
+ minsize, maxsize,
+ collisiondetection,
+ texture);
+ lua_pushnumber(L, id);
+ }
+ else // spawn for all players
+ {
+ u32 id = server->addParticleSpawnerAll( amount, time,
+ minpos, maxpos,
+ minvel, maxvel,
+ minacc, maxacc,
+ minexptime, maxexptime,
+ minsize, maxsize,
+ collisiondetection,
+ texture);
+ lua_pushnumber(L, id);
+ }
+ return 1;
+}
+
+// delete_particlespawner(id, player)
+// player (string) is optional
+int l_delete_particlespawner(lua_State *L)
+{
+ // Get server from registry
+ Server *server = get_server(L);
+ // Get parameters
+ u32 id = luaL_checknumber(L, 1);
+
+ if (lua_gettop(L) == 2) // only delete for one player
+ {
+ const char *playername = luaL_checkstring(L, 2);
+ server->deleteParticleSpawner(playername, id);
+ }
+ else // delete for all players
+ {
+ server->deleteParticleSpawnerAll(id);
+ }
+ return 1;
+}
diff --git a/src/scriptapi_particles.h b/src/scriptapi_particles.h
new file mode 100644
index 000000000..4b37d7ce1
--- /dev/null
+++ b/src/scriptapi_particles.h
@@ -0,0 +1,32 @@
+/*
+Minetest-c55
+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.
+*/
+
+#ifndef LUA_PARTICLES_H_
+#define LUA_PARTICLES_H_
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+}
+
+int l_add_particle(lua_State *L);
+int l_add_particlespawner(lua_State *L);
+int l_delete_particlespawner(lua_State *L);
+
+#endif
diff --git a/src/server.cpp b/src/server.cpp
index f77ac6ad9..644f89349 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include <iostream>
#include <queue>
+#include <algorithm>
#include "clientserver.h"
#include "map.h"
#include "jmutexautolock.h"
@@ -3474,6 +3475,132 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, co
m_con.Send(peer_id, 0, data, true);
}
+// Spawns a particle on peer with peer_id
+void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ std::ostringstream os(std::ios_base::binary);
+ writeU16(os, TOCLIENT_SPAWN_PARTICLE);
+ writeV3F1000(os, pos);
+ writeV3F1000(os, velocity);
+ writeV3F1000(os, acceleration);
+ writeF1000(os, expirationtime);
+ writeF1000(os, size);
+ writeU8(os, collisiondetection);
+ os<<serializeLongString(texture);
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+ // Send as reliable
+ m_con.Send(peer_id, 0, data, true);
+}
+
+// Spawns a particle on all peers
+void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
+{
+ for(std::map<u16, RemoteClient*>::iterator
+ i = m_clients.begin();
+ i != m_clients.end(); i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i->second;
+ assert(client->peer_id == i->first);
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+
+ SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
+ expirationtime, size, collisiondetection, texture);
+ }
+}
+
+// Adds a ParticleSpawner on peer with peer_id
+void Server::SendAddParticleSpawner(u16 peer_id, 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, std::string texture, u32 id)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ std::ostringstream os(std::ios_base::binary);
+ writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
+
+ writeU16(os, amount);
+ writeF1000(os, spawntime);
+ writeV3F1000(os, minpos);
+ writeV3F1000(os, maxpos);
+ writeV3F1000(os, minvel);
+ writeV3F1000(os, maxvel);
+ writeV3F1000(os, minacc);
+ writeV3F1000(os, maxacc);
+ writeF1000(os, minexptime);
+ writeF1000(os, maxexptime);
+ writeF1000(os, minsize);
+ writeF1000(os, maxsize);
+ writeU8(os, collisiondetection);
+ os<<serializeLongString(texture);
+ writeU32(os, id);
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+ // Send as reliable
+ m_con.Send(peer_id, 0, data, true);
+}
+
+// Adds a ParticleSpawner on all peers
+void Server::SendAddParticleSpawnerAll(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, std::string texture, u32 id)
+{
+ for(std::map<u16, RemoteClient*>::iterator
+ i = m_clients.begin();
+ i != m_clients.end(); i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i->second;
+ assert(client->peer_id == i->first);
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+
+ SendAddParticleSpawner(client->peer_id, amount, spawntime,
+ minpos, maxpos, minvel, maxvel, minacc, maxacc,
+ minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
+ }
+}
+
+void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ std::ostringstream os(std::ios_base::binary);
+ writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
+
+ writeU16(os, id);
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+ // Send as reliable
+ m_con.Send(peer_id, 0, data, true);
+}
+
+void Server::SendDeleteParticleSpawnerAll(u32 id)
+{
+ for(std::map<u16, RemoteClient*>::iterator
+ i = m_clients.begin();
+ i != m_clients.end(); i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i->second;
+ assert(client->peer_id == i->first);
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+
+ SendDeleteParticleSpawner(client->peer_id, id);
+ }
+}
+
void Server::BroadcastChatMessage(const std::wstring &message)
{
for(std::map<u16, RemoteClient*>::iterator
@@ -4432,6 +4559,111 @@ void Server::notifyPlayers(const std::wstring msg)
BroadcastChatMessage(msg);
}
+void Server::spawnParticle(const char *playername, v3f pos,
+ v3f velocity, v3f acceleration,
+ float expirationtime, float size, bool
+ collisiondetection, std::string texture)
+{
+ Player *player = m_env->getPlayer(playername);
+ if(!player)
+ return;
+ SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
+ expirationtime, size, collisiondetection, texture);
+}
+
+void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
+ float expirationtime, float size,
+ bool collisiondetection, std::string texture)
+{
+ SendSpawnParticleAll(pos, velocity, acceleration,
+ expirationtime, size, collisiondetection, texture);
+}
+
+u32 Server::addParticleSpawner(const char *playername,
+ 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, std::string texture)
+{
+ Player *player = m_env->getPlayer(playername);
+ if(!player)
+ return -1;
+
+ u32 id = 0;
+ for(;;) // look for unused particlespawner id
+ {
+ id++;
+ if (std::find(m_particlespawner_ids.begin(),
+ m_particlespawner_ids.end(), id)
+ == m_particlespawner_ids.end())
+ {
+ m_particlespawner_ids.push_back(id);
+ break;
+ }
+ }
+
+ SendAddParticleSpawner(player->peer_id, amount, spawntime,
+ minpos, maxpos, minvel, maxvel, minacc, maxacc,
+ minexptime, maxexptime, minsize, maxsize,
+ collisiondetection, texture, id);
+
+ return id;
+}
+
+u32 Server::addParticleSpawnerAll(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, std::string texture)
+{
+ u32 id = 0;
+ for(;;) // look for unused particlespawner id
+ {
+ id++;
+ if (std::find(m_particlespawner_ids.begin(),
+ m_particlespawner_ids.end(), id)
+ == m_particlespawner_ids.end())
+ {
+ m_particlespawner_ids.push_back(id);
+ break;
+ }
+ }
+
+ SendAddParticleSpawnerAll(amount, spawntime,
+ minpos, maxpos, minvel, maxvel, minacc, maxacc,
+ minexptime, maxexptime, minsize, maxsize,
+ collisiondetection, texture, id);
+
+ return id;
+}
+
+void Server::deleteParticleSpawner(const char *playername, u32 id)
+{
+ Player *player = m_env->getPlayer(playername);
+ if(!player)
+ return;
+
+ m_particlespawner_ids.erase(
+ std::remove(m_particlespawner_ids.begin(),
+ m_particlespawner_ids.end(), id),
+ m_particlespawner_ids.end());
+ SendDeleteParticleSpawner(player->peer_id, id);
+}
+
+void Server::deleteParticleSpawnerAll(u32 id)
+{
+ m_particlespawner_ids.erase(
+ std::remove(m_particlespawner_ids.begin(),
+ m_particlespawner_ids.end(), id),
+ m_particlespawner_ids.end());
+ SendDeleteParticleSpawnerAll(id);
+}
+
void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
{
m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, blockpos, allow_generate);
diff --git a/src/server.h b/src/server.h
index 63717eaec..813dc9828 100644
--- a/src/server.h
+++ b/src/server.h
@@ -456,6 +456,35 @@ public:
// Envlock and conlock should be locked when calling this
void notifyPlayer(const char *name, const std::wstring msg);
void notifyPlayers(const std::wstring msg);
+ void spawnParticle(const char *playername,
+ v3f pos, v3f velocity, v3f acceleration,
+ float expirationtime, float size,
+ bool collisiondetection, std::string texture);
+
+ void spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
+ float expirationtime, float size,
+ bool collisiondetection, std::string texture);
+
+ u32 addParticleSpawner(const char *playername,
+ 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, std::string texture);
+
+ u32 addParticleSpawnerAll(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, std::string texture);
+
+ void deleteParticleSpawner(const char *playername, u32 id);
+ void deleteParticleSpawnerAll(u32 id);
+
void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
@@ -574,6 +603,41 @@ private:
void sendDetachedInventoryToAll(const std::string &name);
void sendDetachedInventories(u16 peer_id);
+ // Adds a ParticleSpawner on peer with peer_id
+ void SendAddParticleSpawner(u16 peer_id, 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, std::string texture, u32 id);
+
+ // Adds a ParticleSpawner on all peers
+ void SendAddParticleSpawnerAll(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, std::string texture, u32 id);
+
+ // Deletes ParticleSpawner on a single client
+ void SendDeleteParticleSpawner(u16 peer_id, u32 id);
+
+ // Deletes ParticleSpawner on all clients
+ void SendDeleteParticleSpawnerAll(u32 id);
+
+ // Spawns particle on single client
+ void SendSpawnParticle(u16 peer_id,
+ v3f pos, v3f velocity, v3f acceleration,
+ float expirationtime, float size,
+ bool collisiondetection, std::string texture);
+
+ // Spawns particle on all clients
+ void SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
+ float expirationtime, float size,
+ bool collisiondetection, std::string texture);
+
/*
Something random
*/
@@ -790,6 +854,11 @@ private:
*/
// key = name
std::map<std::string, Inventory*> m_detached_inventories;
+
+ /*
+ Particles
+ */
+ std::vector<u32> m_particlespawner_ids;
};
/*