Skip to content

Commit

Permalink
Attached particle spawners
Browse files Browse the repository at this point in the history
  • Loading branch information
raymoo authored and nerzhul committed Oct 13, 2016
1 parent 0b27a70 commit c9e7a27
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 37 deletions.
2 changes: 2 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/client.h
Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion src/content_sao.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand All @@ -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);
}
} }
} }


Expand Down
24 changes: 24 additions & 0 deletions src/environment.cpp
Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion src/environment.h
Expand Up @@ -329,7 +329,8 @@ class ServerEnvironment : public Environment
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
Expand Down Expand Up @@ -519,6 +520,7 @@ class ServerEnvironment : public Environment
// 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
Expand Down
3 changes: 3 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -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 (...) {}


Expand All @@ -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;
Expand Down
81 changes: 52 additions & 29 deletions src/particles.cpp
Expand Up @@ -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)
{ {
Expand All @@ -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;
Expand All @@ -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();
Expand All @@ -260,33 +270,41 @@ 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
v3f vel = random_v3f(m_minvel, m_maxvel); // particle if it is attached to an unloaded
v3f acc = random_v3f(m_minacc, m_maxacc); // object.
float exptime = rand()/(float)RAND_MAX if (!unloaded) {
*(m_maxexptime-m_minexptime) v3f pos = random_v3f(m_minpos, m_maxpos)
+m_minexptime; + attached_offset;
float size = rand()/(float)RAND_MAX v3f vel = random_v3f(m_minvel, m_maxvel);
*(m_maxsize-m_minsize) v3f acc = random_v3f(m_minacc, m_maxacc);
+m_minsize; // Make relative to offest

pos += attached_offset;
Particle* toadd = new Particle( float exptime = rand()/(float)RAND_MAX
m_gamedef, *(m_maxexptime-m_minexptime)
m_smgr, +m_minexptime;
m_player, float size = rand()/(float)RAND_MAX
env, *(m_maxsize-m_minsize)
pos, +m_minsize;
vel,
acc, Particle* toadd = new Particle(
exptime, m_gamedef,
size, m_smgr,
m_collisiondetection, m_player,
m_collision_removal, env,
m_vertical, pos,
m_texture, vel,
v2f(0.0, 0.0), acc,
v2f(1.0, 1.0)); exptime,
m_particlemanager->addParticle(toadd); size,
m_collisiondetection,
m_collision_removal,
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
m_particlemanager->addParticle(toadd);
}
i = m_spawntimes.erase(i); i = m_spawntimes.erase(i);
} }
else else
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/particles.h
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}; };


/** /**
Expand Down
11 changes: 11 additions & 0 deletions src/script/lua_api/l_particles.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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 = "";


Expand Down Expand Up @@ -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", "");
Expand All @@ -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);
Expand Down
17 changes: 13 additions & 4 deletions src/server.cpp
Expand Up @@ -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);


Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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;
} }
Expand Down
2 changes: 2 additions & 0 deletions src/server.h
Expand Up @@ -258,6 +258,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
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);


Expand Down Expand Up @@ -434,6 +435,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
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);
Expand Down
1 change: 0 additions & 1 deletion src/serverobject.cpp
Expand Up @@ -98,4 +98,3 @@ bool ServerActiveObject::setWieldedItem(const ItemStack &item)
} }
return false; return false;
} }

10 changes: 10 additions & 0 deletions src/serverobject.h
Expand Up @@ -188,6 +188,15 @@ class ServerActiveObject : public ActiveObject
{ 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
Expand Down Expand Up @@ -242,6 +251,7 @@ class ServerActiveObject : public ActiveObject


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
Expand Down

0 comments on commit c9e7a27

Please sign in to comment.