Attached particle spawners

This commit is contained in:
raymoo 2016-08-04 13:09:21 -07:00 committed by Ner'zhul
parent 0b27a70b29
commit c9e7a27eeb
13 changed files with 131 additions and 36 deletions

@ -4120,6 +4120,8 @@ The Biome API is still in an experimental phase and subject to change.
collision_removal = false, collision_removal = false,
-- ^ collision_removal: if true then particle is removed when it collides, -- ^ collision_removal: if true then particle is removed when it collides,
-- ^ requires collisiondetection = true to have any effect -- ^ requires collisiondetection = true to have any effect
attached = ObjectRef,
-- ^ attached: if defined, makes particle positions relative to this object.
vertical = false, vertical = false,
-- ^ vertical: if true faces player using y axis only -- ^ vertical: if true faces player using y axis only
texture = "image.png", texture = "image.png",

@ -201,6 +201,7 @@ struct ClientEvent
f32 maxsize; f32 maxsize;
bool collisiondetection; bool collisiondetection;
bool collision_removal; bool collision_removal;
u16 attached_id;
bool vertical; bool vertical;
std::string *texture; std::string *texture;
u32 id; u32 id;

@ -156,6 +156,11 @@ LuaEntitySAO::~LuaEntitySAO()
if(m_registered){ if(m_registered){
m_env->getScriptIface()->luaentity_Remove(m_id); m_env->getScriptIface()->luaentity_Remove(m_id);
} }
for (UNORDERED_SET<u32>::iterator it = m_attached_particle_spawners.begin();
it != m_attached_particle_spawners.end(); ++it) {
m_env->deleteParticleSpawner(*it, false);
}
} }
void LuaEntitySAO::addedToEnvironment(u32 dtime_s) void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
@ -817,7 +822,6 @@ PlayerSAO::~PlayerSAO()
{ {
if(m_inventory != &m_player->inventory) if(m_inventory != &m_player->inventory)
delete m_inventory; delete m_inventory;
} }
std::string PlayerSAO::getDescription() std::string PlayerSAO::getDescription()
@ -844,6 +848,10 @@ void PlayerSAO::removingFromEnvironment()
m_player->peer_id = 0; m_player->peer_id = 0;
m_env->savePlayer(m_player); m_env->savePlayer(m_player);
m_env->removePlayer(m_player); m_env->removePlayer(m_player);
for (UNORDERED_SET<u32>::iterator it = m_attached_particle_spawners.begin();
it != m_attached_particle_spawners.end(); ++it) {
m_env->deleteParticleSpawner(*it, false);
}
} }
} }

@ -1518,6 +1518,30 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
return id; return id;
} }
u32 ServerEnvironment::addParticleSpawner(float exptime, u16 attached_id)
{
u32 id = addParticleSpawner(exptime);
m_particle_spawner_attachments[id] = attached_id;
if (ServerActiveObject *obj = getActiveObject(attached_id)) {
obj->attachParticleSpawner(id);
}
return id;
}
void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
{
m_particle_spawners.erase(id);
UNORDERED_MAP<u32, u16>::iterator it = m_particle_spawner_attachments.find(id);
if (it != m_particle_spawner_attachments.end()) {
u16 obj_id = (*it).second;
ServerActiveObject *sao = getActiveObject(obj_id);
if (sao != NULL && remove_from_object) {
sao->detachParticleSpawner(id);
}
m_particle_spawner_attachments.erase(id);
}
}
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
{ {
ActiveObjectMap::iterator n = m_active_objects.find(id); ActiveObjectMap::iterator n = m_active_objects.find(id);

@ -329,7 +329,8 @@ public:
void loadDefaultMeta(); void loadDefaultMeta();
u32 addParticleSpawner(float exptime); u32 addParticleSpawner(float exptime);
void deleteParticleSpawner(u32 id) { m_particle_spawners.erase(id); } u32 addParticleSpawner(float exptime, u16 attached_id);
void deleteParticleSpawner(u32 id, bool remove_from_object = true);
/* /*
External ActiveObject interface External ActiveObject interface
@ -519,6 +520,7 @@ private:
// Particles // Particles
IntervalLimiter m_particle_management_interval; IntervalLimiter m_particle_management_interval;
UNORDERED_MAP<u32, float> m_particle_spawners; UNORDERED_MAP<u32, float> m_particle_spawners;
UNORDERED_MAP<u32, u16> m_particle_spawner_attachments;
}; };
#ifndef SERVER #ifndef SERVER

@ -944,9 +944,11 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
bool vertical = false; bool vertical = false;
bool collision_removal = false; bool collision_removal = false;
u16 attached_id = 0;
try { try {
*pkt >> vertical; *pkt >> vertical;
*pkt >> collision_removal; *pkt >> collision_removal;
*pkt >> attached_id;
} catch (...) {} } catch (...) {}
@ -966,6 +968,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
event.add_particlespawner.maxsize = maxsize; event.add_particlespawner.maxsize = maxsize;
event.add_particlespawner.collisiondetection = collisiondetection; event.add_particlespawner.collisiondetection = collisiondetection;
event.add_particlespawner.collision_removal = collision_removal; event.add_particlespawner.collision_removal = collision_removal;
event.add_particlespawner.attached_id = attached_id;
event.add_particlespawner.vertical = vertical; event.add_particlespawner.vertical = vertical;
event.add_particlespawner.texture = new std::string(texture); event.add_particlespawner.texture = new std::string(texture);
event.add_particlespawner.id = id; event.add_particlespawner.id = id;

@ -213,7 +213,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
u16 amount, float time, u16 amount, float time,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize, float minexptime, float maxexptime, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, bool vertical, bool collisiondetection, bool collision_removal, u16 attached_id, bool vertical,
video::ITexture *texture, u32 id, ParticleManager *p_manager) : video::ITexture *texture, u32 id, ParticleManager *p_manager) :
m_particlemanager(p_manager) m_particlemanager(p_manager)
{ {
@ -234,6 +234,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
m_maxsize = maxsize; m_maxsize = maxsize;
m_collisiondetection = collisiondetection; m_collisiondetection = collisiondetection;
m_collision_removal = collision_removal; m_collision_removal = collision_removal;
m_attached_id = attached_id;
m_vertical = vertical; m_vertical = vertical;
m_texture = texture; m_texture = texture;
m_time = 0; m_time = 0;
@ -251,6 +252,15 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
{ {
m_time += dtime; m_time += dtime;
bool unloaded = false;
v3f attached_offset = v3f(0,0,0);
if (m_attached_id != 0) {
if (ClientActiveObject *attached = env->getActiveObject(m_attached_id))
attached_offset = attached->getPosition() / BS;
else
unloaded = true;
}
if (m_spawntime != 0) // Spawner exists for a predefined timespan if (m_spawntime != 0) // Spawner exists for a predefined timespan
{ {
for(std::vector<float>::iterator i = m_spawntimes.begin(); for(std::vector<float>::iterator i = m_spawntimes.begin();
@ -260,9 +270,16 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
{ {
m_amount--; m_amount--;
v3f pos = random_v3f(m_minpos, m_maxpos); // Pretend to, but don't actually spawn a
// particle if it is attached to an unloaded
// object.
if (!unloaded) {
v3f pos = random_v3f(m_minpos, m_maxpos)
+ attached_offset;
v3f vel = random_v3f(m_minvel, m_maxvel); v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc); v3f acc = random_v3f(m_minacc, m_maxacc);
// Make relative to offest
pos += attached_offset;
float exptime = rand()/(float)RAND_MAX float exptime = rand()/(float)RAND_MAX
*(m_maxexptime-m_minexptime) *(m_maxexptime-m_minexptime)
+m_minexptime; +m_minexptime;
@ -287,6 +304,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
v2f(0.0, 0.0), v2f(0.0, 0.0),
v2f(1.0, 1.0)); v2f(1.0, 1.0));
m_particlemanager->addParticle(toadd); m_particlemanager->addParticle(toadd);
}
i = m_spawntimes.erase(i); i = m_spawntimes.erase(i);
} }
else else
@ -297,11 +315,15 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
} }
else // Spawner exists for an infinity timespan, spawn on a per-second base else // Spawner exists for an infinity timespan, spawn on a per-second base
{ {
// Skip this step if attached to an unloaded object
if (unloaded)
return;
for (int i = 0; i <= m_amount; i++) for (int i = 0; i <= m_amount; i++)
{ {
if (rand()/(float)RAND_MAX < dtime) if (rand()/(float)RAND_MAX < dtime)
{ {
v3f pos = random_v3f(m_minpos, m_maxpos); v3f pos = random_v3f(m_minpos, m_maxpos)
+ attached_offset;
v3f vel = random_v3f(m_minvel, m_maxvel); v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc); v3f acc = random_v3f(m_minacc, m_maxacc);
float exptime = rand()/(float)RAND_MAX float exptime = rand()/(float)RAND_MAX
@ -453,6 +475,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef,
event->add_particlespawner.maxsize, event->add_particlespawner.maxsize,
event->add_particlespawner.collisiondetection, event->add_particlespawner.collisiondetection,
event->add_particlespawner.collision_removal, event->add_particlespawner.collision_removal,
event->add_particlespawner.attached_id,
event->add_particlespawner.vertical, event->add_particlespawner.vertical,
texture, texture,
event->add_particlespawner.id, event->add_particlespawner.id,

@ -119,6 +119,7 @@ class ParticleSpawner
float minsize, float maxsize, float minsize, float maxsize,
bool collisiondetection, bool collisiondetection,
bool collision_removal, bool collision_removal,
u16 attached_id,
bool vertical, bool vertical,
video::ITexture *texture, video::ITexture *texture,
u32 id, u32 id,
@ -154,7 +155,7 @@ class ParticleSpawner
bool m_collisiondetection; bool m_collisiondetection;
bool m_collision_removal; bool m_collision_removal;
bool m_vertical; bool m_vertical;
u16 m_attached_id;
}; };
/** /**

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "lua_api/l_particles.h" #include "lua_api/l_particles.h"
#include "lua_api/l_object.h"
#include "lua_api/l_internal.h" #include "lua_api/l_internal.h"
#include "common/c_converter.h" #include "common/c_converter.h"
#include "server.h" #include "server.h"
@ -138,6 +139,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
time= minexptime= maxexptime= minsize= maxsize= 1; time= minexptime= maxexptime= minsize= maxsize= 1;
bool collisiondetection, vertical, collision_removal; bool collisiondetection, vertical, collision_removal;
collisiondetection = vertical = collision_removal = false; collisiondetection = vertical = collision_removal = false;
ServerActiveObject *attached = NULL;
std::string texture = ""; std::string texture = "";
std::string playername = ""; std::string playername = "";
@ -198,6 +200,14 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
"collisiondetection", collisiondetection); "collisiondetection", collisiondetection);
collision_removal = getboolfield_default(L, 1, collision_removal = getboolfield_default(L, 1,
"collision_removal", collision_removal); "collision_removal", collision_removal);
lua_getfield(L, 1, "attached");
if (!lua_isnil(L, -1)) {
ObjectRef *ref = ObjectRef::checkobject(L, -1);
lua_pop(L, 1);
attached = ObjectRef::getobject(ref);
}
vertical = getboolfield_default(L, 1, "vertical", vertical); vertical = getboolfield_default(L, 1, "vertical", vertical);
texture = getstringfield_default(L, 1, "texture", ""); texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", ""); playername = getstringfield_default(L, 1, "playername", "");
@ -211,6 +221,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
minsize, maxsize, minsize, maxsize,
collisiondetection, collisiondetection,
collision_removal, collision_removal,
attached,
vertical, vertical,
texture, playername); texture, playername);
lua_pushnumber(L, id); lua_pushnumber(L, id);

@ -1678,7 +1678,7 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat
void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos, 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, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
float minsize, float maxsize, bool collisiondetection, bool collision_removal, float minsize, float maxsize, bool collisiondetection, bool collision_removal,
bool vertical, const std::string &texture, u32 id) u16 attached_id, bool vertical, const std::string &texture, u32 id)
{ {
DSTACK(FUNCTION_NAME); DSTACK(FUNCTION_NAME);
@ -1692,6 +1692,7 @@ void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3
pkt << id << vertical; pkt << id << vertical;
pkt << collision_removal; pkt << collision_removal;
pkt << attached_id;
if (peer_id != PEER_ID_INEXISTENT) { if (peer_id != PEER_ID_INEXISTENT) {
Send(&pkt); Send(&pkt);
@ -3156,7 +3157,7 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize, float minexptime, float maxexptime, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, bool collisiondetection, bool collision_removal,
bool vertical, const std::string &texture, ServerActiveObject *attached, bool vertical, const std::string &texture,
const std::string &playername) const std::string &playername)
{ {
// m_env will be NULL if the server is initializing // m_env will be NULL if the server is initializing
@ -3171,11 +3172,19 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
peer_id = player->peer_id; peer_id = player->peer_id;
} }
u32 id = m_env->addParticleSpawner(spawntime); u16 attached_id = attached ? attached->getId() : 0;
u32 id;
if (attached_id == 0)
id = m_env->addParticleSpawner(spawntime);
else
id = m_env->addParticleSpawner(spawntime, attached_id);
SendAddParticleSpawner(peer_id, amount, spawntime, SendAddParticleSpawner(peer_id, amount, spawntime,
minpos, maxpos, minvel, maxvel, minacc, maxacc, minpos, maxpos, minvel, maxvel, minacc, maxacc,
minexptime, maxexptime, minsize, maxsize, minexptime, maxexptime, minsize, maxsize,
collisiondetection, collision_removal, vertical, texture, id); collisiondetection, collision_removal, attached_id, vertical,
texture, id);
return id; return id;
} }

@ -258,6 +258,7 @@ public:
float minexptime, float maxexptime, float minexptime, float maxexptime,
float minsize, float maxsize, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, bool collisiondetection, bool collision_removal,
ServerActiveObject *attached,
bool vertical, const std::string &texture, bool vertical, const std::string &texture,
const std::string &playername); const std::string &playername);
@ -434,6 +435,7 @@ private:
float minexptime, float maxexptime, float minexptime, float maxexptime,
float minsize, float maxsize, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, bool collisiondetection, bool collision_removal,
u16 attached_id,
bool vertical, const std::string &texture, u32 id); bool vertical, const std::string &texture, u32 id);
void SendDeleteParticleSpawner(u16 peer_id, u32 id); void SendDeleteParticleSpawner(u16 peer_id, u32 id);

@ -98,4 +98,3 @@ bool ServerActiveObject::setWieldedItem(const ItemStack &item)
} }
return false; return false;
} }

@ -188,6 +188,15 @@ public:
{ return 0; } { return 0; }
virtual ItemStack getWieldedItem() const; virtual ItemStack getWieldedItem() const;
virtual bool setWieldedItem(const ItemStack &item); virtual bool setWieldedItem(const ItemStack &item);
inline void attachParticleSpawner(u32 id)
{
m_attached_particle_spawners.insert(id);
}
inline void detachParticleSpawner(u32 id)
{
m_attached_particle_spawners.erase(id);
}
/* /*
Number of players which know about this object. Object won't be Number of players which know about this object. Object won't be
@ -242,6 +251,7 @@ protected:
ServerEnvironment *m_env; ServerEnvironment *m_env;
v3f m_base_position; v3f m_base_position;
UNORDERED_SET<u32> m_attached_particle_spawners;
private: private:
// Used for creating objects based on type // Used for creating objects based on type