diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 01763fd7..03f2dad3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3885,6 +3885,9 @@ Definition tables size = 1, collisiondetection = false, -- ^ collisiondetection: if true collides with physical objects + collision_removal = false, + -- ^ collision_removal: if true then particle is removed when it collides, + -- ^ requires collisiondetection = true to have any effect vertical = false, -- ^ vertical: if true faces player using y axis only texture = "image.png", @@ -3914,6 +3917,9 @@ Definition tables -- ^ minsize/maxsize, minexptime/maxexptime (expirationtime) collisiondetection = false, -- ^ collisiondetection: if true uses collision detection + collision_removal = false, + -- ^ collision_removal: if true then particle is removed when it collides, + -- ^ requires collisiondetection = true to have any effect vertical = false, -- ^ vertical: if true faces player using y axis only texture = "image.png", diff --git a/src/client.h b/src/client.h index cdadb9d3..a7eb22ad 100644 --- a/src/client.h +++ b/src/client.h @@ -182,6 +182,7 @@ struct ClientEvent f32 expirationtime; f32 size; bool collisiondetection; + bool collision_removal; bool vertical; std::string *texture; } spawn_particle; @@ -199,6 +200,7 @@ struct ClientEvent f32 minsize; f32 maxsize; bool collisiondetection; + bool collision_removal; bool vertical; std::string *texture; u32 id; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 0498f404..48c573da 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -898,8 +898,10 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) bool collisiondetection = readU8(is); std::string texture = deSerializeLongString(is); bool vertical = false; + bool collision_removal = false; try { vertical = readU8(is); + collision_removal = readU8(is); } catch (...) {} ClientEvent event; @@ -910,6 +912,7 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) 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); @@ -942,8 +945,11 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) *pkt >> id; bool vertical = false; + bool collision_removal = false; try { *pkt >> vertical; + *pkt >> collision_removal; + } catch (...) {} ClientEvent event; @@ -961,6 +967,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) 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.vertical = vertical; event.add_particlespawner.texture = new std::string(texture); event.add_particlespawner.id = id; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 177b9768..3a9483ef 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -474,6 +474,7 @@ enum ToClientCommand u8 bool vertical u32 len u8[len] texture + u8 collision_removal */ TOCLIENT_ADD_PARTICLESPAWNER = 0x47, @@ -495,6 +496,7 @@ enum ToClientCommand u32 len u8[len] texture u32 id + u8 collision_removal */ TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY = 0x48, diff --git a/src/particles.cpp b/src/particles.cpp index 525258a2..ccca691d 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -54,6 +54,7 @@ Particle::Particle( float expirationtime, float size, bool collisiondetection, + bool collision_removal, bool vertical, video::ITexture *texture, v2f texpos, @@ -85,6 +86,7 @@ Particle::Particle( m_player = player; m_size = size; m_collisiondetection = collisiondetection; + m_collision_removal = collision_removal; m_vertical = vertical; // Irrlicht stuff @@ -126,20 +128,21 @@ void Particle::render() void Particle::step(float dtime) { m_time += dtime; - if (m_collisiondetection) - { + if (m_collisiondetection) { aabb3f box = m_collisionbox; - v3f p_pos = m_pos*BS; - v3f p_velocity = m_velocity*BS; - collisionMoveSimple(m_env, m_gamedef, - BS*0.5, box, - 0, dtime, - &p_pos, &p_velocity, m_acceleration * BS); - m_pos = p_pos/BS; - m_velocity = p_velocity/BS; - } - else - { + v3f p_pos = m_pos * BS; + v3f p_velocity = m_velocity * BS; + collisionMoveResult r = collisionMoveSimple(m_env, + m_gamedef, BS * 0.5, box, 0, dtime, &p_pos, + &p_velocity, m_acceleration * BS); + if (m_collision_removal && r.collides) { + // force expiration of the particle + m_expiration = -1.0; + } else { + m_pos = p_pos / BS; + m_velocity = p_velocity / BS; + } + } else { m_velocity += m_acceleration * dtime; m_pos += m_velocity * dtime; } @@ -210,8 +213,8 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, 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 vertical, video::ITexture *texture, u32 id, - ParticleManager *p_manager) : + bool collisiondetection, bool collision_removal, bool vertical, + video::ITexture *texture, u32 id, ParticleManager *p_manager) : m_particlemanager(p_manager) { m_gamedef = gamedef; @@ -230,6 +233,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, m_minsize = minsize; m_maxsize = maxsize; m_collisiondetection = collisiondetection; + m_collision_removal = collision_removal; m_vertical = vertical; m_texture = texture; m_time = 0; @@ -277,6 +281,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) exptime, size, m_collisiondetection, + m_collision_removal, m_vertical, m_texture, v2f(0.0, 0.0), @@ -317,6 +322,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) exptime, size, m_collisiondetection, + m_collision_removal, m_vertical, m_texture, v2f(0.0, 0.0), @@ -446,6 +452,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef, event->add_particlespawner.minsize, event->add_particlespawner.maxsize, event->add_particlespawner.collisiondetection, + event->add_particlespawner.collision_removal, event->add_particlespawner.vertical, texture, event->add_particlespawner.id, @@ -480,6 +487,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef, event->spawn_particle.expirationtime, event->spawn_particle.size, event->spawn_particle.collisiondetection, + event->spawn_particle.collision_removal, event->spawn_particle.vertical, texture, v2f(0.0, 0.0), @@ -555,6 +563,7 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s visual_size, true, false, + false, texture, texpos, texsize); diff --git a/src/particles.h b/src/particles.h index dda84385..bc3ca53b 100644 --- a/src/particles.h +++ b/src/particles.h @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., struct ClientEvent; class ParticleManager; +class ClientEnvironment; class Particle : public scene::ISceneNode { @@ -45,6 +46,7 @@ class Particle : public scene::ISceneNode float expirationtime, float size, bool collisiondetection, + bool collision_removal, bool vertical, video::ITexture *texture, v2f texpos, @@ -97,6 +99,7 @@ private: float m_size; u8 m_light; bool m_collisiondetection; + bool m_collision_removal; bool m_vertical; v3s16 m_camera_offset; }; @@ -115,6 +118,7 @@ class ParticleSpawner float minexptime, float maxexptime, float minsize, float maxsize, bool collisiondetection, + bool collision_removal, bool vertical, video::ITexture *texture, u32 id, @@ -148,6 +152,7 @@ class ParticleSpawner video::ITexture *m_texture; std::vector m_spawntimes; bool m_collisiondetection; + bool m_collision_removal; bool m_vertical; }; diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp index f6c1725d..263e3540 100644 --- a/src/script/lua_api/l_particles.cpp +++ b/src/script/lua_api/l_particles.cpp @@ -21,13 +21,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_internal.h" #include "common/c_converter.h" #include "server.h" +#include "particles.h" // add_particle({pos=, velocity=, acceleration=, expirationtime=, -// size=, collisiondetection=, vertical=, texture=, player=}) +// size=, collisiondetection=, collision_removal=, vertical=, +// texture=, player=}) // pos/velocity/acceleration = {x=num, y=num, z=num} // expirationtime = num (seconds) // size = num // collisiondetection = bool +// collision_removal = bool // vertical = bool // texture = e.g."default_wood.png" int ModApiParticles::l_add_particle(lua_State *L) @@ -41,8 +44,8 @@ int ModApiParticles::l_add_particle(lua_State *L) float expirationtime, size; expirationtime = size = 1; - bool collisiondetection, vertical; - collisiondetection = vertical = false; + bool collisiondetection, vertical, collision_removal; + collisiondetection = vertical = collision_removal = false; std::string texture = ""; std::string playername = ""; @@ -94,12 +97,14 @@ int ModApiParticles::l_add_particle(lua_State *L) size = getfloatfield_default(L, 1, "size", 1); collisiondetection = getboolfield_default(L, 1, "collisiondetection", collisiondetection); + collision_removal = getboolfield_default(L, 1, + "collision_removal", collision_removal); vertical = getboolfield_default(L, 1, "vertical", vertical); texture = getstringfield_default(L, 1, "texture", ""); playername = getstringfield_default(L, 1, "playername", ""); } - getServer(L)->spawnParticle(playername, pos, vel, acc, - expirationtime, size, collisiondetection, vertical, texture); + getServer(L)->spawnParticle(playername, pos, vel, acc, expirationtime, size, + collisiondetection, collision_removal, vertical, texture); return 1; } @@ -110,6 +115,7 @@ int ModApiParticles::l_add_particle(lua_State *L) // minexptime=, maxexptime=, // minsize=, maxsize=, // collisiondetection=, +// collision_removal=, // vertical=, // texture=, // player=}) @@ -117,6 +123,7 @@ int ModApiParticles::l_add_particle(lua_State *L) // minexptime/maxexptime = num (seconds) // minsize/maxsize = num // collisiondetection = bool +// collision_removal = bool // vertical = bool // texture = e.g."default_wood.png" int ModApiParticles::l_add_particlespawner(lua_State *L) @@ -129,8 +136,8 @@ int ModApiParticles::l_add_particlespawner(lua_State *L) minpos= maxpos= minvel= maxvel= minacc= maxacc= v3f(0, 0, 0); float time, minexptime, maxexptime, minsize, maxsize; time= minexptime= maxexptime= minsize= maxsize= 1; - bool collisiondetection, vertical; - collisiondetection= vertical= false; + bool collisiondetection, vertical, collision_removal; + collisiondetection = vertical = collision_removal = false; std::string texture = ""; std::string playername = ""; @@ -189,6 +196,8 @@ int ModApiParticles::l_add_particlespawner(lua_State *L) maxsize = getfloatfield_default(L, 1, "maxsize", maxsize); collisiondetection = getboolfield_default(L, 1, "collisiondetection", collisiondetection); + collision_removal = getboolfield_default(L, 1, + "collision_removal", collision_removal); vertical = getboolfield_default(L, 1, "vertical", vertical); texture = getstringfield_default(L, 1, "texture", ""); playername = getstringfield_default(L, 1, "playername", ""); @@ -201,6 +210,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L) minexptime, maxexptime, minsize, maxsize, collisiondetection, + collision_removal, vertical, texture, playername); lua_pushnumber(L, id); diff --git a/src/server.cpp b/src/server.cpp index a3b686c2..ada45dc6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1673,7 +1673,8 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec, // 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, - bool vertical, std::string texture) + bool collision_removal, + bool vertical, const std::string &texture) { DSTACK(FUNCTION_NAME); @@ -1683,6 +1684,7 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat << size << collisiondetection; pkt.putLongString(texture); pkt << vertical; + pkt << collision_removal; if (peer_id != PEER_ID_INEXISTENT) { Send(&pkt); @@ -1695,7 +1697,8 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat // 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, bool vertical, std::string texture, u32 id) + float minsize, float maxsize, bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture, u32 id) { DSTACK(FUNCTION_NAME); @@ -1708,6 +1711,7 @@ void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3 pkt.putLongString(texture); pkt << id << vertical; + pkt << collision_removal; if (peer_id != PEER_ID_INEXISTENT) { Send(&pkt); @@ -3160,7 +3164,8 @@ void Server::notifyPlayers(const std::wstring &msg) void Server::spawnParticle(const std::string &playername, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool - collisiondetection, bool vertical, const std::string &texture) + collisiondetection, bool collision_removal, + bool vertical, const std::string &texture) { // m_env will be NULL if the server is initializing if (!m_env) @@ -3175,13 +3180,15 @@ void Server::spawnParticle(const std::string &playername, v3f pos, } SendSpawnParticle(peer_id, pos, velocity, acceleration, - expirationtime, size, collisiondetection, vertical, texture); + expirationtime, size, collisiondetection, + collision_removal, vertical, texture); } 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 vertical, const std::string &texture, + bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture, const std::string &playername) { // m_env will be NULL if the server is initializing @@ -3200,7 +3207,7 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime, SendAddParticleSpawner(peer_id, amount, spawntime, minpos, maxpos, minvel, maxvel, minacc, maxacc, minexptime, maxexptime, minsize, maxsize, - collisiondetection, vertical, texture, id); + collisiondetection, collision_removal, vertical, texture, id); return id; } diff --git a/src/server.h b/src/server.h index daf51dee..7ee15a46 100644 --- a/src/server.h +++ b/src/server.h @@ -275,7 +275,8 @@ public: void spawnParticle(const std::string &playername, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, - bool collisiondetection, bool vertical, const std::string &texture); + bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture); u32 addParticleSpawner(u16 amount, float spawntime, v3f minpos, v3f maxpos, @@ -283,7 +284,8 @@ public: v3f minacc, v3f maxacc, float minexptime, float maxexptime, float minsize, float maxsize, - bool collisiondetection, bool vertical, const std::string &texture, + bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture, const std::string &playername); void deleteParticleSpawner(const std::string &playername, u32 id); @@ -456,7 +458,8 @@ private: v3f minacc, v3f maxacc, float minexptime, float maxexptime, float minsize, float maxsize, - bool collisiondetection, bool vertical, std::string texture, u32 id); + bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture, u32 id); void SendDeleteParticleSpawner(u16 peer_id, u32 id); @@ -464,7 +467,8 @@ private: void SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, - bool collisiondetection, bool vertical, std::string texture); + bool collisiondetection, bool collision_removal, + bool vertical, const std::string &texture); u32 SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas); void SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable = true);